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