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