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