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