b2864bb2db5a2b4ad8fa5c8b92ffb621f9fb8a46
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-common.c
1 /*
2  * Bluetooth-frwk
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:  Hocheol Seo <hocheol.seo@samsung.com>
7  *               Girishashok Joshi <girish.joshi@samsung.com>
8  *               Chanyeol Park <chanyeol.park@samsung.com>
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *              http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */
23
24 #include <string.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <sys/types.h>
28 #include <stdlib.h>
29 #include <sys/socket.h>
30
31
32 #include <gio/gunixfdlist.h>
33
34
35 #include "bluetooth-api.h"
36 #include "bluetooth-audio-api.h"
37 #include "bluetooth-hid-api.h"
38 #include "bluetooth-media-control.h"
39 #include "bt-internal-types.h"
40
41 #include "bt-common.h"
42 #include "bt-request-sender.h"
43 #include "bt-event-handler.h"
44
45 static bt_user_info_t user_info[BT_MAX_USER_INFO];
46 static DBusGConnection *system_conn = NULL;
47 static GDBusConnection *system_gdbus_conn = NULL;
48
49 static guint bus_id;
50
51 static char *cookie;
52 static size_t cookie_size;
53
54 static GDBusConnection *system_gconn = NULL;
55
56 GDBusConnection *_bt_gdbus_init_system_gconn(void)
57 {
58         GError *error = NULL;
59
60         if (!g_thread_supported()) {
61                 g_thread_init(NULL);
62         }
63
64         dbus_g_thread_init();
65
66         g_type_init();
67
68         if (system_gconn != NULL)
69                 return system_gconn;
70
71         system_gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
72
73         if (!system_gconn) {
74                 BT_ERR("Unable to connect to dbus: %s", error->message);
75                 g_clear_error(&error);
76         }
77
78         return system_gconn;
79 }
80
81 GDBusConnection *_bt_gdbus_get_system_gconn(void)
82 {
83         GDBusConnection *local_system_gconn = NULL;
84         GError *error = NULL;
85
86         if (system_gconn == NULL) {
87                 system_gconn = _bt_gdbus_init_system_gconn();
88         } else if (g_dbus_connection_is_closed(system_gconn)){
89
90                 local_system_gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
91
92                 if (!local_system_gconn) {
93                         BT_ERR("Unable to connect to dbus: %s", error->message);
94                         g_clear_error(&error);
95                 }
96
97                 system_gconn = local_system_gconn;
98         }
99
100         return system_gconn;
101 }
102
103 void _bt_print_device_address_t(const bluetooth_device_address_t *addr)
104 {
105         BT_DBG("%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", addr->addr[0], addr->addr[1], addr->addr[2],
106                                 addr->addr[3], addr->addr[4], addr->addr[5]);
107 }
108
109 void _bt_set_user_data(int type, void *callback, void *user_data)
110 {
111         user_info[type].cb = callback;
112         user_info[type].user_data = user_data;
113 }
114
115 bt_user_info_t *_bt_get_user_data(int type)
116 {
117         return &user_info[type];
118 }
119
120 void _bt_common_event_cb(int event, int result, void *param,
121                                         void *callback, void *user_data)
122 {
123         bluetooth_event_param_t bt_event = { 0, };
124         bt_event.event = event;
125         bt_event.result = result;
126         bt_event.param_data = param;
127
128         if (callback)
129                 ((bluetooth_cb_func_ptr)callback)(bt_event.event, &bt_event,
130                                         user_data);
131 }
132
133 void _bt_input_event_cb(int event, int result, void *param,
134                                         void *callback, void *user_data)
135 {
136         hid_event_param_t bt_event = { 0, };
137         bt_event.event = event;
138         bt_event.result = result;
139         bt_event.param_data = param;
140
141         if (callback)
142                 ((hid_cb_func_ptr)callback)(bt_event.event, &bt_event,
143                                         user_data);
144 }
145
146 void _bt_headset_event_cb(int event, int result, void *param,
147                                         void *callback, void *user_data)
148 {
149         bt_audio_event_param_t bt_event = { 0, };
150         bt_event.event = event;
151         bt_event.result = result;
152         bt_event.param_data = param;
153
154         if (callback)
155                 ((bt_audio_func_ptr)callback)(bt_event.event, &bt_event,
156                                         user_data);
157 }
158
159 void _bt_hf_event_cb(int event, int result, void *param,
160                                         void *callback, void *user_data)
161 {
162         bt_hf_event_param_t bt_event = { 0, };
163         bt_event.event = event;
164         bt_event.result = result;
165         bt_event.param_data = param;
166
167         if (callback)
168                 ((bt_hf_func_ptr)callback)(bt_event.event, &bt_event,
169                                         user_data);
170 }
171
172
173 void _bt_avrcp_event_cb(int event, int result, void *param,
174                                         void *callback, void *user_data)
175 {
176         media_event_param_t bt_event = { 0, };
177         bt_event.event = event;
178         bt_event.result = result;
179         bt_event.param_data = param;
180
181         if (callback)
182                 ((media_cb_func_ptr)callback)(bt_event.event, &bt_event,
183                                         user_data);
184 }
185
186 void _bt_divide_device_class(bluetooth_device_class_t *device_class,
187                                 unsigned int cod)
188 {
189         ret_if(device_class == NULL);
190
191         device_class->major_class = (unsigned short)(cod & 0x00001F00) >> 8;
192         device_class->minor_class = (unsigned short)((cod & 0x000000FC));
193         device_class->service_class = (unsigned long)((cod & 0x00FF0000));
194
195         if (cod & 0x002000) {
196                 device_class->service_class |=
197                 BLUETOOTH_DEVICE_SERVICE_CLASS_LIMITED_DISCOVERABLE_MODE;
198         }
199 }
200
201 void _bt_convert_addr_string_to_type(unsigned char *addr,
202                                         const char *address)
203 {
204         int i;
205         char *ptr = NULL;
206
207         ret_if(address == NULL);
208         ret_if(addr == NULL);
209
210         for (i = 0; i < BT_ADDRESS_LENGTH_MAX; i++) {
211                 addr[i] = strtol(address, &ptr, 16);
212                 if (ptr[0] != '\0') {
213                         if (ptr[0] != ':')
214                                 return;
215
216                         address = ptr + 1;
217                 }
218         }
219 }
220
221 void _bt_convert_addr_type_to_string(char *address,
222                                 unsigned char *addr)
223 {
224         ret_if(address == NULL);
225         ret_if(addr == NULL);
226
227         g_snprintf(address, BT_ADDRESS_STRING_SIZE,
228                         "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
229                         addr[0], addr[1], addr[2],
230                         addr[3], addr[4], addr[5]);
231 }
232
233 int _bt_copy_utf8_string(char *dest, const char *src, unsigned int length)
234 {
235         int i;
236         const char *p = src;
237         char *next;
238         int count;
239
240         if (dest == NULL || src == NULL)
241                 return BLUETOOTH_ERROR_INVALID_PARAM;
242
243         i = 0;
244         while (*p != '\0' && i < length) {
245                 next = g_utf8_next_char(p);
246                 count = next - p;
247
248                 while (count > 0 && ((i + count) < length)) {
249                         dest[i++] = *p;
250                         p++;
251                         count --;
252                 }
253                 p = next;
254         }
255         return BLUETOOTH_ERROR_NONE;
256 }
257
258 gboolean _bt_utf8_validate(char *name)
259 {
260         BT_DBG("+");
261         gunichar2 *u16;
262         glong items_written = 0;
263
264         if (FALSE == g_utf8_validate(name, -1, NULL))
265                 return FALSE;
266
267         u16 = g_utf8_to_utf16(name, -1, NULL, &items_written, NULL);
268         if (u16 == NULL)
269                 return FALSE;
270
271         g_free(u16);
272
273         if (items_written != g_utf8_strlen(name, -1))
274                 return FALSE;
275
276         BT_DBG("-");
277         return TRUE;
278 }
279
280
281 static GDBusProxy *profile_gproxy;
282 static GDBusConnection *gconn;
283 static int latest_id = -1;
284 #define BT_RFCOMM_ID_MAX 245
285 static gboolean id_used[BT_RFCOMM_ID_MAX];
286 GDBusNodeInfo *new_conn_node;
287
288 static const gchar rfcomm_agent_xml[] =
289 "<node name='/'>"
290 " <interface name='org.bluez.Profile1'>"
291 "     <method name='NewConnection'>"
292 "          <arg type='o' name='object' direction='in'/>"
293 "          <arg type='h' name='fd' direction='in'/>"
294 "          <arg type='a{sv}' name='properties' direction='in'/>"
295 "     </method>"
296 "  </interface>"
297 "</node>";
298
299 /* Remote socket address */
300 struct sockaddr_remote {
301         sa_family_t     family;
302         bluetooth_device_address_t      remote_bdaddr;
303         unsigned char   channel;
304 };
305
306 static void __get_remote_address(int fd, bluetooth_device_address_t *bdaddr)
307 {
308         struct sockaddr_remote address;
309         socklen_t address_len;
310
311         address_len = sizeof(address);
312         if (getpeername(fd, (struct sockaddr *) &address, &address_len) != 0) {
313                 BT_DBG("getpeername failed");
314                 return;
315         }
316
317         memcpy(bdaddr->addr, address.remote_bdaddr.addr,
318                                         BLUETOOTH_ADDRESS_LENGTH);
319 }
320
321 static void __new_connection_method(GDBusConnection *connection,
322                                             const gchar *sender,
323                                             const gchar *object_path,
324                                             const gchar *interface_name,
325                                             const gchar *method_name,
326                                             GVariant *parameters,
327                                             GDBusMethodInvocation *invocation,
328                                             gpointer user_data)
329 {
330         BT_DBG("method %s", method_name);
331         if (g_strcmp0(method_name, "NewConnection") == 0) {
332                 int index;
333                 GDBusMessage *msg;
334                 GUnixFDList *fd_list;
335                 GVariantBuilder *properties;
336                 char *obj_path;
337                 char addr[20];
338                 bluetooth_device_address_t remote_addr, remote_addr1;
339                 bt_new_connection_cb cb = user_data;
340                 int fd;
341
342                 g_variant_get(parameters, "(oha{sv})", &obj_path, &index,
343                                                                 &properties);
344
345                 msg = g_dbus_method_invocation_get_message(invocation);
346                 fd_list = g_dbus_message_get_unix_fd_list(msg);
347                 if (fd_list == NULL) {
348                         GQuark quark = g_quark_from_string("rfcomm-app");
349                         GError *err = g_error_new(quark, 0, "No fd in message");
350                         g_dbus_method_invocation_return_gerror(invocation, err);
351                         g_error_free(err);
352                         return;
353                 }
354
355
356                 fd = g_unix_fd_list_get(fd_list, index, NULL);
357                 if (fd == -1) {
358                         BT_ERR("Invalid fd return");
359                         GQuark quark = g_quark_from_string("rfcomm-app");
360                         GError *err = g_error_new(quark, 0, "Invalid FD return");
361                         g_dbus_method_invocation_return_gerror(invocation, err);
362                         g_error_free(err);
363                         return;
364                 }
365
366                 __get_remote_address(fd, &remote_addr);
367                 _bt_swap_addr(remote_addr1.addr, remote_addr.addr);
368                 _bt_convert_addr_type_to_string(addr, remote_addr1.addr);
369                 BT_INFO("fd: %d, address %s", fd, addr);
370
371                 g_dbus_method_invocation_return_value(invocation, NULL);
372
373                 if (cb)
374                         cb(object_path, fd, &remote_addr1);
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         GError *err = NULL;
441
442         if (gconn == NULL)
443                 gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
444
445         if (!gconn) {
446                 if (err) {
447                         BT_ERR("Unable to connect to dbus: %s", err->message);
448                         g_clear_error(&err);
449                 }
450                 return NULL;
451         }
452
453         return gconn;
454 }
455
456 static GDBusProxy *__bt_gdbus_get_profile_proxy(void)
457 {
458         GDBusConnection *gconn;
459         GError *err = NULL;
460
461         if (profile_gproxy)
462                 return profile_gproxy;
463
464         gconn = __get_gdbus_connection();
465         if (gconn == NULL)
466                 return NULL;
467
468         profile_gproxy = g_dbus_proxy_new_sync(gconn, G_DBUS_PROXY_FLAGS_NONE,
469                                                 NULL, BT_BLUEZ_NAME,
470                                                 "/org/bluez",
471                                                 "org.bluez.ProfileManager1",
472                                                 NULL, &err);
473         if (err) {
474                 BT_ERR("Unable to create proxy: %s", err->message);
475                 g_clear_error(&err);
476         }
477
478         return profile_gproxy;
479 }
480
481 void _bt_unregister_gdbus(int object_id)
482 {
483         GDBusConnection *gconn;
484
485         gconn = __get_gdbus_connection();
486         if (gconn == NULL)
487                 return;
488
489         g_dbus_connection_unregister_object(gconn, object_id);
490 }
491
492 int _bt_register_new_conn(const char *path, bt_new_connection_cb cb)
493 {
494         GDBusConnection *gconn;
495         int id;
496         GError *error = NULL;
497
498         gconn = __get_gdbus_connection();
499         if (gconn == NULL)
500                 return -1;
501
502         if (new_conn_node == NULL)
503                 new_conn_node = _bt_get_gdbus_node(rfcomm_agent_xml);
504
505         if (new_conn_node == NULL)
506                 return -1;
507
508         id = g_dbus_connection_register_object(gconn, path,
509                                                 new_conn_node->interfaces[0],
510                                                 &method_table,
511                                                 cb, NULL, &error);
512         if (id == 0) {
513                 BT_ERR("Failed to register: %s", error->message);
514                 g_error_free(error);
515                 return -1;
516         }
517
518         BT_DBG("NEW CONNECTION ID %d", id);
519
520         return id;
521 }
522
523
524 int _bt_register_profile(bt_register_profile_info_t *info, gboolean use_default_rfcomm)
525 {
526         GVariantBuilder *option_builder;
527         GVariant *ret;
528         GDBusProxy *proxy;
529         GError *err = NULL;
530         int result = BLUETOOTH_ERROR_NONE;
531
532         proxy = __bt_gdbus_get_profile_proxy();
533         if (proxy == NULL) {
534                 BT_ERR("Getting profile proxy failed");
535                 return BLUETOOTH_ERROR_INTERNAL;
536         }
537
538         option_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
539         if (info->authentication)
540                 g_variant_builder_add(option_builder, "{sv}",
541                                                 "RequireAuthentication",
542                                                 g_variant_new_boolean(TRUE));
543         if (info->authorization)
544                 g_variant_builder_add(option_builder, "{sv}",
545                                                 "RequireAuthorization",
546                                                 g_variant_new_boolean(TRUE));
547         if (info->role)
548                 g_variant_builder_add(option_builder, "{sv}",
549                                                 "Role",
550                                                 g_variant_new_string(info->role));
551
552         /* Setting RFCOMM channel to default value 0; would allow bluez to assign
553          * RFCOMM channels based on the availability when two services want
554          * to use the RFCOMM along with SPP. Hence bluez makes sure that no
555          * two services use the same SPP RFCOMM channel. */
556         if (use_default_rfcomm)
557                 g_variant_builder_add(option_builder, "{sv}",
558                                                 "Channel",
559                                                 g_variant_new_uint16(RFCOMM_DEFAULT_PROFILE_CHANNEL));
560         if (info->service)
561                 g_variant_builder_add(option_builder, "{sv}",
562                                                 "Service",
563                                                 g_variant_new_string(info->service));
564
565
566         ret = g_dbus_proxy_call_sync(proxy, "RegisterProfile",
567                                         g_variant_new("(osa{sv})", info->obj_path,
568                                                                 info->uuid,
569                                                                 option_builder),
570                                         G_DBUS_CALL_FLAGS_NONE, -1,
571                                         NULL, &err);
572         if (err) {
573                 BT_ERR("RegisterProfile failed: %s", err->message);
574
575                 if (g_strrstr(err->message, BT_ACCESS_DENIED_MSG))
576                         result = BLUETOOTH_ERROR_ACCESS_DENIED;
577                 else
578                         result = BLUETOOTH_ERROR_INTERNAL;
579
580                 g_clear_error(&err);
581         }
582
583         g_variant_builder_unref(option_builder);
584
585         if (ret)
586                 g_variant_unref(ret);
587
588         return result;
589 }
590
591 int _bt_register_profile_platform(bt_register_profile_info_t *info, gboolean use_default_rfcomm)
592 {
593         GVariantBuilder *option_builder;
594         GVariant *ret;
595         GDBusProxy *proxy;
596         GError *err = NULL;
597         int result = BLUETOOTH_ERROR_NONE;
598
599         proxy = __bt_gdbus_get_profile_proxy();
600         if (proxy == NULL) {
601                 BT_ERR("Getting profile proxy failed");
602                 return BLUETOOTH_ERROR_INTERNAL;
603         }
604
605         option_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
606         if (info->authentication)
607                 g_variant_builder_add(option_builder, "{sv}",
608                                                 "RequireAuthentication",
609                                                 g_variant_new_boolean(TRUE));
610         if (info->authorization)
611                 g_variant_builder_add(option_builder, "{sv}",
612                                                 "RequireAuthorization",
613                                                 g_variant_new_boolean(TRUE));
614         if (info->role)
615                 g_variant_builder_add(option_builder, "{sv}",
616                                                 "Role",
617                                                 g_variant_new_string(info->role));
618
619         /* Setting RFCOMM channel to default value 0; would allow bluez to assign
620          * RFCOMM channels based on the availability when two services want
621          * to use the RFCOMM along with SPP. Hence bluez makes sure that no
622          * two services use the same SPP RFCOMM channel. */
623         if (use_default_rfcomm)
624                 g_variant_builder_add(option_builder, "{sv}",
625                                                 "Channel",
626                                                 g_variant_new_uint16(RFCOMM_DEFAULT_PROFILE_CHANNEL));
627         if (info->service)
628                 g_variant_builder_add(option_builder, "{sv}",
629                                                 "Service",
630                                                 g_variant_new_string(info->service));
631
632
633         ret = g_dbus_proxy_call_sync(proxy, "RegisterProfile1",
634                                         g_variant_new("(osa{sv})", info->obj_path,
635                                                                 info->uuid,
636                                                                 option_builder),
637                                         G_DBUS_CALL_FLAGS_NONE, -1,
638                                         NULL, &err);
639         if (err) {
640                 BT_ERR("RegisterProfile failed: %s", err->message);
641
642                 if (g_strrstr(err->message, BT_ACCESS_DENIED_MSG))
643                         result = BLUETOOTH_ERROR_ACCESS_DENIED;
644                 else
645                         result = BLUETOOTH_ERROR_INTERNAL;
646
647                 g_clear_error(&err);
648         }
649
650         g_variant_builder_unref(option_builder);
651
652         if (ret)
653                 g_variant_unref(ret);
654
655         return result;
656 }
657
658
659 void _bt_unregister_profile(char *path)
660 {
661         GVariant *ret;
662         GDBusProxy *proxy;
663         GError *err = NULL;
664
665         proxy = __bt_gdbus_get_profile_proxy();
666         if (proxy == NULL) {
667                 BT_ERR("Getting profile proxy failed");
668                 return;
669         }
670
671         ret = g_dbus_proxy_call_sync(proxy, "UnregisterProfile",
672                         g_variant_new("(o)", path),
673                         G_DBUS_CALL_FLAGS_NONE, -1,
674                         NULL, &err);
675         if (err) {
676                 BT_ERR("UnregisterProfile failed : %s", err->message);
677                 g_clear_error(&err);
678         }
679
680         if (ret)
681                 g_variant_unref(ret);
682
683         return;
684 }
685
686 GDBusNodeInfo * _bt_get_gdbus_node(const gchar *xml_data)
687 {
688         if (bus_id == 0) {
689                 char *name = g_strdup_printf("org.bt.frwk%d", getpid());
690
691                 bus_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
692                                                 name,
693                                                 G_BUS_NAME_OWNER_FLAGS_NONE,
694                                                 NULL,
695                                                 NULL,
696                                                 NULL,
697                                                 NULL,
698                                                 NULL);
699                 BT_DBG("Got bus id %d", bus_id);
700                 g_free(name);
701         }
702
703         return g_dbus_node_info_new_for_xml(xml_data, NULL);
704 }
705
706 int _bt_connect_profile(char *address, char *uuid, void *cb,
707                                                         gpointer func_data)
708 {
709         char *object_path;
710         DBusGProxy *proxy;
711         DBusGConnection *conn;
712         DBusGProxy *adapter_proxy;
713         GError *error = NULL;
714
715         conn = _bt_get_system_gconn();
716         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
717
718         object_path = _bt_get_device_object_path(address);
719         if (object_path == NULL) {
720                 BT_ERR("No searched device");
721
722                 adapter_proxy = _bt_get_adapter_proxy(conn);
723                 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
724
725                 dbus_g_proxy_call(adapter_proxy, "CreateDevice", &error,
726                         G_TYPE_STRING, address,
727                         G_TYPE_INVALID, G_TYPE_INVALID);
728
729                 if (error != NULL) {
730                         BT_ERR("CreateDevice Fail: %s", error->message);
731                         g_error_free(error);
732                 }
733
734                 object_path = _bt_get_device_object_path(address);
735         }
736         retv_if(object_path == NULL, BLUETOOTH_ERROR_INTERNAL);
737
738
739         proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
740                                 object_path, BT_DEVICE_INTERFACE);
741         g_free(object_path);
742         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
743
744         if (!dbus_g_proxy_begin_call(proxy, "ConnectProfile",
745                         (DBusGProxyCallNotify)cb,
746                         func_data, NULL,
747                         G_TYPE_STRING, uuid,
748                         G_TYPE_INVALID)) {
749                 BT_ERR("Connect Dbus Call Error");
750                 g_object_unref(proxy);
751                 return BLUETOOTH_ERROR_INTERNAL;
752         }
753         return BLUETOOTH_ERROR_NONE;
754 }
755
756 int _bt_discover_services(char *address, char *uuid, void *cb,
757                 gpointer func_data)
758 {
759         char *object_path;
760         DBusGProxy *proxy;
761         DBusGConnection *conn;
762         DBusGProxy *adapter_proxy;
763         GError *error = NULL;
764
765         int timeout = 10000;
766         BT_DBG("+");
767         conn = _bt_get_system_gconn();
768         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
769
770         object_path = _bt_get_device_object_path(address);
771         if (object_path == NULL) {
772                 BT_ERR("No searched device");
773
774                 adapter_proxy = _bt_get_adapter_proxy(conn);
775                 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
776
777                 dbus_g_proxy_call(adapter_proxy, "CreateDevice", &error,
778                         G_TYPE_STRING, address,
779                         G_TYPE_INVALID, G_TYPE_INVALID);
780
781                 if (error != NULL) {
782                         BT_ERR("CreateDevice Fail: %s", error->message);
783                         g_error_free(error);
784                 }
785
786                 object_path = _bt_get_device_object_path(address);
787         }
788         retv_if(object_path == NULL, BLUETOOTH_ERROR_INTERNAL);
789
790         proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
791                                 object_path, BT_DEVICE_INTERFACE);
792         g_free(object_path);
793         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
794
795         if (!dbus_g_proxy_begin_call_with_timeout(proxy, "DiscoverServices",
796                         (DBusGProxyCallNotify)cb,
797                         func_data, NULL, timeout,
798                         G_TYPE_STRING, uuid,
799                         G_TYPE_INVALID)) {
800                 BT_ERR("Error: While calling DiscoverServices");
801                 g_object_unref(proxy);
802                 return BLUETOOTH_ERROR_INTERNAL;
803         }
804         BT_DBG("-");
805         return BLUETOOTH_ERROR_NONE;
806 }
807
808 int _bt_cancel_discovers(char *address)
809 {
810         char *object_path;
811         DBusGProxy *proxy;
812         DBusGConnection *conn;
813         BT_DBG("+");
814         conn = _bt_get_system_gconn();
815         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
816
817         object_path = _bt_get_device_object_path(address);
818         retv_if(object_path == NULL, BLUETOOTH_ERROR_INTERNAL);
819
820         proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
821                                 object_path, BT_DEVICE_INTERFACE);
822         g_free(object_path);
823         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
824         if (!dbus_g_proxy_call(proxy,
825                         "CancelDiscovery",
826                         NULL,
827                         G_TYPE_INVALID, G_TYPE_INVALID)) {
828                 BT_ERR("Error: while CancelDiscovery");
829                 g_object_unref(proxy);
830                 return BLUETOOTH_ERROR_INTERNAL;
831         }
832         g_object_unref(proxy);
833         BT_DBG("-");
834         return BLUETOOTH_ERROR_NONE;
835 }
836
837 int _bt_discover_service_uuids(char *address, char *remote_uuid)
838 {
839         char *object_path;
840         DBusGProxy *proxy;
841         DBusGConnection *conn;
842         GHashTable *hash = NULL;
843         GValue *value;
844         char **uuid_value;
845         int i =0;
846         int result = BLUETOOTH_ERROR_INTERNAL;
847         retv_if(remote_uuid == NULL, BLUETOOTH_ERROR_INTERNAL);
848
849         conn = _bt_get_system_gconn();
850         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
851
852         object_path = _bt_get_device_object_path(address);
853         retv_if(object_path == NULL, BLUETOOTH_ERROR_INTERNAL);
854
855         proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
856                                 object_path, BT_PROPERTIES_INTERFACE);
857         g_free(object_path);
858
859         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
860
861         if (!dbus_g_proxy_call(proxy, "GetAll", NULL,
862                         G_TYPE_STRING, BT_DEVICE_INTERFACE,
863                         G_TYPE_INVALID,
864                         dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
865                         G_TYPE_VALUE), &hash, G_TYPE_INVALID)) {
866                         BT_ERR("Dbus error while GetAll");
867                         g_object_unref(proxy);
868                         return BLUETOOTH_ERROR_INTERNAL;
869         }
870         g_object_unref(proxy);
871         BT_DBG("Remote uuids %s", remote_uuid);
872         value = g_hash_table_lookup(hash, "UUIDs");
873         if (value == NULL) {
874                 BT_ERR("No uuids found");
875                 goto done;
876         }
877
878         uuid_value = g_value_get_boxed(value);
879         if(uuid_value == NULL) {
880                 BT_ERR("Error: while obtaining uuids");
881                 goto done;
882         }
883
884         for (i = 0; uuid_value[i] != NULL; i++) {
885                 BT_DBG("Remote uuids %s", uuid_value[i]);
886                 if (strcasecmp(uuid_value[i], remote_uuid) == 0) {
887                         result = BLUETOOTH_ERROR_NONE;
888                         goto done;
889                 }
890         }
891         BT_INFO("Specified uuid not found on remote device");
892 done:
893         if (hash)
894                 g_hash_table_destroy(hash);
895
896         return result;
897 }
898
899 int _bt_disconnect_profile(char *address, char *uuid, void *cb,
900                                                         gpointer func_data)
901 {
902         char *object_path;
903         DBusGProxy *proxy;
904         DBusGConnection *conn;
905
906         conn = _bt_get_system_gconn();
907         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
908
909         object_path = _bt_get_device_object_path(address);
910         retv_if(object_path == NULL, BLUETOOTH_ERROR_INTERNAL);
911
912
913         proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
914                                 object_path, BT_DEVICE_INTERFACE);
915         g_free(object_path);
916         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
917
918         if (!dbus_g_proxy_begin_call(proxy, "DisconnectProfile",
919                         (DBusGProxyCallNotify)cb,
920                         func_data, NULL,
921                         G_TYPE_STRING, uuid,
922                         G_TYPE_INVALID)) {
923                 BT_ERR("Connect Dbus Call Error");
924                 g_object_unref(proxy);
925                 return BLUETOOTH_ERROR_INTERNAL;
926         }
927         return BLUETOOTH_ERROR_NONE;
928 }
929
930 int _bt_get_adapter_path(GDBusConnection *conn, char *path)
931 {
932         GError *err = NULL;
933         GDBusProxy *manager_proxy = NULL;
934         GVariant *result = NULL;
935         char *adapter_path = NULL;
936
937         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
938
939         manager_proxy =  g_dbus_proxy_new_sync(conn,
940                         G_DBUS_PROXY_FLAGS_NONE, NULL,
941                         BT_BLUEZ_NAME,
942                         BT_MANAGER_PATH,
943                         BT_MANAGER_INTERFACE,
944                         NULL, &err);
945
946         if (!manager_proxy) {
947                 BT_ERR("Unable to create proxy: %s", err->message);
948                 goto fail;
949         }
950
951         result = g_dbus_proxy_call_sync(manager_proxy, "DefaultAdapter", NULL,
952                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
953         if (!result) {
954                 if (err != NULL)
955                         BT_ERR("Fail to get DefaultAdapter (Error: %s)", err->message);
956                 else
957                         BT_ERR("Fail to get DefaultAdapter");
958
959                 goto fail;
960         }
961
962         if (g_strcmp0(g_variant_get_type_string(result), "(o)")) {
963                 BT_ERR("Incorrect result\n");
964                 goto fail;
965         }
966
967         g_variant_get(result, "(&o)", &adapter_path);
968
969         if (adapter_path == NULL ||
970                 strlen(adapter_path) >= BT_ADAPTER_OBJECT_PATH_MAX) {
971                 BT_ERR("Adapter path is inproper\n");
972                 goto fail;
973         }
974
975         if (path)
976                 g_strlcpy(path, adapter_path, BT_ADAPTER_OBJECT_PATH_MAX);
977
978         g_variant_unref(result);
979         g_object_unref(manager_proxy);
980
981         return BLUETOOTH_ERROR_NONE;
982
983 fail:
984         g_clear_error(&err);
985
986         if (result)
987                 g_variant_unref(result);
988
989         if (manager_proxy)
990                 g_object_unref(manager_proxy);
991
992         return BLUETOOTH_ERROR_INTERNAL;
993
994 }
995
996 void _bt_convert_device_path_to_address(const char *device_path,
997                                                 char *device_address)
998 {
999         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1000         char *dev_addr;
1001
1002         ret_if(device_path == NULL);
1003         ret_if(device_address == NULL);
1004
1005         dev_addr = strstr(device_path, "dev_");
1006         if (dev_addr != NULL) {
1007                 char *pos = NULL;
1008                 dev_addr += 4;
1009                 g_strlcpy(address, dev_addr, sizeof(address));
1010
1011                 while ((pos = strchr(address, '_')) != NULL) {
1012                         *pos = ':';
1013                 }
1014
1015                 g_strlcpy(device_address, address, BT_ADDRESS_STRING_SIZE);
1016         }
1017 }
1018
1019 static char *__bt_extract_adapter_path(DBusMessageIter *msg_iter)
1020 {
1021         char *object_path = NULL;
1022         DBusMessageIter value_iter;
1023
1024         /* Parse the signature:  oa{sa{sv}}} */
1025         retv_if(dbus_message_iter_get_arg_type(msg_iter) !=
1026                                 DBUS_TYPE_OBJECT_PATH, NULL);
1027
1028         dbus_message_iter_get_basic(msg_iter, &object_path);
1029         retv_if(object_path == NULL, NULL);
1030
1031         /* object array (oa) */
1032         retv_if(dbus_message_iter_next(msg_iter) == FALSE, NULL);
1033         retv_if(dbus_message_iter_get_arg_type(msg_iter) !=
1034                                 DBUS_TYPE_ARRAY, NULL);
1035
1036         dbus_message_iter_recurse(msg_iter, &value_iter);
1037
1038         /* string array (sa) */
1039         while (dbus_message_iter_get_arg_type(&value_iter) ==
1040                                         DBUS_TYPE_DICT_ENTRY) {
1041                 char *interface_name = NULL;
1042                 DBusMessageIter interface_iter;
1043
1044                 dbus_message_iter_recurse(&value_iter, &interface_iter);
1045
1046                 retv_if(dbus_message_iter_get_arg_type(&interface_iter) !=
1047                         DBUS_TYPE_STRING, NULL);
1048
1049                 dbus_message_iter_get_basic(&interface_iter, &interface_name);
1050
1051                 if (g_strcmp0(interface_name, "org.bluez.Adapter1") == 0) {
1052                         /* Tizen don't allow the multi-adapter */
1053                         BT_DBG("Found an adapter: %s", object_path);
1054                         return g_strdup(object_path);
1055                 }
1056
1057                 dbus_message_iter_next(&value_iter);
1058         }
1059
1060         return NULL;
1061 }
1062
1063 static char *__bt_extract_device_path(DBusMessageIter *msg_iter, char *address)
1064 {
1065         char *object_path = NULL;
1066         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
1067
1068         /* Parse the signature:  oa{sa{sv}}} */
1069         retv_if(dbus_message_iter_get_arg_type(msg_iter) !=
1070                                 DBUS_TYPE_OBJECT_PATH, NULL);
1071
1072         dbus_message_iter_get_basic(msg_iter, &object_path);
1073         retv_if(object_path == NULL, NULL);
1074
1075         _bt_convert_device_path_to_address(object_path, device_address);
1076
1077         if (g_strcmp0(address, device_address) == 0) {
1078                 return g_strdup(object_path);
1079         }
1080
1081         return NULL;
1082 }
1083
1084 char *_bt_get_device_object_path(char *address)
1085 {
1086         DBusMessage *msg;
1087         DBusMessage *reply;
1088         DBusMessageIter reply_iter;
1089         DBusMessageIter value_iter;
1090         DBusError err;
1091         DBusConnection *conn;
1092         char *object_path = NULL;
1093
1094         conn = _bt_get_system_conn();
1095         retv_if(conn == NULL, NULL);
1096
1097         msg = dbus_message_new_method_call(BT_BLUEZ_NAME, BT_MANAGER_PATH,
1098                                                 BT_MANAGER_INTERFACE,
1099                                                 "GetManagedObjects");
1100
1101         retv_if(msg == NULL, NULL);
1102
1103         /* Synchronous call */
1104         dbus_error_init(&err);
1105         reply = dbus_connection_send_with_reply_and_block(
1106                                         conn, msg,
1107                                         -1, &err);
1108         dbus_message_unref(msg);
1109
1110         if (!reply) {
1111                 BT_ERR("Can't get managed objects");
1112
1113                 if (dbus_error_is_set(&err)) {
1114                         BT_ERR("%s", err.message);
1115                         dbus_error_free(&err);
1116                 }
1117                 return NULL;
1118         }
1119
1120         if (dbus_message_iter_init(reply, &reply_iter) == FALSE) {
1121             BT_ERR("Fail to iterate the reply");
1122             dbus_message_unref(reply);
1123             return NULL;
1124         }
1125
1126         dbus_message_iter_recurse(&reply_iter, &value_iter);
1127
1128         /* signature of GetManagedObjects:  a{oa{sa{sv}}} */
1129         while (dbus_message_iter_get_arg_type(&value_iter) ==
1130                                                 DBUS_TYPE_DICT_ENTRY) {
1131                 DBusMessageIter msg_iter;
1132
1133                 dbus_message_iter_recurse(&value_iter, &msg_iter);
1134
1135                 object_path = __bt_extract_device_path(&msg_iter, address);
1136                 if (object_path != NULL) {
1137                         BT_DBG("Found the device path %s", object_path);
1138                         break;
1139                 }
1140
1141                 dbus_message_iter_next(&value_iter);
1142         }
1143
1144         dbus_message_unref(reply);
1145
1146         return object_path;
1147 }
1148
1149
1150 DBusGProxy *_bt_get_adapter_proxy(DBusGConnection *conn)
1151 {
1152         DBusGProxy *adapter_proxy = NULL;
1153
1154         retv_if(conn == NULL, NULL);
1155
1156         adapter_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
1157                         BT_BLUEZ_HCI_PATH, BT_PROPERTIES_INTERFACE);
1158
1159         return adapter_proxy;
1160 }
1161
1162 void _bt_device_path_to_address(const char *device_path, char *device_address)
1163 {
1164         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1165         char *dev_addr = NULL;
1166
1167         if (!device_path || !device_address)
1168                 return;
1169
1170         dev_addr = strstr(device_path, "dev_");
1171         if (dev_addr != NULL) {
1172                 char *pos = NULL;
1173                 dev_addr += 4;
1174                 g_strlcpy(address, dev_addr, sizeof(address));
1175
1176                 while ((pos = strchr(address, '_')) != NULL) {
1177                         *pos = ':';
1178                 }
1179
1180                 g_strlcpy(device_address, address, BT_ADDRESS_STRING_SIZE);
1181         }
1182 }
1183
1184 DBusGConnection *__bt_init_system_gconn(void)
1185 {
1186         g_type_init();
1187
1188         if (system_conn == NULL)
1189                 system_conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL);
1190
1191         return system_conn;
1192 }
1193
1194 DBusGConnection *_bt_get_system_gconn(void)
1195 {
1196         return (system_conn) ? system_conn : __bt_init_system_gconn();
1197 }
1198
1199 GDBusConnection *_bt_init_system_gdbus_conn(void)
1200 {
1201         g_type_init();
1202         GError *error = NULL;
1203         if (system_gdbus_conn == NULL) {
1204                 system_gdbus_conn =
1205                 g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
1206                 if (error) {
1207                         BT_ERR("GDBus connection Error : %s \n",
1208                                 error->message);
1209                         g_clear_error(&error);
1210                         return NULL;
1211                 }
1212         }
1213         return system_gdbus_conn;
1214 }
1215
1216 DBusConnection *_bt_get_system_conn(void)
1217 {
1218         DBusGConnection *g_conn;
1219
1220         if (system_conn == NULL) {
1221                 g_conn = __bt_init_system_gconn();
1222         } else {
1223                 g_conn = system_conn;
1224         }
1225
1226         retv_if(g_conn == NULL, NULL);
1227
1228         return dbus_g_connection_get_connection(g_conn);
1229 }
1230
1231 int _bt_register_osp_server_in_agent(int type, char *uuid, char *path, int fd)
1232 {
1233         int ret;
1234         char uuid_str[BLUETOOTH_UUID_STRING_MAX] = { 0, };
1235         char path_str[BLUETOOTH_PATH_STRING] = { 0, };
1236
1237         BT_DBG("+");
1238         BT_INIT_PARAMS();
1239         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1240
1241         g_array_append_vals(in_param1, &type, sizeof(int));
1242         g_strlcpy(uuid_str, uuid, sizeof(uuid_str));
1243         g_array_append_vals(in_param2, &uuid_str, BLUETOOTH_UUID_STRING_MAX);
1244         g_strlcpy(path_str, path, sizeof(path_str));
1245         g_array_append_vals(in_param3, &path_str, BLUETOOTH_PATH_STRING);
1246         g_array_append_vals(in_param4, &fd, sizeof(int));
1247
1248         ret =  _bt_send_request(BT_AGENT_SERVICE, BT_SET_AUTHORIZATION,
1249                 in_param1, in_param2, in_param3, in_param4, &out_param);
1250
1251         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1252         BT_DBG("-");
1253         return ret;
1254 }
1255
1256 int _bt_unregister_osp_server_in_agent(int type, char *uuid)
1257 {
1258         int ret;
1259         char uuid_str[BLUETOOTH_UUID_STRING_MAX] = { 0, };
1260         char path_str[BLUETOOTH_PATH_STRING] = { 0, };
1261
1262         BT_DBG("+");
1263         BT_INIT_PARAMS();
1264         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1265
1266         g_array_append_vals(in_param1, &type, sizeof(int));
1267         g_strlcpy(uuid_str, uuid, sizeof(uuid_str));
1268         g_array_append_vals(in_param2, &uuid_str, BLUETOOTH_UUID_STRING_MAX);
1269
1270         ret =  _bt_send_request(BT_AGENT_SERVICE, BT_UNSET_AUTHORIZATION,
1271                 in_param1, in_param2, in_param3, in_param4, &out_param);
1272
1273         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1274         BT_DBG("-");
1275         return ret;
1276 }
1277
1278 int _bt_check_privilege(int service_type, int service_function)
1279 {
1280         int result;
1281
1282         BT_INIT_PARAMS();
1283         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1284
1285         result = _bt_send_request(service_type, service_function,
1286                 in_param1, in_param2, in_param3, in_param4, &out_param);
1287
1288         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1289
1290         return result;
1291 }
1292
1293 GVariant *_bt_get_managed_objects(void)
1294 {
1295         GDBusConnection *g_conn;
1296         GDBusProxy *manager_proxy = NULL;
1297         GVariant *result = NULL;
1298         GError *error = NULL;
1299
1300         BT_DBG("+");
1301
1302         g_conn = _bt_gdbus_get_system_gconn();
1303         retv_if(g_conn == NULL, NULL);
1304
1305         manager_proxy = g_dbus_proxy_new_sync(g_conn,
1306                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1307                         BT_BLUEZ_NAME,
1308                         BT_MANAGER_PATH,
1309                         BT_MANAGER_INTERFACE,
1310                         NULL, &error);
1311
1312         if (error) {
1313                 BT_ERR("Unable to create proxy: %s", error->message);
1314                 g_clear_error(&error);
1315                 return NULL;
1316         }
1317
1318         result = g_dbus_proxy_call_sync (manager_proxy,
1319                         "GetManagedObjects", NULL,
1320                         G_DBUS_CALL_FLAGS_NONE, -1,
1321                         NULL, &error);
1322
1323         if (error) {
1324                 BT_ERR("Fail to get ManagedObjects (Error: %s)", error->message);
1325                 g_clear_error(&error);
1326         }
1327
1328         g_object_unref(manager_proxy);
1329
1330         BT_DBG("-");
1331         return result;
1332 }
1333
1334 BT_EXPORT_API int bluetooth_is_supported(void)
1335 {
1336         int is_supported = 0;
1337         int len = 0;
1338         int fd = -1;
1339         rfkill_event event;
1340
1341         fd = open(RFKILL_NODE, O_RDONLY);
1342         if (fd < 0) {
1343                 BT_ERR("Fail to open RFKILL node");
1344                 return BLUETOOTH_ERROR_INTERNAL;
1345         }
1346
1347         if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
1348                 BT_ERR("Fail to set RFKILL node to non-blocking");
1349                 close(fd);
1350                 return BLUETOOTH_ERROR_INTERNAL;
1351         }
1352
1353         while (1) {
1354                 len = read(fd, &event, sizeof(event));
1355                 if (len < 0) {
1356                         BT_ERR("Fail to read events");
1357                         break;
1358                 }
1359
1360                 if (len != RFKILL_EVENT_SIZE) {
1361                         BT_ERR("The size is wrong\n");
1362                         continue;
1363                 }
1364
1365                 if (event.type == RFKILL_TYPE_BLUETOOTH) {
1366                         is_supported = 1;
1367                         break;
1368                 }
1369         }
1370
1371         close(fd);
1372
1373         BT_DBG("supported: %d", is_supported);
1374
1375         return is_supported;
1376 }
1377
1378 BT_EXPORT_API int bluetooth_register_callback(bluetooth_cb_func_ptr callback_ptr, void *user_data)
1379 {
1380         int ret;
1381
1382         _bt_gdbus_init_system_gconn();
1383         __bt_init_system_gconn();
1384
1385         ret = _bt_init_event_handler();
1386         if (ret != BLUETOOTH_ERROR_NONE &&
1387              ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
1388                 BT_ERR("Fail to init the event handler");
1389                 return ret;
1390         }
1391
1392
1393         _bt_set_user_data(BT_COMMON, (void *)callback_ptr, user_data);
1394
1395         /* Register All events */
1396         ret = _bt_register_event(BT_ADAPTER_EVENT, (void *)callback_ptr, user_data);
1397         if (ret != BLUETOOTH_ERROR_NONE)
1398                 goto fail;
1399         ret = _bt_register_event(BT_DEVICE_EVENT, (void *)callback_ptr, user_data);
1400         if (ret != BLUETOOTH_ERROR_NONE)
1401                 goto fail;
1402         ret = _bt_register_event(BT_NETWORK_EVENT, (void *)callback_ptr, user_data);
1403         if (ret != BLUETOOTH_ERROR_NONE)
1404                 goto fail;
1405         ret = _bt_register_event(BT_RFCOMM_CLIENT_EVENT, (void *)callback_ptr, user_data);
1406         if (ret != BLUETOOTH_ERROR_NONE)
1407                 goto fail;
1408         ret = _bt_register_event(BT_RFCOMM_SERVER_EVENT, (void *)callback_ptr, user_data);
1409         if (ret != BLUETOOTH_ERROR_NONE)
1410                 goto fail;
1411
1412         _bt_register_name_owner_changed();
1413
1414         return BLUETOOTH_ERROR_NONE;
1415 fail:
1416         BT_ERR("Fail to do _bt_register_event()");
1417         bluetooth_unregister_callback();
1418         return ret;
1419 }
1420
1421 BT_EXPORT_API int bluetooth_unregister_callback(void)
1422 {
1423         int ret;
1424
1425         ret = _bt_deinit_event_handler();
1426         if (ret != BLUETOOTH_ERROR_NONE) {
1427                 BT_ERR("Fail to deinit the event handler");
1428         }
1429
1430         _bt_unregister_name_owner_changed();
1431
1432         _bt_set_user_data(BT_COMMON, NULL, NULL);
1433
1434         if (system_conn) {
1435                 dbus_g_connection_unref(system_conn);
1436                 system_conn = NULL;
1437         }
1438         if (system_gconn) {
1439                 g_object_unref(system_gconn);
1440                 system_gconn = NULL;
1441         }
1442         return BLUETOOTH_ERROR_NONE;
1443 }
1444