Merge "DPM: Add basic code for device policy manager for BT." into tizen
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-gatt-client.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 <gio/gio.h>
19 #include <glib.h>
20 #include <glib/gprintf.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <stdint.h>
24
25 #include "bt-common.h"
26 #include "bt-internal-types.h"
27 #include "bt-request-sender.h"
28
29 #define GATT_SERV_INTERFACE             "org.bluez.GattService1"
30 #define GATT_CHAR_INTERFACE             "org.bluez.GattCharacteristic1"
31 #define GATT_DESC_INTERFACE             "org.bluez.GattDescriptor1"
32
33 #define GATT_USER_DESC_UUID              "00002901-0000-1000-8000-00805f9b34fb"
34 #define GATT_CHAR_CLIENT_CONF           "00002902-0000-1000-8000-00805f9b34fb"
35 #define GATT_CHAR_SERVER_CONF            "00002903-0000-1000-8000-00805f9b34fb"
36 #define GATT_CHAR_FORMAT                "00002904-0000-1000-8000-00805f9b34fb"
37
38 typedef enum {
39         TYPE_NONE,
40         USER_DESC,
41         CLIENT_CONF,
42         SERVER_CONF,
43         CHAR_FORMAT
44 }char_descriptor_type_t;
45
46 BT_EXPORT_API int bluetooth_gatt_free_service_property(bt_gatt_service_property_t *svc_pty)
47 {
48         BT_DBG("+");
49
50         BT_CHECK_PARAMETER(svc_pty, return);
51
52         g_free(svc_pty->uuid);
53         g_free(svc_pty->handle);
54         g_strfreev(svc_pty->include_handles.handle);
55         g_strfreev(svc_pty->char_handle.handle);
56
57         memset(svc_pty, 0, sizeof(bt_gatt_service_property_t));
58
59         BT_DBG("-");
60         return BLUETOOTH_ERROR_NONE;
61 }
62
63 BT_EXPORT_API int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty)
64 {
65         BT_DBG("+");
66
67         BT_CHECK_PARAMETER(char_pty, return);
68
69         g_free(char_pty->uuid);
70         g_free(char_pty->name);
71         g_free(char_pty->description);
72         g_free(char_pty->val);
73         g_free(char_pty->handle);
74         g_strfreev(char_pty->char_desc_handle.handle);
75
76         memset(char_pty, 0, sizeof(bt_gatt_char_property_t));
77
78         BT_DBG("-");
79         return BLUETOOTH_ERROR_NONE;
80 }
81
82 BT_EXPORT_API int bluetooth_gatt_free_desc_property(bt_gatt_char_descriptor_property_t *desc_pty)
83 {
84         BT_DBG("+");
85
86         BT_CHECK_PARAMETER(desc_pty, return);
87
88         g_free(desc_pty->uuid);
89         g_free(desc_pty->val);
90         g_free(desc_pty->handle);
91
92         memset(desc_pty, 0, sizeof(bt_gatt_char_descriptor_property_t));
93
94         BT_DBG("-");
95         return BLUETOOTH_ERROR_NONE;
96 }
97
98 static char **__get_string_array_from_gptr_array(GPtrArray *gp)
99 {
100         gchar *gp_path = NULL;
101         char **path = NULL;
102         int i;
103
104         if (gp->len == 0)
105                 return NULL;
106
107         path = g_malloc0((gp->len + 1) * sizeof(char *));
108
109         /* Fix : NULL_RETURNS */
110         if (path == NULL)
111                 return NULL;
112
113         for (i = 0; i < gp->len; i++) {
114                 gp_path = g_ptr_array_index(gp, i);
115                 path[i] = g_strdup(gp_path);
116                 BT_DBG("path[%d] : [%s]", i, path[i]);
117         }
118
119         return path;
120 }
121
122 BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle,
123                                                 bt_gatt_service_property_t *service)
124 {
125         GDBusProxy *properties_proxy = NULL;
126         GError *error = NULL;
127         GVariant *result = NULL;
128         GDBusConnection *g_conn;
129         gsize len;
130         char *char_handle = NULL;
131         GPtrArray *gp_array  = NULL ;
132         GVariantIter *property_iter, *char_iter;
133         const gchar *key;
134         GVariant *value;
135
136         BT_CHECK_PARAMETER(service_handle, return);
137         BT_CHECK_PARAMETER(service, return);
138         BT_CHECK_ENABLED_ANY(return);
139
140         g_conn = _bt_gdbus_get_system_gconn();
141         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
142
143         properties_proxy = g_dbus_proxy_new_sync(g_conn,
144                         G_DBUS_PROXY_FLAGS_NONE, NULL,
145                         BT_BLUEZ_NAME,
146                         service_handle,
147                         BT_PROPERTIES_INTERFACE,
148                         NULL, &error);
149
150         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
151
152         result = g_dbus_proxy_call_sync(properties_proxy,
153                                 "GetAll",
154                                 g_variant_new("(s)", GATT_SERV_INTERFACE),
155                                 G_DBUS_CALL_FLAGS_NONE,
156                                 -1,
157                                 NULL,
158                                 &error);
159
160         if (!result) {
161                 if (error != NULL) {
162                         BT_ERR("Fail to get properties (Error: %s)", error->message);
163                         g_clear_error(&error);
164                 } else
165                         BT_ERR("Fail to get properties");
166                 g_object_unref(properties_proxy);
167                 return BLUETOOTH_ERROR_INTERNAL;
168         }
169
170         g_variant_get(result, "(a{sv})", &property_iter);
171
172         memset(service, 0, sizeof(bt_gatt_service_property_t));
173
174         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
175                 if (!g_strcmp0(key,"UUID")) {
176                         service->uuid = g_variant_dup_string(value,&len);
177
178                 } else if(!g_strcmp0(key, "Primary")) {
179                         service->primary = g_variant_get_boolean(value);
180
181                 } else if (!g_strcmp0(key, "Includes")) {
182                         g_variant_get(value, "ao", &char_iter);
183                         gp_array = g_ptr_array_new();
184                         while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
185                                 g_ptr_array_add(gp_array, (gpointer)char_handle);
186                         }
187                         if (gp_array->len != 0) {
188                                 service->include_handles.count = gp_array->len;
189                                 service->include_handles.handle =
190                                                 __get_string_array_from_gptr_array(gp_array);
191                         }
192                         g_ptr_array_free(gp_array, TRUE);
193                 } else if (!g_strcmp0(key, "Characteristics")) {
194                         g_variant_get(value, "ao", &char_iter);
195                         gp_array = g_ptr_array_new();
196                         while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
197                                 g_ptr_array_add(gp_array, (gpointer)char_handle);
198                         }
199                         if (gp_array->len != 0) {
200                                 service->char_handle.count = gp_array->len;
201                                 service->char_handle.handle =
202                                                 __get_string_array_from_gptr_array(gp_array);
203                         }
204                         g_ptr_array_free(gp_array, TRUE);
205                 }
206         }
207
208         service->handle = g_strdup(service_handle);
209
210         g_variant_iter_free(property_iter);
211         g_variant_unref(result);
212         g_object_unref(properties_proxy);
213
214         return BLUETOOTH_ERROR_NONE;
215 }
216
217 BT_EXPORT_API int bluetooth_gatt_get_primary_services(
218                 const bluetooth_device_address_t *address,
219                 bt_gatt_handle_info_t *prim_svc)
220 {
221         GVariant *result = NULL;
222         GVariantIter *iter;
223         GVariantIter *svc_iter;
224         GVariantIter *interface_iter;
225         char *object_path = NULL;
226         char *interface_str = NULL;
227         const gchar *key = NULL;
228         GVariant *value = NULL;
229         GPtrArray *gp_array  = NULL;
230         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
231         char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
232         int ret = BLUETOOTH_ERROR_INTERNAL;
233
234         BT_INFO("+");
235         BT_CHECK_PARAMETER(address, return);
236         BT_CHECK_PARAMETER(prim_svc, return);
237         BT_CHECK_ENABLED_ANY(return);
238
239         result = _bt_get_managed_objects();
240         if (result == NULL)
241                 return ret;
242
243         _bt_convert_addr_type_to_string(device_address,
244                         (unsigned char *)address->addr);
245
246         gp_array = g_ptr_array_new();
247         g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
248
249         while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
250                         &interface_iter)) {
251                 if (object_path == NULL)
252                         continue;
253
254                 _bt_convert_device_path_to_address(object_path, temp_address);
255
256                 if (g_strcmp0(temp_address, device_address) != 0)
257                         continue;
258
259                 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
260                                 &interface_str, &svc_iter)) {
261                         if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
262                                 continue;
263
264                         BT_DBG("Object Path: %s", object_path);
265                         while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
266                                 if (g_strcmp0(key, "Primary") == 0) {
267                                         if (g_variant_get_boolean(value))
268                                                 g_ptr_array_add(gp_array, (gpointer)object_path);
269                                 }
270                         }
271                 }
272         }
273
274         if (gp_array->len == 0) {
275                 BT_ERR("gp_array is NULL");
276                 ret = BLUETOOTH_ERROR_NOT_FOUND;
277         } else {
278                 ret = BLUETOOTH_ERROR_NONE;
279                 prim_svc->count = gp_array->len;
280                 prim_svc->handle = __get_string_array_from_gptr_array(gp_array);
281         }
282
283         g_ptr_array_free(gp_array, TRUE);
284         g_variant_iter_free(iter);
285         g_variant_unref(result);
286         BT_DBG("-");
287         return ret;
288 }
289
290 BT_EXPORT_API int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address,
291                         const char *service_uuid,
292                         bt_gatt_service_property_t *service)
293 {
294         GVariant *result = NULL;
295         GVariantIter *iter;
296         GVariantIter *svc_iter;
297         GVariantIter *interface_iter;
298         char *object_path = NULL;
299         char *interface_str = NULL;
300         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
301         char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
302         int ret = BLUETOOTH_ERROR_INTERNAL;
303
304         BT_CHECK_PARAMETER(address, return);
305         BT_CHECK_PARAMETER(service_uuid, return);
306         BT_CHECK_PARAMETER(service, return);
307         BT_CHECK_ENABLED_ANY(return);
308
309         result = _bt_get_managed_objects();
310         if (result == NULL)
311                 return ret;
312
313         _bt_convert_addr_type_to_string(device_address,
314                                 (unsigned char *)address->addr);
315
316         g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
317
318         while (g_variant_iter_loop(iter, "{oa{sa{sv}}}", &object_path,
319                         &interface_iter)) {
320                 if (object_path == NULL)
321                         continue;
322
323                 _bt_convert_device_path_to_address(object_path,
324                                 temp_address);
325
326                 if (g_strcmp0(temp_address, device_address) != 0)
327                         continue;
328
329                 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
330                                 &interface_str, &svc_iter)) {
331                         if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
332                                 continue;
333
334                         BT_DBG("Object Path: %s", object_path);
335                         ret = bluetooth_gatt_get_service_property(object_path,
336                                         service);
337
338                         if (ret != BLUETOOTH_ERROR_NONE) {
339                                 BT_ERR("Get service property failed(0x%08x)", ret);
340                         } else {
341                                 if (service->primary == TRUE &&
342                                                 g_strstr_len(service->uuid, -1,
343                                                                 service_uuid)) {
344                                         ret = BLUETOOTH_ERROR_NONE;
345                                         goto done;
346                                 }
347                         }
348                         bluetooth_gatt_free_service_property(service);
349                 }
350         }
351
352 done:
353         g_variant_iter_free(iter);
354         g_variant_unref(result);
355
356         return ret;
357 }
358
359 static void __bluetooth_internal_get_char_cb(GDBusProxy *proxy,
360                 GAsyncResult *res, gpointer user_data)
361 {
362         GVariant *value;
363         GVariant *char_value;
364         GVariantIter *char_iter;
365         GPtrArray *gp_array = NULL;
366         bt_gatt_discovered_char_t svc_char = { 0, };
367         char *char_handle;
368         GError *error = NULL;
369         bt_user_info_t *user_info;
370
371         BT_DBG("+");
372
373         user_info = _bt_get_user_data(BT_COMMON);
374         svc_char.service_handle = user_data;
375
376         value = g_dbus_proxy_call_finish(proxy, res, &error);
377
378         if (value == NULL) {
379                 if (error != NULL) {
380                         BT_ERR("Get service characteristics failed\n errCode[%x],"
381                                         "message[%s]\n", error->code, error->message);
382                         g_clear_error(&error);
383                 } else {
384                         BT_ERR("Get service characteristics failed\n");
385                 }
386                 if (user_info) {
387                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
388                                 BLUETOOTH_ERROR_INTERNAL, NULL,
389                                 user_info->cb, user_info->user_data);
390                 }
391                 g_free(svc_char.service_handle);
392                 g_object_unref(proxy);
393                 return;
394         }
395
396         g_variant_get(value, "(v)", &char_value);
397         g_variant_get(char_value, "ao", &char_iter);
398
399         gp_array = g_ptr_array_new();
400         while(g_variant_iter_loop(char_iter, "&o",  &char_handle));
401                 g_ptr_array_add(gp_array, (gpointer)char_handle);
402
403         if (gp_array->len != 0) {
404                 svc_char.handle_info.count = gp_array->len;
405                 svc_char.handle_info.handle =
406                         __get_string_array_from_gptr_array(gp_array);
407         }
408         g_ptr_array_free(gp_array, TRUE);
409
410         if (user_info) {
411                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
412                         BLUETOOTH_ERROR_NONE, &svc_char,
413                         user_info->cb, user_info->user_data);
414         }
415
416         g_strfreev(svc_char.handle_info.handle);
417         g_free(svc_char.service_handle);
418         g_variant_iter_free(char_iter);
419         g_object_unref(proxy);
420 }
421
422 BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(
423                         const char *service_handle)
424 {
425         GDBusProxy *properties_proxy = NULL;
426         GDBusConnection *g_conn;
427         GError *error = NULL;
428         char *handle;
429
430         BT_DBG("+");
431
432         BT_CHECK_PARAMETER(service_handle, return);
433         BT_CHECK_ENABLED_ANY(return);
434
435         g_conn = _bt_gdbus_get_system_gconn();
436         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
437
438         properties_proxy = g_dbus_proxy_new_sync(g_conn,
439                         G_DBUS_PROXY_FLAGS_NONE, NULL,
440                         BT_BLUEZ_NAME,
441                         service_handle,
442                         BT_PROPERTIES_INTERFACE,
443                         NULL, &error);
444
445         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
446
447         handle = g_strdup(service_handle);
448         g_dbus_proxy_call(properties_proxy,
449                         "Get",
450                         g_variant_new("(ss)",
451                                 GATT_SERV_INTERFACE, "Characteristics"),
452                         G_DBUS_CALL_FLAGS_NONE,
453                         -1,
454                         NULL,
455                         (GAsyncReadyCallback)__bluetooth_internal_get_char_cb,
456                         (gpointer)handle);
457
458         BT_DBG("-");
459         return BLUETOOTH_ERROR_NONE;
460 }
461
462
463 static int __get_permission_flag(char *permission)
464 {
465         int ret = 0;
466
467         retv_if(permission == NULL, ret);
468
469         BT_DBG("permission = %s",permission);
470
471         if (!g_strcmp0(permission,"broadcast")) {
472                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
473         } else if (!g_strcmp0(permission,"read")) {
474                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
475         } else if (!g_strcmp0(permission,"write-without-response")) {
476                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
477         } else if (!g_strcmp0(permission,"write")) {
478                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
479         } else if (!g_strcmp0(permission,"notify")) {
480                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
481         } else if (!g_strcmp0(permission,"indicate")) {
482                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
483         } else if (!g_strcmp0(permission,"authenticated-signed-writes")) {
484                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
485         } else if (!g_strcmp0(permission,"reliable-write")) {
486                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS;
487         } else if (!g_strcmp0(permission,"writable-auxiliaries")) {
488                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS;
489         }
490
491         return ret;
492 }
493
494 BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
495                 const char *char_handle, bt_gatt_char_property_t *characteristic)
496 {
497         GDBusProxy *properties_proxy = NULL;
498         GError *error = NULL;
499         GVariant *value = NULL;
500         GVariant *result = NULL;
501         GByteArray *gb_array = NULL;
502         GPtrArray *gp_array  = NULL ;
503         GDBusConnection *g_conn;
504         guint8 char_value;
505         const gchar *key;
506         gchar* permission;
507         char *char_desc_handle = NULL;
508         gsize len;
509         GVariantIter *property_iter;
510         GVariantIter *char_value_iter;
511         GVariantIter *char_perm_iter;
512         GVariantIter *char_desc_iter;
513
514         BT_DBG("+");
515         BT_CHECK_PARAMETER(char_handle, return);
516         BT_CHECK_PARAMETER(characteristic, return);
517
518         BT_CHECK_ENABLED_ANY(return);
519
520         g_conn = _bt_gdbus_get_system_gconn();
521         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
522
523         properties_proxy = g_dbus_proxy_new_sync(g_conn,
524                         G_DBUS_PROXY_FLAGS_NONE, NULL,
525                         BT_BLUEZ_NAME,
526                         char_handle,
527                         BT_PROPERTIES_INTERFACE,
528                         NULL, &error);
529
530         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
531
532         result = g_dbus_proxy_call_sync(properties_proxy,
533                                 "GetAll",
534                                         g_variant_new("(s)", GATT_CHAR_INTERFACE),
535                                 G_DBUS_CALL_FLAGS_NONE,
536                                 -1,
537                                 NULL,
538                                 &error);
539
540         if (!result) {
541                 if (error != NULL) {
542                         BT_ERR("Fail to get properties (Error: %s)", error->message);
543                         g_clear_error(&error);
544                 } else
545                         BT_ERR("Fail to get properties");
546                 g_object_unref(properties_proxy);
547                 return BLUETOOTH_ERROR_INTERNAL;
548         }
549
550         g_variant_get(result, "(a{sv})", &property_iter);
551
552         memset(characteristic, 0, sizeof(bt_gatt_char_property_t));
553         characteristic->handle = g_strdup(char_handle);
554
555         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
556                 BT_DBG("property");
557                 if (!g_strcmp0(key,"UUID")) {
558                         characteristic->uuid = g_variant_dup_string(value,&len);
559                         BT_DBG("UUID of the char = %s",characteristic->uuid);
560                 } else if(!g_strcmp0(key, "Value")) {
561                         gb_array = g_byte_array_new();
562                         g_variant_get(value, "ay", &char_value_iter);
563                         while(g_variant_iter_loop(char_value_iter, "y",  &char_value)) {
564                                 BT_DBG("value of char = %d",char_value);
565                                 g_byte_array_append(gb_array, &char_value, 1);
566                         }
567                         if (gb_array->len != 0) {
568                                 characteristic->val = g_malloc0(gb_array->len *
569                                                                 sizeof(unsigned char));
570                                 memcpy(characteristic->val, gb_array->data, gb_array->len);
571                         }
572                         characteristic->val_len = gb_array->len;
573                         g_byte_array_free(gb_array, TRUE);
574                 } else if(!g_strcmp0(key, "Flags")) {
575                         g_variant_get(value, "as", &char_perm_iter);
576                         characteristic->permission = 0x00;
577                         while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
578                                 BT_DBG("permission = %s",permission);
579                                 characteristic->permission |= __get_permission_flag(permission);
580                                 BT_DBG("permission check = %d",characteristic->permission);
581                         }
582                         g_variant_iter_free(char_perm_iter);
583                 } else if (!g_strcmp0(key, "Descriptors")) {
584                         g_variant_get(value, "ao", &char_desc_iter);
585                         gp_array = g_ptr_array_new();
586                         while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
587                                 g_ptr_array_add(gp_array, (gpointer)char_desc_handle);
588                         }
589                         if (gp_array->len != 0) {
590                                 characteristic->char_desc_handle.count = gp_array->len;
591                                 characteristic->char_desc_handle.handle =
592                                                 __get_string_array_from_gptr_array(gp_array);
593                         }
594                         g_ptr_array_free(gp_array, TRUE);
595                 }
596         }
597
598         g_variant_iter_free(property_iter);
599         g_variant_unref(result);
600         g_object_unref(properties_proxy);
601
602         BT_DBG("-");
603         return BLUETOOTH_ERROR_NONE;
604 }
605
606 void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy,
607                         GAsyncResult *res, gpointer user_data)
608 {
609         GVariant *value;
610         GVariantIter *char_iter;
611         int i, len;
612         char *char_handle;
613         GError *error = NULL;
614         bt_user_info_t *user_info;
615         int ret = BLUETOOTH_ERROR_INTERNAL;
616         bt_gatt_char_property_t characteristic;
617
618         user_info = _bt_get_user_data(BT_COMMON);
619
620         value = g_dbus_proxy_call_finish(proxy, res, &error);
621
622         if (value == NULL) {
623                 if (error != NULL) {
624                         BT_ERR("Get service characteristics failed\n errCode[%x],"
625                                         "message[%s]\n", error->code, error->message);
626                         g_clear_error(&error);
627                 } else {
628                         BT_ERR("Get service characteristics failed\n");
629                 }
630                 if (user_info) {
631                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
632                                 BLUETOOTH_ERROR_INTERNAL, NULL,
633                                 user_info->cb, user_info->user_data);
634                 }
635                 g_object_unref(proxy);
636                 g_free(user_data);
637                 return;
638         }
639
640         g_variant_get(value, "(ao)", &char_iter);
641
642         len = g_variant_get_size((GVariant *)char_iter);
643
644         for (i = 0; i < len; i++) {
645                 g_variant_iter_loop(char_iter, "o",  &char_handle);
646                 if (!char_handle)
647                         continue;
648                 ret = bluetooth_gatt_get_characteristics_property(char_handle,
649                                 &characteristic);
650
651                 if (ret != BLUETOOTH_ERROR_NONE) {
652                         BT_ERR("Get characteristic property failed(0x%08x)", ret);
653                 } else {
654                         if (g_strstr_len(characteristic.uuid, -1, user_data)) {
655                                 ret = BLUETOOTH_ERROR_NONE;
656                                 break;
657                         }
658                 }
659                 bluetooth_gatt_free_char_property(&characteristic);
660         }
661
662         if (user_info) {
663                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret,
664                                 &characteristic, user_info->cb, user_info->user_data);
665         }
666
667         bluetooth_gatt_free_char_property(&characteristic);
668         g_variant_iter_free(char_iter);
669         g_free(user_data);
670 }
671
672 BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
673                                                 const char *char_uuid)
674 {
675         GDBusProxy *properties_proxy = NULL;
676         GDBusConnection *g_conn;
677         GError *error = NULL;
678         char *uuid;
679
680         BT_CHECK_PARAMETER(service_handle, return);
681         BT_CHECK_PARAMETER(char_uuid, return);
682         BT_CHECK_ENABLED_ANY(return);
683
684         g_conn = _bt_gdbus_get_system_gconn();
685         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
686
687         properties_proxy = g_dbus_proxy_new_sync(g_conn,
688                         G_DBUS_PROXY_FLAGS_NONE, NULL,
689                         BT_BLUEZ_NAME,
690                         service_handle,
691                         BT_PROPERTIES_INTERFACE,
692                         NULL, &error);
693
694         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
695
696         uuid = g_strdup(char_uuid);
697         g_dbus_proxy_call(properties_proxy,
698                         "Get",
699                         g_variant_new("(ss)",
700                                 GATT_SERV_INTERFACE, "Characteristics"),
701                         G_DBUS_CALL_FLAGS_NONE,
702                         -1,
703                         NULL,
704                         (GAsyncReadyCallback)bluetooth_gatt_get_char_from_uuid_cb,
705                         (gpointer)uuid);
706
707         return BLUETOOTH_ERROR_NONE;
708 }
709
710 BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
711                 const char *descriptor_handle, bt_gatt_char_descriptor_property_t *descriptor)
712 {
713         GDBusProxy *properties_proxy = NULL;
714         GError *error = NULL;
715         GDBusConnection *g_conn;
716         GVariant *result = NULL;
717         GVariantIter *property_iter;
718         const gchar *key;
719         guint8 char_value;
720         gsize len;
721         GVariant *value = NULL;
722         GByteArray *gb_array = NULL;
723         GVariantIter *desc_value_iter;
724
725         BT_DBG("+");
726         BT_CHECK_PARAMETER(descriptor_handle, return);
727         BT_CHECK_PARAMETER(descriptor, return);
728
729         BT_CHECK_ENABLED_ANY(return);
730
731         g_conn = _bt_gdbus_get_system_gconn();
732         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
733
734         properties_proxy = g_dbus_proxy_new_sync(g_conn,
735                         G_DBUS_PROXY_FLAGS_NONE, NULL,
736                         BT_BLUEZ_NAME,
737                         descriptor_handle,
738                         BT_PROPERTIES_INTERFACE,
739                         NULL, &error);
740
741         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
742
743         result = g_dbus_proxy_call_sync(properties_proxy,
744                                 "GetAll",
745                                         g_variant_new("(s)", GATT_DESC_INTERFACE),
746                                 G_DBUS_CALL_FLAGS_NONE,
747                                 -1,
748                                 NULL,
749                                 &error);
750
751         if (!result) {
752                 if (error != NULL) {
753                         BT_ERR("Fail to get properties (Error: %s)", error->message);
754                         g_clear_error(&error);
755                 } else
756                         BT_ERR("Fail to get properties");
757                 g_object_unref(properties_proxy);
758                 return BLUETOOTH_ERROR_INTERNAL;
759         }
760
761         g_variant_get(result, "(a{sv})", &property_iter);
762
763         memset(descriptor, 0, sizeof(bt_gatt_char_descriptor_property_t));
764         descriptor->handle = g_strdup(descriptor_handle);
765
766         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
767                 BT_DBG("property");
768                 if (!g_strcmp0(key,"UUID")) {
769                         descriptor->uuid = g_variant_dup_string(value,&len);
770                         BT_DBG("UUID of the char_desc = %s",descriptor->uuid);
771                 } else if(!g_strcmp0(key, "Value")) {
772                         gb_array = g_byte_array_new();
773                         g_variant_get(value, "ay", &desc_value_iter);
774                         while(g_variant_iter_loop(desc_value_iter, "y",  &char_value)) {
775                                 BT_DBG("value of descriptor = %d",char_value);
776                                 g_byte_array_append(gb_array, &char_value, 1);
777                         }
778                         if (gb_array->len != 0) {
779                                 descriptor->val = g_malloc0(gb_array->len *
780                                                                 sizeof(unsigned char));
781                                 memcpy(descriptor->val, gb_array->data, gb_array->len);
782                         }
783                         descriptor->val_len = gb_array->len;
784                         g_byte_array_free(gb_array, TRUE);
785                 }
786         }
787
788         g_variant_iter_free(property_iter);
789         g_variant_unref(result);
790         g_object_unref(properties_proxy);
791
792         BT_DBG("-");
793         return BLUETOOTH_ERROR_NONE;
794 }
795
796 static void __bluetooth_internal_read_cb(GObject *source_object,
797                         GAsyncResult *res,
798                         gpointer user_data)
799 {
800         GError *error = NULL;
801         bt_user_info_t *user_info;
802         bt_gatt_char_value_t char_value =  { 0, };
803         GDBusConnection *system_gconn = NULL;
804         GVariant *value;
805         GByteArray *gp_byte_array = NULL;
806         GVariantIter *iter;
807         guint8 g_byte;
808
809         BT_DBG("+");
810         user_info = _bt_get_user_data(BT_COMMON);
811
812         system_gconn = _bt_gdbus_get_system_gconn();
813         value = g_dbus_connection_call_finish(system_gconn, res, &error);
814
815         if (error) {
816                 BT_ERR("Error : %s \n", error->message);
817                 g_clear_error(&error);
818                 if (user_info) {
819                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
820                                 BLUETOOTH_ERROR_INTERNAL, NULL,
821                                 user_info->cb, user_info->user_data);
822                 }
823                 g_free(user_data);
824                 return;
825         }
826
827         char_value.char_handle = user_data;
828         gp_byte_array = g_byte_array_new();
829         g_variant_get(value, "(ay)", &iter);
830
831         while (g_variant_iter_loop(iter, "y", &g_byte)) {
832                 g_byte_array_append(gp_byte_array, &g_byte, 1);
833         }
834
835         if (gp_byte_array->len != 0) {
836                 char_value.val_len = gp_byte_array->len;
837                 char_value.char_value = gp_byte_array->data;
838         }
839
840         if (user_info) {
841                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
842                                 BLUETOOTH_ERROR_NONE, &char_value,
843                                 user_info->cb, user_info->user_data);
844         }
845
846         g_free(char_value.char_handle);
847         g_byte_array_free(gp_byte_array, TRUE);
848         g_variant_unref(value);
849         g_variant_iter_free(iter);
850
851         BT_DBG("-");
852 }
853
854 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *characteristic)
855 {
856         GDBusConnection *conn;
857         char *handle;
858
859         BT_CHECK_PARAMETER(characteristic, return);
860         BT_CHECK_ENABLED_ANY(return);
861
862         conn = _bt_gdbus_get_system_gconn();
863         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
864
865         handle = g_strdup(characteristic);
866
867         g_dbus_connection_call(conn,
868                         BT_BLUEZ_NAME,
869                         characteristic,
870                         GATT_CHAR_INTERFACE,
871                         "ReadValue",
872                         NULL,
873                         G_VARIANT_TYPE("(ay)"),
874                         G_DBUS_CALL_FLAGS_NONE,
875                         -1,
876                         NULL,
877                         (GAsyncReadyCallback)__bluetooth_internal_read_cb,
878                         (gpointer)handle);
879
880         return BLUETOOTH_ERROR_NONE;
881 }
882
883 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
884                 const char *char_handle, const guint8 *value, int length)
885 {
886         GVariant *val;
887         GVariantBuilder *builder;
888         GError *error = NULL;
889         GDBusConnection *conn;
890         int i = 0;
891
892         BT_DBG("+");
893         BT_CHECK_PARAMETER(char_handle, return);
894         BT_CHECK_PARAMETER(value, return);
895         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
896         BT_CHECK_ENABLED_ANY(return);
897
898         conn = _bt_gdbus_get_system_gconn();
899         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
900
901         builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
902
903         for (i = 0; i < length; i++) {
904                 g_variant_builder_add(builder, "y", value[i]);
905         }
906
907         val = g_variant_new("(ay)", builder);
908
909         g_dbus_connection_call_sync(conn,
910                         BT_BLUEZ_NAME,
911                         char_handle,
912                         GATT_CHAR_INTERFACE,
913                         "WriteValue",
914                         val,
915                         NULL,
916                         G_DBUS_CALL_FLAGS_NONE,
917                         -1, NULL, &error);
918
919         if (error) {
920                 BT_ERR("Set value Failed: %s", error->message);
921                 g_clear_error(&error);
922                 g_variant_builder_unref(builder);
923                 return BLUETOOTH_ERROR_INTERNAL;
924         }
925
926         g_variant_builder_unref(builder);
927
928         BT_DBG("-");
929         return BLUETOOTH_ERROR_NONE;
930 }
931
932 static void __bluetooth_internal_write_cb(GObject *source_object,
933                         GAsyncResult *res,
934                         gpointer user_data)
935 {
936         BT_DBG("+");
937         GError *error = NULL;
938         bt_user_info_t *user_info;
939         GDBusConnection *system_gconn = NULL;
940         GVariant *value;
941         int result = BLUETOOTH_ERROR_NONE;
942
943         user_info = _bt_get_user_data(BT_COMMON);
944
945         system_gconn = _bt_gdbus_get_system_gconn();
946         value = g_dbus_connection_call_finish(system_gconn, res, &error);
947
948         if (error) {
949                 BT_ERR("Error : %s \n", error->message);
950                 g_clear_error(&error);
951                 result = BLUETOOTH_ERROR_INTERNAL;
952         }
953         if (user_info) {
954                 BT_DBG("result = %d", result);
955                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
956                                 result, NULL,
957                                 user_info->cb, user_info->user_data);
958         }
959
960         if (value)
961                 g_variant_unref(value);
962         BT_DBG("-");
963         return;
964 }
965
966 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
967                 const char *char_handle, const guint8 *value, int length, guint8 write_type)
968 {
969         GVariant *val;
970         GVariantBuilder *builder;
971         GDBusConnection *conn;
972         int i = 0;
973         int ret = BLUETOOTH_ERROR_NONE;
974
975         BT_CHECK_PARAMETER(char_handle, return);
976         BT_CHECK_PARAMETER(value, return);
977         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
978         BT_CHECK_ENABLED_ANY(return);
979
980         conn = _bt_gdbus_get_system_gconn();
981         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
982
983         builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
984
985         for (i = 0; i < length; i++) {
986                 g_variant_builder_add(builder, "y", value[i]);
987         }
988
989         val = g_variant_new("ay", builder);
990         g_dbus_connection_call(conn,
991                         BT_BLUEZ_NAME,
992                         char_handle,
993                         GATT_CHAR_INTERFACE,
994                         "WriteValuebyType",
995                         g_variant_new("(y@ay)", write_type, val),
996                         NULL,
997                         G_DBUS_CALL_FLAGS_NONE,
998                         -1, NULL,
999                         (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1000                         NULL);
1001
1002         g_variant_builder_unref(builder);
1003         return ret;
1004 }
1005
1006 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
1007                         const char *char_handle, const guint8 *value, int length)
1008 {
1009         GVariant *val;
1010         GDBusConnection *conn;
1011         GVariantBuilder *builder;
1012         int i;
1013
1014         BT_DBG("+");
1015         BT_CHECK_PARAMETER(char_handle, return);
1016         BT_CHECK_PARAMETER(value, return);
1017         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1018         BT_CHECK_ENABLED_ANY(return);
1019
1020         conn = _bt_gdbus_get_system_gconn();
1021         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1022
1023         builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1024
1025         for (i = 0; i < length; i++) {
1026                 g_variant_builder_add(builder, "y", value[i]);
1027                 BT_DBG("value [] = %d", value[i]);
1028         }
1029
1030         val = g_variant_new("(ay)", builder);
1031
1032         g_dbus_connection_call(conn,
1033                                 BT_BLUEZ_NAME,
1034                                 char_handle,
1035                                 GATT_CHAR_INTERFACE,
1036                                 "WriteValue",
1037                                 val,
1038                                 NULL,
1039                                 G_DBUS_CALL_FLAGS_NONE,
1040                                 -1, NULL,
1041                                 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1042                                 NULL);
1043
1044         g_variant_builder_unref(builder);
1045
1046         BT_DBG("-");
1047         return BLUETOOTH_ERROR_NONE;
1048 }
1049
1050 static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
1051                         bt_gatt_char_property_t *characteristic)
1052 {
1053         BT_DBG("+");
1054         GDBusProxy *properties_proxy = NULL;
1055         GError *error = NULL;
1056         GVariant *value = NULL;
1057         GVariant *result = NULL;
1058         GDBusConnection *g_conn;
1059         int i, ret = BLUETOOTH_ERROR_NONE;
1060         const char *uuid = NULL;
1061         gsize len = 0;
1062         GVariantIter *desc_value_iter, *property_iter;
1063         const gchar *key;
1064         char_descriptor_type_t desc_type = TYPE_NONE;
1065
1066         g_conn = _bt_gdbus_get_system_gconn();
1067         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1068
1069         properties_proxy = g_dbus_proxy_new_sync(g_conn,
1070                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1071                         BT_BLUEZ_NAME,
1072                         char_handle,
1073                         BT_PROPERTIES_INTERFACE,
1074                         NULL, &error);
1075
1076         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1077
1078         result = g_dbus_proxy_call_sync(properties_proxy,
1079                                 "GetAll",
1080                                 g_variant_new("(s)", GATT_DESC_INTERFACE),
1081                                 G_DBUS_CALL_FLAGS_NONE,
1082                                 -1,
1083                                 NULL,
1084                                 &error);
1085
1086         if (!result) {
1087                 if (error != NULL) {
1088                         BT_ERR("Fail to get properties (Error: %s)", error->message);
1089                         g_clear_error(&error);
1090                 } else
1091                         BT_ERR("Fail to get properties");
1092                 g_object_unref(properties_proxy);
1093                 return BLUETOOTH_ERROR_INTERNAL;
1094         }
1095         g_variant_get(result, "(a{sv})", &property_iter);
1096         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1097                 if (!g_strcmp0(key,"UUID")) {
1098                         uuid = g_variant_get_string(value, &len);
1099                         if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
1100                                 BT_DBG("GATT_USER_DESC_UUID");
1101                                 desc_type = USER_DESC;
1102                         } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) {
1103                                 BT_DBG("GATT_CHAR_FORMAT");
1104                                 desc_type = CHAR_FORMAT;
1105                         } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) {
1106                                 BT_DBG("GATT_CHAR_CLIENT_CONF");
1107                                 desc_type = CLIENT_CONF;
1108                         } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) {
1109                                 BT_DBG("GATT_CHAR_SERVER_CONF");
1110                                 desc_type = SERVER_CONF;
1111                         } else {
1112                                 BT_DBG("descriptor uuid = %s", uuid);
1113                         }
1114                 } else if (!g_strcmp0(key, "Value")) {
1115                         switch(desc_type) {
1116                                 case CHAR_FORMAT :
1117                                         BT_DBG("Format descriptor");
1118                                         g_variant_get(value, "(yyqyq)",
1119                                                         &(characteristic->format.format),
1120                                                         &(characteristic->format.exponent),
1121                                                         &(characteristic->format.unit),
1122                                                         &(characteristic->format.name_space),
1123                                                         &(characteristic->format.description));
1124                                         break;
1125                                 case USER_DESC:
1126                                         BT_DBG("User descriptor");
1127                                         g_variant_get(value, "ay", &desc_value_iter);
1128                                         len = g_variant_get_size((GVariant *)desc_value_iter);
1129
1130                                         if (len > 0) {
1131                                                 characteristic->description = (char *)g_malloc0(len + 1);
1132                                                 if (!characteristic->description) {
1133                                                         ret = BLUETOOTH_ERROR_OUT_OF_MEMORY;
1134                                                         goto done;
1135                                                 }
1136                                         }
1137                                         for (i = 0; i < len; i++) {
1138                                                 g_variant_iter_loop(desc_value_iter, "y",
1139                                                         &characteristic->description[i]);
1140                                                 BT_DBG("description = %s", characteristic->description);
1141                                         }
1142                                         break;
1143                                 case CLIENT_CONF :
1144                                         BT_DBG(" CLIENT_CONF");
1145                                         break;
1146                                 case SERVER_CONF :
1147                                         BT_DBG(" SERVER_CONF");
1148                                         break;
1149                                 default:break;
1150                         }
1151                 }
1152         }
1153
1154 done:
1155         g_variant_iter_free(property_iter);
1156         g_variant_unref(result);
1157         g_object_unref(properties_proxy);
1158
1159         BT_DBG("-");
1160         return ret;
1161 }
1162
1163
1164 static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
1165                         GAsyncResult *res, gpointer user_data)
1166 {
1167         BT_DBG("+");
1168         GVariant *value;
1169         GVariant        *char_value;
1170         GVariantIter *char_iter;
1171         char *char_handle;
1172         GError *error = NULL;
1173         bt_user_info_t *user_info;
1174         bt_gatt_char_property_t characteristic = {0, };
1175         int ret = BLUETOOTH_ERROR_INTERNAL;
1176
1177         user_info = _bt_get_user_data(BT_COMMON);
1178
1179         value = g_dbus_proxy_call_finish(proxy, res, &error);
1180
1181         if (value == NULL) {
1182                 if (error != NULL) {
1183                         BT_ERR("Get characteristic descriptor failed\n errCode[%x],"
1184                                         "message[%s]\n", error->code, error->message);
1185                         g_clear_error(&error);
1186                 } else {
1187                         BT_ERR("Get characteristic descriptor failed\n");
1188                 }
1189                 if (user_info) {
1190                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1191                                 BLUETOOTH_ERROR_INTERNAL, NULL,
1192                                 user_info->cb, user_info->user_data);
1193                 }
1194                 g_free(user_data);
1195                 g_object_unref(proxy);
1196                 return;
1197         }
1198
1199         g_variant_get(value, "(v)", &char_value);
1200         g_variant_get(char_value, "ao", &char_iter);
1201
1202         while(g_variant_iter_loop(char_iter, "&o",  &char_handle)) {
1203                 BT_DBG("object path of descriptor = %s",char_handle);
1204                 if(char_handle) {
1205                                 ret = __bluetooth_gatt_descriptor_iter(char_handle,
1206                                                         &characteristic);
1207                                 BT_DBG("Descriptor read status [%d]",ret);
1208                 }
1209         }
1210
1211         characteristic.handle = user_data;
1212         if (user_info) {
1213                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1214                                 ret, &characteristic, user_info->cb, user_info->user_data);
1215         }
1216         bluetooth_gatt_free_char_property(&characteristic);
1217
1218         g_variant_iter_free(char_iter);
1219         BT_DBG("-");
1220 }
1221
1222 BT_EXPORT_API int bluetooth_gatt_discover_characteristic_descriptor(
1223                         const char *characteristic_handle)
1224 {
1225         GDBusProxy *properties_proxy = NULL;
1226         GDBusConnection *g_conn;
1227         char *handle;
1228         GError *error = NULL;
1229
1230         BT_CHECK_PARAMETER(characteristic_handle, return);
1231         BT_CHECK_ENABLED_ANY(return);
1232
1233         g_conn = _bt_gdbus_get_system_gconn();
1234         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1235
1236         properties_proxy = g_dbus_proxy_new_sync(g_conn,
1237                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1238                         BT_BLUEZ_NAME,
1239                         characteristic_handle,
1240                         BT_PROPERTIES_INTERFACE,
1241                         NULL, &error);
1242
1243         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1244
1245         handle = g_strdup(characteristic_handle);
1246         g_dbus_proxy_call(properties_proxy,
1247                         "Get",
1248                         g_variant_new("(ss)",
1249                                 GATT_CHAR_INTERFACE, "Descriptors"),
1250                         G_DBUS_CALL_FLAGS_NONE,
1251                         -1, NULL,
1252                         (GAsyncReadyCallback)bluetooth_gatt_get_char_desc_cb,
1253                         (gpointer)handle);
1254
1255         return BLUETOOTH_ERROR_NONE;
1256 }
1257
1258 static void __bluetooth_internal_read_desc_cb(GObject *source_object,
1259                         GAsyncResult *res,
1260                         gpointer user_data)
1261 {
1262         GError *error = NULL;
1263         bt_user_info_t *user_info;
1264         bt_gatt_char_property_t char_value =  { 0, };
1265         GDBusConnection *system_gconn = NULL;
1266         GVariant *value;
1267         GByteArray *gp_byte_array = NULL;
1268         GVariantIter *iter;
1269         guint8 g_byte;
1270
1271         BT_DBG("+");
1272         user_info = _bt_get_user_data(BT_COMMON);
1273         system_gconn = _bt_gdbus_get_system_gconn();
1274
1275         char_value.handle = user_data;
1276         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1277
1278         if (error) {
1279                 BT_ERR("Error : %s \n", error->message);
1280                 g_clear_error(&error);
1281                 if (user_info) {
1282                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1283                                         BLUETOOTH_ERROR_INTERNAL, NULL,
1284                                         user_info->cb, user_info->user_data);
1285                 }
1286                 g_free(char_value.handle);
1287                 return;
1288         }
1289
1290         gp_byte_array = g_byte_array_new();
1291         g_variant_get(value, "(ay)", &iter);
1292
1293         while(g_variant_iter_loop(iter, "y",  &g_byte)) {
1294                 g_byte_array_append(gp_byte_array, &g_byte, 1);
1295         }
1296
1297         if (gp_byte_array->len != 0) {
1298                 char_value.val_len = (unsigned int )gp_byte_array->len;
1299                 char_value.description= (char *)gp_byte_array->data;
1300         }
1301
1302         if (user_info) {
1303                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1304                                 BLUETOOTH_ERROR_NONE, &char_value,
1305                                 user_info->cb, user_info->user_data);
1306         }
1307
1308         g_byte_array_free(gp_byte_array, TRUE);
1309         g_free(char_value.handle);
1310         g_variant_unref(value);
1311         g_variant_iter_free(iter);
1312
1313         BT_DBG("-");
1314 }
1315
1316 BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *char_descriptor)
1317 {
1318         GDBusConnection *conn;
1319         char *handle;
1320
1321         BT_DBG("+");
1322         BT_CHECK_PARAMETER(char_descriptor, return);
1323         BT_CHECK_ENABLED_ANY(return);
1324
1325         conn = _bt_gdbus_get_system_gconn();
1326         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1327
1328         handle = g_strdup(char_descriptor);
1329
1330         g_dbus_connection_call(conn,
1331                         BT_BLUEZ_NAME,
1332                         char_descriptor,
1333                         GATT_DESC_INTERFACE,
1334                         "ReadValue",
1335                         NULL,
1336                         G_VARIANT_TYPE("(ay)"),
1337                         G_DBUS_CALL_FLAGS_NONE,
1338                         -1,
1339                         NULL,
1340                         (GAsyncReadyCallback)__bluetooth_internal_read_desc_cb,
1341                         (gpointer)handle);
1342
1343         BT_DBG("-");
1344         return BLUETOOTH_ERROR_NONE;
1345 }
1346
1347 static void __bluetooth_internal_write_desc_cb(GObject *source_object,
1348                         GAsyncResult *res,
1349                         gpointer user_data)
1350 {
1351         GError *error = NULL;
1352         bt_user_info_t *user_info;
1353         GDBusConnection *system_gconn = NULL;
1354         GVariant *value;
1355         int result = BLUETOOTH_ERROR_NONE;
1356
1357         BT_DBG("+");
1358         user_info = _bt_get_user_data(BT_COMMON);
1359
1360         system_gconn = _bt_gdbus_get_system_gconn();
1361         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1362
1363         if (error) {
1364                 BT_ERR("Error : %s \n", error->message);
1365                 g_clear_error(&error);
1366                 result = BLUETOOTH_ERROR_INTERNAL;
1367         }
1368         if (user_info) {
1369                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1370                                 result, NULL,
1371                                 user_info->cb, user_info->user_data);
1372         }
1373
1374         if(value)
1375                 g_variant_unref(value);
1376
1377         BT_DBG("-");
1378 }
1379
1380 BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(
1381                         const char *desc_handle, const guint8 *value, int length)
1382 {
1383         GVariant *val;
1384         GDBusConnection *conn;
1385         GVariantBuilder *builder;
1386         int i;
1387
1388         BT_DBG("+");
1389         BT_CHECK_PARAMETER(desc_handle, return);
1390         BT_CHECK_PARAMETER(value, return);
1391         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1392         BT_CHECK_ENABLED_ANY(return);
1393
1394         conn = _bt_gdbus_get_system_gconn();
1395         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1396
1397         builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1398
1399         for (i = 0; i < length; i++) {
1400                 g_variant_builder_add(builder, "y", value[i]);
1401         }
1402
1403         val = g_variant_new("(ay)", builder);
1404
1405         g_dbus_connection_call(conn,
1406                                 BT_BLUEZ_NAME,
1407                                 desc_handle,
1408                                 GATT_DESC_INTERFACE,
1409                                 "WriteValue",
1410                                 val,
1411                                 NULL,
1412                                 G_DBUS_CALL_FLAGS_NONE,
1413                                 -1, NULL,
1414                                 (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
1415                                 NULL);
1416
1417         g_variant_builder_unref(builder);
1418
1419         BT_DBG("-");
1420         return BLUETOOTH_ERROR_NONE;
1421 }
1422
1423 #ifndef GATT_NO_RELAY
1424 static int __bluetooth_gatt_watch_characteristics(void)
1425 {
1426         int result = BLUETOOTH_ERROR_NONE;
1427
1428         BT_INIT_PARAMS();
1429         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1430
1431         result = _bt_send_request(BT_BLUEZ_SERVICE,
1432                         BT_GATT_WATCH_CHARACTERISTIC,
1433                         in_param1, in_param2, in_param3, in_param4, &out_param);
1434
1435         if (result != BLUETOOTH_ERROR_NONE)
1436                         BT_ERR("Watch Characteristic request failed !");
1437
1438         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1439         return result;
1440 }
1441 #endif
1442
1443 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle)
1444 {
1445
1446         GDBusConnection *conn;
1447         GError *error = NULL;
1448         int ret = BLUETOOTH_ERROR_NONE;
1449         BT_DBG("+");
1450         BT_CHECK_PARAMETER(char_handle, return);
1451
1452         BT_CHECK_ENABLED_ANY(return);
1453
1454         BT_DBG("Entered characteristic handle:%s \n ", char_handle);
1455
1456         conn = _bt_gdbus_get_system_gconn();
1457         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1458
1459         g_dbus_connection_call_sync(conn,
1460                         BT_BLUEZ_NAME,
1461                         char_handle,
1462                         GATT_CHAR_INTERFACE,
1463                         "StartNotify",
1464                         NULL,
1465                         NULL,
1466                         G_DBUS_CALL_FLAGS_NONE,
1467                         -1, NULL, &error);
1468
1469         if (error) {
1470                 BT_ERR("Watch Failed: %s", error->message);
1471                 if (g_strrstr(error->message, "Already notifying"))
1472                         ret = BLUETOOTH_ERROR_NONE;
1473                 else if (g_strrstr(error->message, "In Progress"))
1474                         ret = BLUETOOTH_ERROR_IN_PROGRESS;
1475                 else if (g_strrstr(error->message, "Operation is not supported"))
1476                         ret = BLUETOOTH_ERROR_NOT_SUPPORT;
1477 /*failed because of either Insufficient Authorization or Write Not Permitted */
1478                 else if (g_strrstr(error->message, "Write not permitted") ||
1479                                 g_strrstr(error->message, "Operation Not Authorized"))
1480                         ret = BLUETOOTH_ERROR_PERMISSION_DEINED;
1481 /* failed because of either Insufficient Authentication,
1482         Insufficient Encryption Key Size, or Insufficient Encryption. */
1483                 else if (g_strrstr(error->message, "Not paired"))
1484                         ret = BLUETOOTH_ERROR_NOT_PAIRED;
1485                 else
1486                         ret = BLUETOOTH_ERROR_INTERNAL;
1487
1488                 g_clear_error(&error);
1489         }
1490 #ifndef GATT_NO_RELAY
1491         else {
1492                 /* Register the client sender to bt-service */
1493                 ret = __bluetooth_gatt_watch_characteristics();
1494         }
1495 #endif
1496
1497         return ret;
1498 }
1499
1500 #ifndef GATT_NO_RELAY
1501 static void __bluetooth_gatt_unwatch_characteristics(void)
1502 {
1503         int result = BLUETOOTH_ERROR_NONE;
1504
1505         BT_INIT_PARAMS();
1506         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1507
1508         result = _bt_send_request(BT_BLUEZ_SERVICE,
1509                         BT_GATT_UNWATCH_CHARACTERISTIC,
1510                         in_param1, in_param2, in_param3, in_param4, &out_param);
1511
1512         if (result != BLUETOOTH_ERROR_NONE)
1513                         BT_ERR("Unwatch Characteristic request failed !");
1514
1515         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1516 }
1517 #endif
1518
1519 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle)
1520 {
1521
1522         GDBusConnection *conn;
1523         GError *error = NULL;
1524         int ret = BLUETOOTH_ERROR_NONE;
1525         BT_DBG("+");
1526         BT_CHECK_PARAMETER(char_handle, return);
1527
1528         BT_CHECK_ENABLED_ANY(return);
1529
1530         BT_DBG("Entered characteristic handle:%s \n ", char_handle);
1531
1532         conn = _bt_gdbus_get_system_gconn();
1533         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1534
1535         g_dbus_connection_call_sync(conn,
1536                         BT_BLUEZ_NAME,
1537                         char_handle,
1538                         GATT_CHAR_INTERFACE,
1539                         "StopNotify",
1540                         NULL,
1541                         NULL,
1542                         G_DBUS_CALL_FLAGS_NONE,
1543                         -1, NULL, &error);
1544
1545         if (error) {
1546                 BT_ERR("Watch Failed: %s", error->message);
1547                 g_clear_error(&error);
1548                 ret =  BLUETOOTH_ERROR_INTERNAL;
1549         }
1550 #ifndef GATT_NO_RELAY
1551         else {
1552                 /* Unregister the client sender to bt-service */
1553                 __bluetooth_gatt_unwatch_characteristics();
1554         }
1555 #endif
1556         BT_DBG("-");
1557         return ret;
1558 }