Code Sync [Tizen3.0]: Merged the tizen_2.4 Spin code to tizen.org
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / TFXF5A4.tmp
1 /*
2  * Bluetooth-frwk low energy
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Hocheol Seo <hocheol.seo@samsung.com>
7  *          Girishashok Joshi <girish.joshi@samsung.com>
8  *          Chanyeol Park <chanyeol.park@samsung.com>
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *              http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */
23
24 #include <string.h>
25 #include <dbus/dbus.h>
26 #include <dbus/dbus-glib.h>
27 #include <glib.h>
28
29 #include "bluetooth-api.h"
30 #include "bt-common.h"
31 #include "bt-internal-types.h"
32
33
34 #define BLUEZ_CHAR_INTERFACE "org.bluez.Characteristic"
35
36 #define GATT_OBJECT_PATH  "/org/bluez/gatt_attrib"
37
38 typedef struct {
39         GObject parent;
40 } BluetoothGattService;
41
42 typedef struct {
43         GObjectClass parent;
44 } BluetoothGattServiceClass;
45
46 typedef struct {
47         char *char_uuid;
48         char **handle;
49 } char_pty_req_t;
50
51 GType bluetooth_gatt_service_get_type(void);
52
53 #define BLUETOOTH_GATT_TYPE_SERVICE (bluetooth_gatt_service_get_type())
54
55 #define BLUETOOTH_GATT_SERVICE(object)  \
56                 (G_TYPE_CHECK_INSTANCE_CAST((object), \
57                 BLUETOOTH_GATT_TYPE_SERVICE, BluetoothGattService))
58
59 #define BLUETOOTH_GATT_SERVICE_CLASS(klass)     \
60                 (G_TYPE_CHECK_CLASS_CAST((klass), \
61                 BLUETOOTH_GATT_TYPE_SERVICE, BluetoothGattServiceClass))
62
63 #define BLUETOOTH_GATT_IS_SERVICE(object)       \
64                 (G_TYPE_CHECK_INSTANCE_TYPE((object), BLUETOOTH_GATT_TYPE_SERVICE))
65
66 #define BLUETOOTH_GATT_IS_SERVICE_CLASS(klass)  \
67                 (G_TYPE_CHECK_CLASS_TYPE((klass), BLUETOOTH_GATT_TYPE_SERVICE))
68
69 #define BLUETOOTH_GATT_SERVICE_GET_CLASS(obj)   \
70                 (G_TYPE_INSTANCE_GET_CLASS((obj), \
71                 BLUETOOTH_GATT_TYPE_SERVICE, BluetoothGattServiceClass))
72
73 G_DEFINE_TYPE(BluetoothGattService, bluetooth_gatt_service, G_TYPE_OBJECT)
74
75 static gboolean bluetooth_gatt_value_changed(BluetoothGattService *agent,
76                                         gchar *obj_path,
77                                         GArray *byte_array,
78                                         DBusGMethodInvocation *context);
79
80 #include "bt-gatt-glue.h"
81
82 static void bluetooth_gatt_service_init(BluetoothGattService *obj)
83 {
84         g_assert(obj != NULL);
85 }
86
87 static void bluetooth_gatt_service_finalize(GObject *obj)
88 {
89         G_OBJECT_CLASS(bluetooth_gatt_service_parent_class)->finalize(obj);
90 }
91
92 static void bluetooth_gatt_service_class_init(BluetoothGattServiceClass *klass)
93 {
94         GObjectClass *object_class = (GObjectClass *)klass;
95
96         g_assert(klass != NULL);
97
98         object_class->finalize = bluetooth_gatt_service_finalize;
99
100         dbus_g_object_type_install_info(BLUETOOTH_GATT_TYPE_SERVICE,
101                                         &dbus_glib_bluetooth_gatt_object_info);
102 }
103
104 static gboolean bluetooth_gatt_value_changed(BluetoothGattService *agent,
105                                         gchar *obj_path,
106                                         GArray *byte_array,
107                                         DBusGMethodInvocation *context)
108 {
109         bt_gatt_char_value_t char_val;
110         bt_user_info_t *user_info;
111         BT_DBG("+");
112
113         char_val.char_handle = obj_path;
114         char_val.char_value = &g_array_index(byte_array, guint8, 0);
115         char_val.val_len = byte_array->len;
116         BT_DBG("Byte array length = %d", char_val.val_len);
117
118         user_info = _bt_get_user_data(BT_COMMON);
119
120         if (user_info->cb) {
121                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED,
122                                 BLUETOOTH_ERROR_NONE, &char_val,
123                                 user_info->cb, user_info->user_data);
124         }
125
126         BT_DBG("-");
127
128         return TRUE;
129 }
130
131 static void __add_value_changed_method(DBusGConnection *conn)
132 {
133         static gboolean method_added = FALSE;
134         BluetoothGattService *bluetooth_gatt_obj = NULL;
135
136         if (method_added) {
137                 BT_ERR("Method already added. \n");
138                 return;
139         }
140
141         method_added = TRUE;
142
143         bluetooth_gatt_obj = g_object_new(BLUETOOTH_GATT_TYPE_SERVICE, NULL);
144
145         dbus_g_connection_register_g_object(conn, GATT_OBJECT_PATH,
146                         G_OBJECT(bluetooth_gatt_obj));
147
148 }
149
150 static char **__get_string_array_from_gptr_array(GPtrArray *gp)
151 {
152         gchar *gp_path = NULL;
153         char **path = NULL;
154         int i;
155
156         if (gp->len == 0)
157                 return NULL;
158
159         path = g_malloc0((gp->len + 1) * sizeof(char *));
160
161         for (i = 0; i < gp->len; i++) {
162                 gp_path = g_ptr_array_index(gp, i);
163                 path[i] = g_strdup(gp_path);
164                 BT_DBG("path[%d] : [%s]", i, path[i]);
165         }
166
167         return path;
168 }
169
170 static void __bluetooth_internal_get_char_cb(DBusGProxy *proxy,
171                                         DBusGProxyCall *call,
172                                         gpointer user_data)
173 {
174         GError *error = NULL;
175         GPtrArray *gp_array = NULL;
176         bt_gatt_discovered_char_t svc_char = { 0, };
177         bt_user_info_t *user_info;
178
179         svc_char.service_handle = user_data;
180
181         user_info = _bt_get_user_data(BT_COMMON);
182
183         if (!dbus_g_proxy_end_call(proxy, call, &error,
184                 dbus_g_type_get_collection("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
185                 &gp_array, G_TYPE_INVALID)) {
186                 BT_ERR("Error : %s \n", error->message);
187                 g_error_free(error);
188
189                 if (user_info->cb) {
190                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
191                                         BLUETOOTH_ERROR_NONE, &svc_char,
192                                         user_info->cb, user_info->user_data);
193                 }
194                 g_free(svc_char.service_handle);
195                 g_object_unref(proxy);
196                 return;
197         }
198
199         if (NULL != gp_array) {
200                 svc_char.handle_info.count = gp_array->len;
201                 svc_char.handle_info.handle = __get_string_array_from_gptr_array(gp_array);
202         }
203
204         if (user_info) {
205                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
206                                 BLUETOOTH_ERROR_NONE, &svc_char,
207                                 user_info->cb, user_info->user_data);
208         }
209
210         g_ptr_array_free(gp_array, TRUE);
211         g_free(svc_char.service_handle);
212         g_free(svc_char.handle_info.handle);
213         g_object_unref(proxy);
214 }
215
216 static void __bluetooth_internal_read_cb(GObject *source_object,
217                                         GAsyncResult *res,
218                                         gpointer user_data)
219 {
220         GError *error = NULL;
221         bt_user_info_t *user_info;
222         bt_gatt_char_value_t rsp =  { 0, };
223         GDBusConnection *system_gconn = NULL;
224         GVariant *return_data;
225         GByteArray *gp_byte_array = NULL;
226         GVariantIter *iter;
227         guint8 g_byte;
228
229         user_info = _bt_get_user_data(BT_COMMON);
230
231         system_gconn = _bt_init_system_gdbus_conn();
232         return_data = g_dbus_connection_call_finish(system_gconn, res, &error);
233
234         if (error) {
235                 BT_ERR("Error : %s \n", error->message);
236                 if(return_data)
237                         g_variant_unref(return_data);
238                 g_clear_error(&error);
239                 return;
240         }
241
242         gp_byte_array = g_byte_array_new();
243         g_variant_get(return_data, "(ay)", &iter);
244
245         while (g_variant_iter_loop(iter, "y",  &g_byte)) {
246                 g_byte_array_append(gp_byte_array, &g_byte, 1);
247         }
248
249         if (NULL != gp_byte_array) {
250                 rsp.val_len = gp_byte_array->len;
251                 rsp.char_value = gp_byte_array->data;
252         }
253
254         if (user_info) {
255                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
256                                 BLUETOOTH_ERROR_NONE, &rsp,
257                                 user_info->cb, user_info->user_data);
258         }
259
260         g_byte_array_free(gp_byte_array, TRUE);
261         g_variant_unref(return_data);
262         g_variant_iter_free(iter);
263         return;
264 }
265
266 static void __bluetooth_internal_write_cb(GObject *source_object,
267                                         GAsyncResult *res,
268                                         gpointer user_data)
269 {
270         GError *error = NULL;
271         bt_user_info_t *user_info;
272         GDBusConnection *system_gconn = NULL;
273         GVariant *return_data;
274         int result = BLUETOOTH_ERROR_NONE;
275
276         BT_DBG("__bluetooth_internal_write_cb");
277         user_info = _bt_get_user_data(BT_COMMON);
278
279         system_gconn = _bt_init_system_gdbus_conn();
280         return_data = g_dbus_connection_call_finish(system_gconn, res, &error);
281
282         if (error) {
283                 BT_ERR("Error : %s \n", error->message);
284                 g_clear_error(&error);
285                 result = BLUETOOTH_ERROR_INTERNAL;
286         }
287         if (user_info) {
288                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
289                                 result, NULL,
290                                 user_info->cb, user_info->user_data);
291         }
292         BT_DBG("BP 0>>>>>>");
293
294         if(return_data)
295                 g_variant_unref(return_data);
296
297         return;
298 }
299
300 static void __bluetooth_internal_get_char_desc_cb(GObject *source_object,
301                                         GAsyncResult *res,
302                                         gpointer user_data)
303 {
304         GError *error = NULL;
305         GByteArray *gp_byte_array = NULL;
306         bt_gatt_char_property_t svc_char_desc = { 0, };
307         bt_user_info_t *user_info;
308         GDBusConnection *system_gconn = NULL;
309         GVariant *return_data;
310         GVariantIter *iter;
311         guint8 g_byte;
312
313         svc_char_desc.handle = user_data;
314         svc_char_desc.val_len = 0x00;
315         svc_char_desc.description = NULL;
316
317         user_info = _bt_get_user_data(BT_COMMON);
318         system_gconn = _bt_init_system_gdbus_conn();
319         return_data = g_dbus_connection_call_finish(system_gconn, res, &error);
320         BT_DBG("result data received..");
321         if (error) {
322                 BT_ERR("Error : %s \n", error->message);
323                 g_clear_error(&error);
324                 g_free(svc_char_desc.handle);
325                 return;
326         }
327         gp_byte_array = g_byte_array_new();
328         g_variant_get(return_data, "(ay)", &iter);
329
330         /*Format*/
331         if (g_variant_iter_loop(iter, "y",  &g_byte))
332                 svc_char_desc.format.format = g_byte;
333
334         /*Handle and UUIDs*/
335         while (g_variant_iter_loop(iter, "y",  &g_byte)) {
336                 g_byte_array_append(gp_byte_array, &g_byte, 1);
337         }
338
339         if (NULL != gp_byte_array) {
340                 svc_char_desc.val_len = gp_byte_array->len;
341                 svc_char_desc.description = (char *)gp_byte_array->data;
342         }
343
344         if (user_info) {
345                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
346                                 BLUETOOTH_ERROR_NONE, &svc_char_desc,
347                                 user_info->cb, user_info->user_data);
348         }
349
350         g_byte_array_free(gp_byte_array, TRUE);
351         g_free(svc_char_desc.handle);
352         g_variant_unref(return_data);
353         g_variant_iter_free(iter);
354 }
355
356 static void __free_char_req(char_pty_req_t *char_req)
357 {
358         g_free(char_req->char_uuid);
359         g_strfreev(char_req->handle);
360         g_free(char_req);
361 }
362
363 static gboolean __filter_chars_with_uuid(gpointer data)
364 {
365         int i = 0;
366         bt_gatt_char_property_t *char_pty;
367         char_pty_req_t *char_req = data;
368         bt_user_info_t *user_info;
369         int ret;
370
371         user_info = _bt_get_user_data(BT_COMMON);
372         if (user_info->cb == NULL) {
373                 __free_char_req(char_req);
374                 return FALSE;
375         }
376
377         char_pty = g_new0(bt_gatt_char_property_t, 1);
378
379         while (char_req->handle[i] != NULL) {
380                 BT_DBG("char_pty[%d] = %s", i, char_req->handle[i]);
381                 ret = bluetooth_gatt_get_characteristics_property(char_req->handle[i],
382                                                                         char_pty);
383                 if (ret != BLUETOOTH_ERROR_NONE) {
384                         BT_ERR("get char property failed");
385                         goto done;
386                 }
387
388                 if (char_pty->uuid  && g_strstr_len(char_pty->uuid, -1,
389                                                 char_req->char_uuid) != NULL) {
390                         BT_DBG("Requested Char recieved");
391                         ret = BLUETOOTH_ERROR_NONE;
392                         break;
393                 }
394
395                 bluetooth_gatt_free_char_property(char_pty);
396
397                 i++;
398         }
399
400 done:
401         if (char_req->handle[i] == NULL)
402                 ret = BLUETOOTH_ERROR_NOT_FOUND;
403
404         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret,
405                                 char_pty, user_info->cb, user_info->user_data);
406
407         g_free(char_pty);
408         __free_char_req(char_req);
409
410         return FALSE;
411 }
412
413 static void __disc_char_from_uuid_cb(DBusGProxy *proxy,
414                                         DBusGProxyCall *call,
415                                         gpointer user_data)
416 {
417         GError *error = NULL;
418         GPtrArray *gp_array = NULL;
419         bt_user_info_t *user_info;
420         char_pty_req_t *char_req = user_data;
421
422         user_info = _bt_get_user_data(BT_COMMON);
423         if (!user_info->cb) {
424                 __free_char_req(char_req);
425                 return;
426         }
427
428         if (!dbus_g_proxy_end_call(proxy, call, &error,
429                 dbus_g_type_get_collection("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
430                 &gp_array, G_TYPE_INVALID)) {
431                 BT_ERR("Error : %s \n", error->message);
432                 g_error_free(error);
433
434                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
435                                         BLUETOOTH_ERROR_INTERNAL, NULL,
436                                         user_info->cb, user_info->user_data);
437
438                 __free_char_req(char_req);
439                 g_object_unref(proxy);
440                 return;
441         }
442
443         if (gp_array == NULL) {
444                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
445                                         BLUETOOTH_ERROR_NOT_FOUND, NULL,
446                                         user_info->cb, user_info->user_data);
447
448                 __free_char_req(char_req);
449                 g_object_unref(proxy);
450
451                 return;
452         }
453
454         char_req->handle = __get_string_array_from_gptr_array(gp_array);
455
456         __filter_chars_with_uuid(char_req);
457
458         g_ptr_array_free(gp_array, TRUE);
459         g_object_unref(proxy);
460 }
461
462
463 static int __discover_char_from_uuid(const char *service_handle,
464                                                         const char *char_uuid){
465         DBusGProxy *service_proxy = NULL;
466         DBusGConnection *conn;
467         char_pty_req_t *char_req;
468
469         conn = _bt_get_system_gconn();
470         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
471
472         service_proxy = dbus_g_proxy_new_for_name(conn,
473                                                 BT_BLUEZ_NAME, service_handle,
474                                                 BLUEZ_CHAR_INTERFACE);
475         retv_if(service_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
476
477         char_req = g_new0(char_pty_req_t, 1);
478
479         char_req->char_uuid = g_strdup(char_uuid);
480         BT_DBG("Char uuid %s ", char_uuid);
481
482         if (!dbus_g_proxy_begin_call(service_proxy, "DiscoverCharacteristics",
483                         (DBusGProxyCallNotify)__disc_char_from_uuid_cb,
484                         char_req, NULL, G_TYPE_INVALID)) {
485                 __free_char_req(char_req);
486                 g_object_unref(service_proxy);
487                 return BLUETOOTH_ERROR_INTERNAL;
488         }
489
490         return BLUETOOTH_ERROR_NONE;
491 }
492
493 BT_EXPORT_API int bluetooth_gatt_free_primary_services(bt_gatt_handle_info_t *prim_svc)
494 {
495         BT_DBG("+");
496
497         BT_CHECK_PARAMETER(prim_svc, return);
498
499         g_strfreev(prim_svc->handle);
500
501         memset(prim_svc, 0, sizeof(bt_gatt_handle_info_t));
502
503         BT_DBG("-");
504         return BLUETOOTH_ERROR_NONE;
505 }
506
507 BT_EXPORT_API int bluetooth_gatt_free_service_property(bt_gatt_service_property_t *svc_pty)
508 {
509         BT_DBG("+");
510
511         BT_CHECK_PARAMETER(svc_pty, return);
512
513         g_free(svc_pty->uuid);
514         g_free(svc_pty->handle);
515         g_strfreev(svc_pty->handle_info.handle);
516
517         memset(svc_pty, 0, sizeof(bt_gatt_service_property_t));
518
519         BT_DBG("-");
520         return BLUETOOTH_ERROR_NONE;
521 }
522
523 BT_EXPORT_API int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty)
524 {
525         BT_DBG("+");
526
527         BT_CHECK_PARAMETER(char_pty, return);
528
529         g_free(char_pty->uuid);
530         g_free(char_pty->name);
531         g_free(char_pty->description);
532         g_free(char_pty->val);
533         g_free(char_pty->handle);
534
535         memset(char_pty, 0, sizeof(bt_gatt_char_property_t));
536
537         BT_DBG("-");
538         return BLUETOOTH_ERROR_NONE;
539 }
540
541 BT_EXPORT_API int bluetooth_gatt_get_primary_services(const bluetooth_device_address_t *address,
542                                                                 bt_gatt_handle_info_t *prim_svc)
543 {
544         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
545         gchar *device_path = NULL;
546         GError *error = NULL;
547
548         GVariant *result;
549         GVariantIter *iter;
550         GDBusConnection *conn;
551         GVariant *value = NULL;
552         gchar *g_str;
553
554         GPtrArray *gp_array  = NULL;
555         int ret = BLUETOOTH_ERROR_INTERNAL;
556
557         BT_DBG("+");
558
559         BT_CHECK_PARAMETER(address, return);
560         BT_CHECK_PARAMETER(prim_svc, return);
561
562         BT_CHECK_ENABLED(return);
563
564         /* About org.tizen.device1 interface, dbus SMACK is not working. So use bt-service's
565           privilege checking logic */
566         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_GATT_GET_PRIMARY_SERVICES)
567              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
568                 BT_ERR("Don't have a privilege to use this API");
569                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
570         }
571
572         _bt_convert_addr_type_to_string(device_address,
573                                 (unsigned char *)address->addr);
574
575         BT_INFO("bluetooth address [%s]\n", device_address);
576
577         device_path = _bt_get_device_object_path(device_address);
578
579         retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL);
580
581         conn = _bt_init_system_gdbus_conn();
582         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
583
584         result = g_dbus_connection_call_sync(conn,
585                                 BT_BLUEZ_NAME,
586                                 device_path,
587                                 BT_DEVICE_INTERFACE,
588                                 "GetPrimServices",
589                                 NULL,
590                                 G_VARIANT_TYPE ("(ao)"),
591                                 G_DBUS_CALL_FLAGS_NONE,
592                                 -1,
593                                 NULL,
594                                 &error);
595                 if (error) {
596                         BT_ERR("GetPrimServices Call Error %s[%s]", error->message,
597                                                                  device_address);
598                         g_clear_error(&error);
599                         return BLUETOOTH_ERROR_INTERNAL;
600                 }
601                 g_free(device_path);
602
603                 gp_array = g_ptr_array_new();
604                 g_variant_get(result, "(ao)", &iter);
605                 while ((value = g_variant_iter_next_value(iter))) {
606                         g_variant_get(value, "o", &g_str);
607                         g_ptr_array_add(gp_array, (gpointer)g_str);
608                  }
609
610         if (gp_array == NULL) {
611                 BT_ERR("gp_array == NULL");
612                 goto done;
613         }
614
615         prim_svc->count = gp_array->len;
616         prim_svc->handle = __get_string_array_from_gptr_array(gp_array);
617
618         g_ptr_array_free(gp_array, TRUE);
619         g_variant_iter_free(iter);
620         g_variant_unref(result);
621
622         ret = BLUETOOTH_ERROR_NONE;
623 done:
624         BT_DBG("-");
625         return ret;
626 }
627
628 BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(const char *service_handle)
629 {
630         DBusGProxy *service_proxy = NULL;
631         char *handle;
632         DBusGConnection *conn;
633
634         BT_CHECK_PARAMETER(service_handle, return);
635
636         BT_CHECK_ENABLED(return);
637
638         /* Because this API is async call, so can't use dbus SMACK */
639         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_GATT_DISCOVER_CHARACTERISTICS)
640              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
641                 BT_ERR("Don't have a privilege to use this API");
642                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
643         }
644
645         conn = _bt_get_system_gconn();
646         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
647
648         service_proxy = dbus_g_proxy_new_for_name(conn,
649                                                 BT_BLUEZ_NAME, service_handle,
650                                                 BLUEZ_CHAR_INTERFACE);
651
652         retv_if(service_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
653
654         handle = g_strdup(service_handle);
655         BT_DBG("Requested characteristic handle:%s \n ", handle);
656
657         if (!dbus_g_proxy_begin_call(service_proxy, "DiscoverCharacteristics",
658                         (DBusGProxyCallNotify)__bluetooth_internal_get_char_cb,
659                         handle, NULL, G_TYPE_INVALID)) {
660                 g_free(handle);
661                 g_object_unref(service_proxy);
662                 return BLUETOOTH_ERROR_INTERNAL;
663         }
664
665         return BLUETOOTH_ERROR_NONE;
666 }
667
668 BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle,
669                                                 bt_gatt_service_property_t *service)
670 {
671         DBusGProxy *service_proxy = NULL;
672         GHashTable *hash = NULL;
673         GError *error = NULL;
674         GValue *value = NULL;
675         GPtrArray *gp_array  = NULL ;
676         DBusGConnection *conn;
677         int ret = BLUETOOTH_ERROR_NONE;
678
679         BT_CHECK_PARAMETER(service_handle, return);
680         BT_CHECK_PARAMETER(service, return);
681
682         BT_CHECK_ENABLED(return);
683
684         conn = _bt_get_system_gconn();
685         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
686
687         service_proxy = dbus_g_proxy_new_for_name(conn,
688                                                 BT_BLUEZ_NAME, service_handle,
689                                                 BLUEZ_CHAR_INTERFACE);
690
691         retv_if(service_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
692
693         dbus_g_proxy_call(service_proxy, "GetProperties", &error, G_TYPE_INVALID,
694                                 dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
695                                 &hash, G_TYPE_INVALID);
696
697         g_object_unref(service_proxy);
698
699         if (error != NULL) {
700                 BT_ERR("GetProperties Call Error %s\n", error->message);
701
702                 if (g_strrstr(error->message, BT_ACCESS_DENIED_MSG))
703                         ret = BLUETOOTH_ERROR_ACCESS_DENIED;
704                 else
705                         ret = BLUETOOTH_ERROR_INTERNAL;
706
707                 g_error_free(error);
708                 return ret;
709         }
710
711         retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL);
712
713         memset(service, 0, sizeof(bt_gatt_service_property_t));
714
715         value = g_hash_table_lookup(hash, "UUID");
716         service->uuid = value ? g_value_dup_string(value) : NULL;
717         if (service->uuid) {
718                 BT_DBG("svc_pty.uuid = [%s] \n", service->uuid);
719         }
720
721         value = g_hash_table_lookup(hash, "Characteristics");
722         gp_array = value ? g_value_get_boxed(value) : NULL;
723         if (gp_array) {
724                 service->handle_info.count = gp_array->len;
725                 service->handle_info.handle = __get_string_array_from_gptr_array(gp_array);
726         }
727
728         service->handle = g_strdup(service_handle);
729         g_hash_table_destroy(hash);
730         return BLUETOOTH_ERROR_NONE;
731 }
732
733 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *service_handle)
734 {
735         DBusGProxy *watch_proxy = NULL;
736         GError *error = NULL;
737         DBusGConnection *conn;
738         int ret = BLUETOOTH_ERROR_NONE;
739
740         BT_CHECK_PARAMETER(service_handle, return);
741
742         BT_CHECK_ENABLED(return);
743
744         BT_DBG("Entered service handle:%s \n ", service_handle);
745
746         conn = _bt_get_system_gconn();
747         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
748
749         watch_proxy = dbus_g_proxy_new_for_name(conn,
750                                 BT_BLUEZ_NAME, service_handle,
751                                 BLUEZ_CHAR_INTERFACE);
752
753         retv_if(watch_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
754
755         __add_value_changed_method(conn);
756
757         dbus_g_proxy_call(watch_proxy, "RegisterCharacteristicsWatcher", &error,
758                                 DBUS_TYPE_G_OBJECT_PATH, GATT_OBJECT_PATH,
759                                 G_TYPE_INVALID, G_TYPE_INVALID);
760         if (error) {
761                 BT_ERR("Method call  Fail: %s", error->message);
762
763                 if (g_strrstr(error->message, BT_ACCESS_DENIED_MSG))
764                         ret = BLUETOOTH_ERROR_ACCESS_DENIED;
765                 else
766                         ret = BLUETOOTH_ERROR_INTERNAL;
767
768                 g_error_free(error);
769                 g_object_unref(watch_proxy);
770                 return ret;
771         }
772
773         g_object_unref(watch_proxy);
774
775         return BLUETOOTH_ERROR_NONE;
776 }
777
778 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *service_handle)
779 {
780         DBusGProxy *watch_proxy = NULL;
781         GError *error = NULL;
782         DBusGConnection *conn;
783         int ret = BLUETOOTH_ERROR_NONE;
784
785         BT_CHECK_PARAMETER(service_handle, return);
786
787         BT_CHECK_ENABLED(return);
788
789         conn = _bt_get_system_gconn();
790         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
791
792         watch_proxy = dbus_g_proxy_new_for_name(conn,
793                                 BT_BLUEZ_NAME, service_handle,
794                                 BLUEZ_CHAR_INTERFACE);
795
796         retv_if(watch_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
797
798         dbus_g_proxy_call(watch_proxy, "UnregisterCharacteristicsWatcher", &error,
799                                 DBUS_TYPE_G_OBJECT_PATH, GATT_OBJECT_PATH,
800                                 G_TYPE_INVALID, G_TYPE_INVALID);
801         if (error) {
802                 BT_ERR("Method call  Fail: %s", error->message);
803
804                 if (g_strrstr(error->message, BT_ACCESS_DENIED_MSG))
805                         ret = BLUETOOTH_ERROR_ACCESS_DENIED;
806                 else
807                         ret = BLUETOOTH_ERROR_INTERNAL;
808
809                 g_error_free(error);
810                 g_object_unref(watch_proxy);
811                 return ret;
812         }
813
814         g_object_unref(watch_proxy);
815
816         return BLUETOOTH_ERROR_NONE;
817 }
818
819 BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(const char *char_handle,
820                                                 bt_gatt_char_property_t *characteristic)
821 {
822         DBusGProxy *characteristic_proxy = NULL;
823         GHashTable *hash = NULL;
824         GError *error = NULL;
825         GValue *value = NULL;
826         GByteArray *gb_array = NULL;
827         DBusGConnection *conn;
828         int ret = BLUETOOTH_ERROR_NONE;
829
830         BT_CHECK_PARAMETER(char_handle, return);
831         BT_CHECK_PARAMETER(characteristic, return);
832
833         BT_CHECK_ENABLED(return);
834
835         conn = _bt_get_system_gconn();
836         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
837
838         characteristic_proxy = dbus_g_proxy_new_for_name(conn,
839                                                 BT_BLUEZ_NAME, char_handle,
840                                                 BLUEZ_CHAR_INTERFACE);
841
842         retv_if(characteristic_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
843
844         dbus_g_proxy_call(characteristic_proxy, "GetProperties", &error, G_TYPE_INVALID,
845                                 dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
846                                 &hash, G_TYPE_INVALID);
847         if (error != NULL) {
848                 BT_ERR("GetProperties Call Error %s\n", error->message);
849
850                 if (g_strrstr(error->message, BT_ACCESS_DENIED_MSG))
851                         ret = BLUETOOTH_ERROR_ACCESS_DENIED;
852                 else
853                         ret = BLUETOOTH_ERROR_INTERNAL;
854
855                 g_error_free(error);
856                 g_object_unref(characteristic_proxy);
857                 return ret;
858         }
859         g_object_unref(characteristic_proxy);
860
861         retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL);
862
863         memset(characteristic, 0, sizeof(bt_gatt_char_property_t));
864
865         value = g_hash_table_lookup(hash, "UUID");
866         characteristic->uuid = value ? g_value_dup_string(value) : NULL;
867         if (characteristic->uuid) {
868                 BT_DBG("characteristic->uuid = [%s] \n", characteristic->uuid);
869         }
870
871         value = g_hash_table_lookup(hash, "Name");
872         characteristic->name = value ? g_value_dup_string(value) : NULL;
873         if (characteristic->name) {
874                 DBG_SECURE("characteristic->name = [%s] \n", characteristic->name);
875         }
876
877         value = g_hash_table_lookup(hash, "Description");
878         characteristic->description = value ? g_value_dup_string(value) : NULL;
879         if (characteristic->description) {
880                 BT_DBG("characteristic->description = [%s] \n", characteristic->description);
881         }
882
883         value = g_hash_table_lookup(hash, "Value");
884
885         gb_array = value ? g_value_get_boxed(value) : NULL;
886         if (gb_array) {
887                 if (gb_array->len) {
888                         BT_DBG("gb_array->len  = %d \n", gb_array->len);
889                         characteristic->val_len = gb_array->len;
890
891                         characteristic->val = g_malloc0(gb_array->len * sizeof(unsigned char));
892                         memcpy(characteristic->val, gb_array->data, gb_array->len);
893                 } else {
894                         characteristic->val = NULL;
895                         characteristic->val_len = 0;
896                 }
897         } else {
898                 characteristic->val = NULL;
899                 characteristic->val_len = 0;
900         }
901         characteristic->handle = g_strdup(char_handle);
902         g_hash_table_destroy(hash);
903         return BLUETOOTH_ERROR_NONE;
904 }
905
906 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(const char *char_handle,
907                                                 const guint8 *value, int length)
908 {
909         GVariant *val;
910         char *handle;
911         GVariantBuilder *builder;
912         GError *error = NULL;
913         DBusGConnection *conn;
914         int i = 0;
915         int ret = BLUETOOTH_ERROR_NONE;
916
917         BT_CHECK_PARAMETER(char_handle, return);
918         BT_CHECK_PARAMETER(value, return);
919         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
920
921         BT_CHECK_ENABLED(return);
922
923         conn = _bt_get_system_gconn();
924         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
925
926         BT_DBG("Requested characteristic handle:%s \n ", char_handle);
927
928         builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
929
930         for (i = 0; i < length; i++) {
931                 g_variant_builder_add(builder, "y", value[i]);
932                 BT_DBG("value idx:%d, %d", i, value[i]);
933         }
934
935         val = g_variant_new("ay", builder);
936
937         handle = g_strdup(char_handle);
938         BT_DBG("BP 0");
939
940         g_dbus_connection_call_sync(conn,
941                                 BT_BLUEZ_NAME,
942                                 char_handle,
943                                 BLUEZ_CHAR_INTERFACE,
944                                 "SetProperty",
945                                 g_variant_new("(sv)",
946                                         "Value", val),
947                                 NULL,
948                                 G_DBUS_CALL_FLAGS_NONE,
949                                 -1,
950                                 NULL,
951                                 &error);
952
953         if (error) {
954                 BT_ERR("Set value Fail: %s", error->message);
955
956                 if (g_strrstr(error->message, BT_ACCESS_DENIED_MSG))
957                         ret = BLUETOOTH_ERROR_ACCESS_DENIED;
958                 else
959                         ret = BLUETOOTH_ERROR_INTERNAL;
960
961                 g_error_free(error);
962                 g_variant_builder_unref(builder);
963                 return ret;
964         }
965         BT_DBG("BP 1");
966
967         g_variant_builder_unref(builder);
968         return BLUETOOTH_ERROR_NONE;
969 }
970
971 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
972                 const char *char_handle, const guint8 *value, int length)
973 {
974         GVariant *val;
975         GError *error = NULL;
976         GDBusConnection *conn;
977         char *handle;
978         GVariantBuilder *builder;
979         int i;
980
981         BT_CHECK_PARAMETER(char_handle, return);
982         BT_CHECK_PARAMETER(value, return);
983         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
984
985         BT_CHECK_ENABLED(return);
986
987         /* Because this API is async call, so can't use dbus SMACK */
988         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_GATT_SET_PROPERTY_REQUEST)
989              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
990                 BT_ERR("Don't have a privilege to use this API");
991                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
992         }
993
994         conn = _bt_init_system_gdbus_conn();
995         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
996
997         builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
998
999         for (i = 0; i < length; i++) {
1000                 g_variant_builder_add(builder, "y", value[i]);
1001         }
1002
1003         val = g_variant_new("ay", builder);
1004
1005         handle = g_strdup(char_handle);
1006
1007         g_dbus_connection_call(conn,
1008                                 BT_BLUEZ_NAME,
1009                                 char_handle,
1010                                 BLUEZ_CHAR_INTERFACE,
1011                                 "SetPropertyRequest",
1012                                 g_variant_new("(sv)",
1013                                         "Value", val),
1014                                 NULL,
1015                                 G_DBUS_CALL_FLAGS_NONE,
1016                                 -1,
1017                                 NULL,
1018                                 (GAsyncReadyCallback)
1019                                 __bluetooth_internal_write_cb,
1020                                 handle);
1021
1022         if (error) {
1023                 BT_ERR("Set value Fail: %s", error->message);
1024                 g_clear_error(&error);
1025                 g_variant_builder_unref(builder);
1026                 return BLUETOOTH_ERROR_INTERNAL;
1027         }
1028         g_variant_builder_unref(builder);
1029
1030         return BLUETOOTH_ERROR_NONE;
1031 }
1032
1033 BT_EXPORT_API int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address,
1034                                         const char *service_uuid,
1035                                         bt_gatt_service_property_t *service)
1036 {
1037         int i;
1038         int ret;
1039         bt_gatt_handle_info_t prim_svc;
1040
1041         BT_CHECK_PARAMETER(address, return);
1042         BT_CHECK_PARAMETER(service_uuid, return);
1043         BT_CHECK_PARAMETER(service, return);
1044
1045         BT_CHECK_ENABLED(return);
1046
1047         ret = bluetooth_gatt_get_primary_services(address, &prim_svc);
1048         if (ret != BLUETOOTH_ERROR_NONE) {
1049                 BT_ERR("Get primary service failed ");
1050                 return ret;
1051         }
1052
1053         for (i = 0; i < prim_svc.count; i++) {
1054
1055                 BT_DBG("prim_svc [%d] = %s", i, prim_svc.handle[i]);
1056
1057                 ret = bluetooth_gatt_get_service_property(prim_svc.handle[i],
1058                                                                 service);
1059                 if (ret != BLUETOOTH_ERROR_NONE) {
1060                         BT_ERR("Get service property failed ");
1061                         bluetooth_gatt_free_primary_services(&prim_svc);
1062                         return ret;
1063                 }
1064
1065                 BT_DBG("Service uuid %s", service->uuid);
1066
1067                 if (g_strstr_len(service->uuid, -1, service_uuid)) {
1068                         BT_INFO("Found requested service");
1069                         ret = BLUETOOTH_ERROR_NONE;
1070                         break;
1071                 }
1072
1073                 bluetooth_gatt_free_service_property(service);
1074         }
1075
1076         if (i == prim_svc.count)
1077                 ret = BLUETOOTH_ERROR_NOT_FOUND;
1078
1079         bluetooth_gatt_free_primary_services(&prim_svc);
1080
1081         return ret;
1082 }
1083
1084 BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
1085                                                 const char *char_uuid)
1086 {
1087         char **char_handles;
1088         char_pty_req_t *char_pty;
1089         int i;
1090         bt_gatt_service_property_t svc_pty;
1091         int ret;
1092
1093         BT_CHECK_PARAMETER(service_handle, return);
1094         BT_CHECK_PARAMETER(char_uuid, return);
1095
1096         BT_CHECK_ENABLED(return);
1097
1098         ret = bluetooth_gatt_get_service_property(service_handle, &svc_pty);
1099         if (ret != BLUETOOTH_ERROR_NONE) {
1100                 BT_ERR("Get primary service failed ");
1101                 return ret;
1102         }
1103
1104         if (bluetooth_gatt_get_service_property(service_handle, &svc_pty) !=
1105                                                         BLUETOOTH_ERROR_NONE) {
1106                 BT_ERR("Invalid service");
1107                 return BLUETOOTH_ERROR_NOT_FOUND;
1108         }
1109
1110         char_handles = svc_pty.handle_info.handle;
1111
1112         if (char_handles == NULL)
1113                 return __discover_char_from_uuid(svc_pty.handle, char_uuid);
1114
1115         char_pty = g_new0(char_pty_req_t, 1);
1116
1117         char_pty->handle = g_malloc0((svc_pty.handle_info.count + 1) *
1118                                                         sizeof(char *));
1119         for (i = 0; i < svc_pty.handle_info.count; i++) {
1120                 char_pty->handle[i] = char_handles[i];
1121                 BT_DBG("char_path[%d] : [%s]", i, char_pty->handle[i]);
1122         }
1123         char_pty->char_uuid = g_strdup(char_uuid);
1124
1125         g_idle_add(__filter_chars_with_uuid, char_pty);
1126
1127         return BLUETOOTH_ERROR_NONE;
1128 }
1129
1130 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *characteristic)
1131 {
1132         GDBusConnection *conn;
1133         char *handle;
1134
1135         BT_CHECK_PARAMETER(characteristic, return);
1136         BT_CHECK_ENABLED(return);
1137
1138         /* Because this API is async call, so can't use dbus SMACK */
1139         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_GATT_READ_CHARACTERISTIC)
1140              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1141                 BT_ERR("Don't have a privilege to use this API");
1142                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1143         }
1144
1145         conn = _bt_init_system_gdbus_conn();
1146         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1147
1148         handle = g_strdup(characteristic);
1149         g_dbus_connection_call(conn,
1150                                 BT_BLUEZ_NAME,
1151                                 characteristic,
1152                                 BLUEZ_CHAR_INTERFACE,
1153                                 "ReadCharacteristic",
1154                                 NULL,
1155                                 G_VARIANT_TYPE("(ay)"),
1156                                 G_DBUS_CALL_FLAGS_NONE,
1157                                 -1,
1158                                 NULL,
1159                                 (GAsyncReadyCallback)
1160                                 __bluetooth_internal_read_cb,
1161                                 handle);
1162         return BLUETOOTH_ERROR_NONE;
1163 }
1164
1165 BT_EXPORT_API int bluetooth_gatt_discover_characteristic_descriptor
1166                                                                 (const char *characteristic_handle)
1167 {
1168         char *handle;
1169         GDBusConnection *conn;
1170
1171         BT_CHECK_PARAMETER(characteristic_handle, return);
1172
1173         BT_CHECK_ENABLED(return);
1174
1175         /* Because this API is async call, so can't use dbus SMACK */
1176         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_GATT_DISCOVER_CHARACTERISTICS_DESCRIPTOR)
1177              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1178                 BT_ERR("Don't have a privilege to use this API");
1179                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1180         }
1181
1182         conn = _bt_init_system_gdbus_conn();
1183         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1184         handle = g_strdup(characteristic_handle);
1185         g_dbus_connection_call(conn,
1186                                         BT_BLUEZ_NAME,
1187                                         characteristic_handle,
1188                                         BLUEZ_CHAR_INTERFACE,
1189                                         "DiscoverCharacteristicsDescriptor",
1190                                         NULL,
1191                                         G_VARIANT_TYPE("(ay)"),
1192                                         G_DBUS_CALL_FLAGS_NONE,
1193                                         -1,
1194                                         NULL,
1195                                         (GAsyncReadyCallback)
1196                                         __bluetooth_internal_get_char_desc_cb,
1197                                         handle);
1198
1199         return BLUETOOTH_ERROR_NONE;
1200 }
1201