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