Merge the code from private
[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_variant_unref(value);
514         g_object_unref(proxy);
515 }
516
517 BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(
518                         const char *service_handle)
519 {
520         GDBusProxy *properties_proxy = NULL;
521         GDBusConnection *g_conn;
522         GError *error = NULL;
523         char *handle;
524
525         BT_DBG("+");
526
527         BT_CHECK_PARAMETER(service_handle, return);
528         BT_CHECK_ENABLED(return);
529
530         g_conn = _bt_gdbus_get_system_gconn();
531         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
532
533         properties_proxy = g_dbus_proxy_new_sync(g_conn,
534                         G_DBUS_PROXY_FLAGS_NONE, NULL,
535                         BT_BLUEZ_NAME,
536                         service_handle,
537                         BT_PROPERTIES_INTERFACE,
538                         NULL, &error);
539
540         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
541
542         handle = g_strdup(service_handle);
543         g_dbus_proxy_call(properties_proxy,
544                         "Get",
545                         g_variant_new("(ss)",
546                                 GATT_SERV_INTERFACE, "Characteristics"),
547                         G_DBUS_CALL_FLAGS_NONE,
548                         -1,
549                         NULL,
550                         (GAsyncReadyCallback)__bluetooth_internal_get_char_cb,
551                         (gpointer)handle);
552
553         BT_DBG("-");
554         return BLUETOOTH_ERROR_NONE;
555 }
556
557
558 static int __get_permission_flag(char *permission)
559 {
560         int ret = 0;
561
562         retv_if(permission == NULL, ret);
563
564         BT_INFO("permission = %s", permission);
565
566         if (!g_strcmp0(permission, "broadcast")) {
567                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
568         } else if (!g_strcmp0(permission, "read")) {
569                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
570         } else if (!g_strcmp0(permission, "write-without-response")) {
571                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
572         } else if (!g_strcmp0(permission, "write")) {
573                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
574         } else if (!g_strcmp0(permission, "notify")) {
575                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
576         } else if (!g_strcmp0(permission, "indicate")) {
577                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
578         } else if (!g_strcmp0(permission, "authenticated-signed-writes")) {
579                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
580         } else if (!g_strcmp0(permission, "reliable-write")) {
581                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
582         } else if (!g_strcmp0(permission, "writable-auxiliaries")) {
583                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
584         } else if (!g_strcmp0(permission, "encrypt-read")) {
585                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
586         } else if (!g_strcmp0(permission, "encrypt-write")) {
587                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
588         } else if (!g_strcmp0(permission, "encrypt-authenticated-read")) {
589                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
590         } else if (!g_strcmp0(permission, "encrypt-authenticated-write")) {
591                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
592         }
593
594         return ret;
595 }
596
597 BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
598                 const char *char_handle, bt_gatt_char_property_t *characteristic)
599 {
600         GDBusProxy *properties_proxy = NULL;
601         GError *error = NULL;
602         GVariant *value = NULL;
603         GVariant *result = NULL;
604         GByteArray *gb_array = NULL;
605         GPtrArray *gp_array  = NULL ;
606         GDBusConnection *g_conn;
607         guint8 char_value;
608         const gchar *key;
609         gchar* permission;
610         char *char_desc_handle = NULL;
611         gsize len;
612         GVariantIter *property_iter;
613         GVariantIter *char_value_iter;
614         GVariantIter *char_perm_iter;
615         GVariantIter *char_desc_iter;
616
617         BT_DBG("+");
618         BT_CHECK_PARAMETER(char_handle, return);
619         BT_CHECK_PARAMETER(characteristic, return);
620
621         BT_CHECK_ENABLED(return);
622
623         g_conn = _bt_gdbus_get_system_gconn();
624         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
625
626         properties_proxy = g_dbus_proxy_new_sync(g_conn,
627                         G_DBUS_PROXY_FLAGS_NONE, NULL,
628                         BT_BLUEZ_NAME,
629                         char_handle,
630                         BT_PROPERTIES_INTERFACE,
631                         NULL, &error);
632
633         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
634
635         result = g_dbus_proxy_call_sync(properties_proxy,
636                                 "GetAll",
637                                         g_variant_new("(s)", GATT_CHAR_INTERFACE),
638                                 G_DBUS_CALL_FLAGS_NONE,
639                                 -1,
640                                 NULL,
641                                 &error);
642
643         if (!result) {
644                 if (error != NULL) {
645                         BT_ERR("Fail to get properties (Error: %s)", error->message);
646                         g_clear_error(&error);
647                 } else
648                         BT_ERR("Fail to get properties");
649                 g_object_unref(properties_proxy);
650                 return BLUETOOTH_ERROR_INTERNAL;
651         }
652
653         g_variant_get(result, "(a{sv})", &property_iter);
654
655         memset(characteristic, 0, sizeof(bt_gatt_char_property_t));
656         characteristic->handle = g_strdup(char_handle);
657
658         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
659                 if (!g_strcmp0(key, "UUID")) {
660                         char *name = NULL;
661                         characteristic->uuid = g_variant_dup_string(value, &len);
662                         _bt_get_uuid_specification_name(characteristic->uuid, &name);
663                         BT_INFO("Characteristic : %s [%s]", characteristic->uuid, name);
664                         g_free(name);
665                 } else if (!g_strcmp0(key, "Value")) {
666                         gb_array = g_byte_array_new();
667                         g_variant_get(value, "ay", &char_value_iter);
668                         while (g_variant_iter_loop(char_value_iter, "y",  &char_value)) {
669                         //      BT_DBG("value of char = %d",char_value);
670                                 g_byte_array_append(gb_array, &char_value, 1);
671                         }
672                         g_variant_iter_free(char_value_iter);
673
674                         if (gb_array->len != 0) {
675                                 characteristic->val = g_malloc0(gb_array->len *
676                                                                 sizeof(unsigned char));
677                                 memcpy(characteristic->val, gb_array->data, gb_array->len);
678                         }
679                         characteristic->val_len = gb_array->len;
680                         g_byte_array_free(gb_array, TRUE);
681                 } else if (!g_strcmp0(key, "Flags")) {
682                         g_variant_get(value, "as", &char_perm_iter);
683                         characteristic->permission = 0x00;
684                         while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
685                                 BT_DBG("permission = %s", permission);
686                                 characteristic->permission |= __get_permission_flag(permission);
687                                 BT_DBG("permission check = %d", characteristic->permission);
688                         }
689                         g_variant_iter_free(char_perm_iter);
690                 } else if (!g_strcmp0(key, "Descriptors")) {
691                         g_variant_get(value, "ao", &char_desc_iter);
692                         gp_array = g_ptr_array_new();
693                         while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
694                                 g_ptr_array_add(gp_array, (gpointer)char_desc_handle);
695                         }
696                         g_variant_iter_free(char_desc_iter);
697                         if (gp_array->len != 0) {
698                                 characteristic->char_desc_handle.count = gp_array->len;
699                                 characteristic->char_desc_handle.handle =
700                                                 __get_string_array_from_gptr_array(gp_array);
701                         }
702                         g_ptr_array_free(gp_array, TRUE);
703                 }
704         }
705
706         g_variant_iter_free(property_iter);
707         g_variant_unref(result);
708         g_object_unref(properties_proxy);
709
710         BT_DBG("-");
711         return BLUETOOTH_ERROR_NONE;
712 }
713
714 void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy,
715                         GAsyncResult *res, gpointer user_data)
716 {
717         GVariant *value;
718         GVariantIter *char_iter;
719         char *char_handle;
720         GError *error = NULL;
721         bt_user_info_t *user_info;
722         int ret = BLUETOOTH_ERROR_INTERNAL;
723         bt_gatt_char_property_t characteristic;
724
725         user_info = _bt_get_user_data(BT_COMMON);
726
727         value = g_dbus_proxy_call_finish(proxy, res, &error);
728
729         if (value == NULL) {
730                 if (error != NULL) {
731                         BT_ERR("Get service characteristics failed\n errCode[%x],"
732                                         "message[%s]\n", error->code, error->message);
733                         g_clear_error(&error);
734                 } else {
735                         BT_ERR("Get service characteristics failed\n");
736                 }
737                 if (user_info) {
738                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
739                                 BLUETOOTH_ERROR_INTERNAL, NULL,
740                                 user_info->cb, user_info->user_data);
741                 }
742                 g_object_unref(proxy);
743                 g_free(user_data);
744                 return;
745         }
746
747         g_variant_get(value, "(ao)", &char_iter);
748
749         while (g_variant_iter_loop(char_iter, "&o",  &char_handle)) {
750                 if (!char_handle)
751                         continue;
752                 ret = bluetooth_gatt_get_characteristics_property(char_handle,
753                                 &characteristic);
754
755                 if (ret != BLUETOOTH_ERROR_NONE) {
756                         BT_ERR("Get characteristic property failed(0x%08x)", ret);
757                 } else {
758                         if (g_strstr_len(characteristic.uuid, -1, user_data)) {
759                                 ret = BLUETOOTH_ERROR_NONE;
760                                 break;
761                         }
762                 }
763                 bluetooth_gatt_free_char_property(&characteristic);
764         }
765
766         if (user_info) {
767                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret,
768                                 &characteristic, user_info->cb, user_info->user_data);
769         }
770
771         bluetooth_gatt_free_char_property(&characteristic);
772         g_variant_iter_free(char_iter);
773         g_variant_unref(value);
774         g_free(user_data);
775 }
776
777 BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
778                                                 const char *char_uuid)
779 {
780         GDBusProxy *properties_proxy = NULL;
781         GDBusConnection *g_conn;
782         GError *error = NULL;
783         char *uuid;
784
785         BT_CHECK_PARAMETER(service_handle, return);
786         BT_CHECK_PARAMETER(char_uuid, return);
787         BT_CHECK_ENABLED(return);
788
789         g_conn = _bt_gdbus_get_system_gconn();
790         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
791
792         properties_proxy = g_dbus_proxy_new_sync(g_conn,
793                         G_DBUS_PROXY_FLAGS_NONE, NULL,
794                         BT_BLUEZ_NAME,
795                         service_handle,
796                         BT_PROPERTIES_INTERFACE,
797                         NULL, &error);
798
799         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
800
801         uuid = g_strdup(char_uuid);
802         g_dbus_proxy_call(properties_proxy,
803                         "Get",
804                         g_variant_new("(ss)",
805                                 GATT_SERV_INTERFACE, "Characteristics"),
806                         G_DBUS_CALL_FLAGS_NONE,
807                         -1,
808                         NULL,
809                         (GAsyncReadyCallback)bluetooth_gatt_get_char_from_uuid_cb,
810                         (gpointer)uuid);
811
812         return BLUETOOTH_ERROR_NONE;
813 }
814
815 BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
816                 const char *descriptor_handle, bt_gatt_char_descriptor_property_t *descriptor)
817 {
818         GDBusProxy *properties_proxy = NULL;
819         GError *error = NULL;
820         GDBusConnection *g_conn;
821         GVariant *result = NULL;
822         GVariantIter *property_iter;
823         const gchar *key;
824         guint8 char_value;
825         gsize len;
826         GVariant *value = NULL;
827         GByteArray *gb_array = NULL;
828         GVariantIter *desc_value_iter;
829
830         BT_DBG("+");
831         BT_CHECK_PARAMETER(descriptor_handle, return);
832         BT_CHECK_PARAMETER(descriptor, return);
833
834         BT_CHECK_ENABLED(return);
835
836         g_conn = _bt_gdbus_get_system_gconn();
837         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
838
839         properties_proxy = g_dbus_proxy_new_sync(g_conn,
840                         G_DBUS_PROXY_FLAGS_NONE, NULL,
841                         BT_BLUEZ_NAME,
842                         descriptor_handle,
843                         BT_PROPERTIES_INTERFACE,
844                         NULL, &error);
845
846         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
847
848         result = g_dbus_proxy_call_sync(properties_proxy,
849                                 "GetAll",
850                                         g_variant_new("(s)", GATT_DESC_INTERFACE),
851                                 G_DBUS_CALL_FLAGS_NONE,
852                                 -1,
853                                 NULL,
854                                 &error);
855
856         if (!result) {
857                 if (error != NULL) {
858                         BT_ERR("Fail to get properties (Error: %s)", error->message);
859                         g_clear_error(&error);
860                 } else
861                         BT_ERR("Fail to get properties");
862                 g_object_unref(properties_proxy);
863                 return BLUETOOTH_ERROR_INTERNAL;
864         }
865
866         g_variant_get(result, "(a{sv})", &property_iter);
867
868         memset(descriptor, 0, sizeof(bt_gatt_char_descriptor_property_t));
869         descriptor->handle = g_strdup(descriptor_handle);
870
871         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
872                 if (!g_strcmp0(key, "UUID")) {
873                         char *name = NULL;
874                         descriptor->uuid = g_variant_dup_string(value, &len);
875                         _bt_get_uuid_specification_name(descriptor->uuid, &name);
876                         BT_INFO("Descriptor : %s [%s]", descriptor->uuid, name);
877                         g_free(name);
878                 } else if (!g_strcmp0(key, "Value")) {
879                         gb_array = g_byte_array_new();
880                         g_variant_get(value, "ay", &desc_value_iter);
881                         while (g_variant_iter_loop(desc_value_iter, "y",  &char_value)) {
882                                 BT_DBG("value of descriptor = %d", char_value);
883                                 g_byte_array_append(gb_array, &char_value, 1);
884                         }
885                         g_variant_iter_free(desc_value_iter);
886
887                         if (gb_array->len != 0) {
888                                 descriptor->val = g_malloc0(gb_array->len *
889                                                                 sizeof(unsigned char));
890                                 memcpy(descriptor->val, gb_array->data, gb_array->len);
891                         }
892                         descriptor->val_len = gb_array->len;
893                         g_byte_array_free(gb_array, TRUE);
894                 }
895         }
896
897         g_variant_iter_free(property_iter);
898         g_variant_unref(result);
899         g_object_unref(properties_proxy);
900
901         BT_DBG("-");
902         return BLUETOOTH_ERROR_NONE;
903 }
904
905 static void __bluetooth_internal_read_cb(GObject *source_object,
906                         GAsyncResult *res,
907                         gpointer user_data)
908 {
909         GError *error = NULL;
910         bt_user_info_t *user_info;
911         bt_gatt_char_value_t char_value =  { 0, };
912         GDBusConnection *system_gconn = NULL;
913         GVariant *value;
914         GByteArray *gp_byte_array = NULL;
915         GVariantIter *iter;
916         guint8 g_byte;
917         int ret = BLUETOOTH_ERROR_NONE;
918
919         BT_DBG("+");
920         user_info = _bt_get_user_data(BT_COMMON);
921
922         system_gconn = _bt_gdbus_get_system_gconn();
923         value = g_dbus_connection_call_finish(system_gconn, res, &error);
924
925         if (error) {
926                 BT_ERR("Error : %s \n", error->message);
927                 if (g_strrstr(error->message, "Not paired"))
928                         ret = BLUETOOTH_ERROR_NOT_PAIRED;
929                 else
930                         ret = BLUETOOTH_ERROR_INTERNAL;
931
932                 g_clear_error(&error);
933                 if (user_info) {
934                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
935                                 ret, NULL,
936                                 user_info->cb, user_info->user_data);
937                 }
938                 g_free(user_data);
939                 return;
940         }
941
942         char_value.char_handle = user_data;
943         gp_byte_array = g_byte_array_new();
944         g_variant_get(value, "(ay)", &iter);
945
946         while (g_variant_iter_loop(iter, "y", &g_byte)) {
947                 g_byte_array_append(gp_byte_array, &g_byte, 1);
948         }
949
950         if (gp_byte_array->len != 0) {
951                 char_value.val_len = gp_byte_array->len;
952                 char_value.char_value = gp_byte_array->data;
953         }
954
955         if (user_info) {
956                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
957                                 BLUETOOTH_ERROR_NONE, &char_value,
958                                 user_info->cb, user_info->user_data);
959         }
960
961         g_free(char_value.char_handle);
962         g_byte_array_free(gp_byte_array, TRUE);
963         g_variant_unref(value);
964         g_variant_iter_free(iter);
965
966         BT_DBG("-");
967 }
968
969 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *characteristic)
970 {
971         GDBusConnection *conn;
972         char *handle;
973
974         BT_CHECK_PARAMETER(characteristic, return);
975         BT_CHECK_ENABLED(return);
976
977         conn = _bt_gdbus_get_system_gconn();
978         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
979
980         handle = g_strdup(characteristic);
981
982         g_dbus_connection_call(conn,
983                         BT_BLUEZ_NAME,
984                         characteristic,
985                         GATT_CHAR_INTERFACE,
986                         "ReadValue",
987                         NULL,
988                         G_VARIANT_TYPE("(ay)"),
989                         G_DBUS_CALL_FLAGS_NONE,
990                         -1,
991                         NULL,
992                         (GAsyncReadyCallback)__bluetooth_internal_read_cb,
993                         (gpointer)handle);
994
995         return BLUETOOTH_ERROR_NONE;
996 }
997
998 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
999                 const char *char_handle, const guint8 *value, int length)
1000 {
1001         GVariant *val;
1002         GVariantBuilder *builder;
1003         GError *error = NULL;
1004         GDBusConnection *conn;
1005         int i = 0;
1006
1007         BT_DBG("+");
1008         BT_CHECK_PARAMETER(char_handle, return);
1009         BT_CHECK_PARAMETER(value, return);
1010         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1011         BT_CHECK_ENABLED(return);
1012
1013         conn = _bt_gdbus_get_system_gconn();
1014         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1015
1016         builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1017
1018         for (i = 0; i < length; i++) {
1019                 g_variant_builder_add(builder, "y", value[i]);
1020         }
1021
1022         val = g_variant_new("(ay)", builder);
1023
1024         g_dbus_connection_call_sync(conn,
1025                         BT_BLUEZ_NAME,
1026                         char_handle,
1027                         GATT_CHAR_INTERFACE,
1028                         "WriteValue",
1029                         val,
1030                         NULL,
1031                         G_DBUS_CALL_FLAGS_NONE,
1032                         -1, NULL, &error);
1033
1034         if (error) {
1035                 BT_ERR("Set value Failed: %s", error->message);
1036                 g_clear_error(&error);
1037                 g_variant_builder_unref(builder);
1038                 return BLUETOOTH_ERROR_INTERNAL;
1039         }
1040
1041         g_variant_builder_unref(builder);
1042
1043         BT_DBG("-");
1044         return BLUETOOTH_ERROR_NONE;
1045 }
1046
1047 static void __bluetooth_internal_write_cb(GObject *source_object,
1048                         GAsyncResult *res,
1049                         gpointer user_data)
1050 {
1051         BT_DBG("+");
1052         GError *error = NULL;
1053         bt_user_info_t *user_info;
1054         GDBusConnection *system_gconn = NULL;
1055         GVariant *value;
1056         int result = BLUETOOTH_ERROR_NONE;
1057         guint8 att_ecode = 0;
1058
1059         user_info = _bt_get_user_data(BT_COMMON);
1060
1061         system_gconn = _bt_gdbus_get_system_gconn();
1062         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1063
1064         if (error) {
1065                 BT_ERR("Error : %s \n", error->message);
1066                 g_clear_error(&error);
1067                 result = BLUETOOTH_ERROR_INTERNAL;
1068         } else {
1069                 g_variant_get(value, "(y)", &att_ecode);
1070                 if (att_ecode) {
1071                         result =  att_ecode;
1072                         BT_ERR("ATT Error code: %d \n", att_ecode);
1073                 }
1074         }
1075
1076         if (user_info) {
1077                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
1078                                 result, NULL,
1079                                 user_info->cb, user_info->user_data);
1080         } else {
1081                 BT_ERR("user info is null");
1082         }
1083
1084         if (value)
1085                 g_variant_unref(value);
1086         BT_DBG("-");
1087         return;
1088 }
1089
1090 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
1091                 const char *char_handle, const guint8 *value, int length, guint8 write_type)
1092 {
1093         GVariant *val;
1094         GVariantBuilder *builder;
1095         GDBusConnection *conn;
1096         int i = 0;
1097         int ret = BLUETOOTH_ERROR_NONE;
1098
1099         BT_CHECK_PARAMETER(char_handle, return);
1100         BT_CHECK_PARAMETER(value, return);
1101         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1102         BT_CHECK_ENABLED_INTERNAL(return);
1103
1104         conn = _bt_gdbus_get_system_gconn();
1105         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1106
1107         builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1108
1109         for (i = 0; i < length; i++) {
1110                 g_variant_builder_add(builder, "y", value[i]);
1111         }
1112
1113         val = g_variant_new("ay", builder);
1114         g_dbus_connection_call(conn,
1115                         BT_BLUEZ_NAME,
1116                         char_handle,
1117                         GATT_CHAR_INTERFACE,
1118                         "WriteValuebyType",
1119                         g_variant_new("(y@ay)", write_type, val),
1120                         G_VARIANT_TYPE("(y)"),
1121                         G_DBUS_CALL_FLAGS_NONE,
1122                         -1, NULL,
1123                         (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1124                         NULL);
1125
1126         g_variant_builder_unref(builder);
1127         return ret;
1128 }
1129
1130 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
1131                         const char *char_handle, const guint8 *value, int length)
1132 {
1133         GVariant *val;
1134         GDBusConnection *conn;
1135         GVariantBuilder *builder;
1136         int i;
1137
1138         BT_DBG("+");
1139         BT_CHECK_PARAMETER(char_handle, return);
1140         BT_CHECK_PARAMETER(value, return);
1141         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1142         BT_CHECK_ENABLED(return);
1143
1144         conn = _bt_gdbus_get_system_gconn();
1145         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1146
1147         builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1148
1149         for (i = 0; i < length; i++) {
1150                 g_variant_builder_add(builder, "y", value[i]);
1151                 BT_DBG("value [] = %d", value[i]);
1152         }
1153
1154         val = g_variant_new("(ay)", builder);
1155
1156         g_dbus_connection_call(conn,
1157                                 BT_BLUEZ_NAME,
1158                                 char_handle,
1159                                 GATT_CHAR_INTERFACE,
1160                                 "WriteValue",
1161                                 val,
1162                                 NULL,
1163                                 G_DBUS_CALL_FLAGS_NONE,
1164                                 -1, NULL,
1165                                 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1166                                 NULL);
1167
1168         g_variant_builder_unref(builder);
1169
1170         BT_DBG("-");
1171         return BLUETOOTH_ERROR_NONE;
1172 }
1173
1174 static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
1175                         bt_gatt_char_property_t *characteristic)
1176 {
1177         BT_DBG("+");
1178         GDBusProxy *properties_proxy = NULL;
1179         GError *error = NULL;
1180         GVariant *value = NULL;
1181         GVariant *result = NULL;
1182         GDBusConnection *g_conn;
1183         int i, ret = BLUETOOTH_ERROR_NONE;
1184         const char *uuid = NULL;
1185         gsize len = 0;
1186         GVariantIter *desc_value_iter, *property_iter;
1187         const gchar *key;
1188         char_descriptor_type_t desc_type = TYPE_NONE;
1189
1190         g_conn = _bt_gdbus_get_system_gconn();
1191         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1192
1193         properties_proxy = g_dbus_proxy_new_sync(g_conn,
1194                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1195                         BT_BLUEZ_NAME,
1196                         char_handle,
1197                         BT_PROPERTIES_INTERFACE,
1198                         NULL, &error);
1199
1200         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1201
1202         result = g_dbus_proxy_call_sync(properties_proxy,
1203                                 "GetAll",
1204                                 g_variant_new("(s)", GATT_DESC_INTERFACE),
1205                                 G_DBUS_CALL_FLAGS_NONE,
1206                                 -1,
1207                                 NULL,
1208                                 &error);
1209
1210         if (!result) {
1211                 if (error != NULL) {
1212                         BT_ERR("Fail to get properties (Error: %s)", error->message);
1213                         g_clear_error(&error);
1214                 } else
1215                         BT_ERR("Fail to get properties");
1216                 g_object_unref(properties_proxy);
1217                 return BLUETOOTH_ERROR_INTERNAL;
1218         }
1219         g_variant_get(result, "(a{sv})", &property_iter);
1220         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1221                 if (!g_strcmp0(key, "UUID")) {
1222                         uuid = g_variant_get_string(value, &len);
1223                         if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
1224                                 BT_DBG("GATT_USER_DESC_UUID");
1225                                 desc_type = USER_DESC;
1226                         } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) {
1227                                 BT_DBG("GATT_CHAR_FORMAT");
1228                                 desc_type = CHAR_FORMAT;
1229                         } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) {
1230                                 BT_DBG("GATT_CHAR_CLIENT_CONF");
1231                                 desc_type = CLIENT_CONF;
1232                         } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) {
1233                                 BT_DBG("GATT_CHAR_SERVER_CONF");
1234                                 desc_type = SERVER_CONF;
1235                         } else {
1236                                 BT_DBG("descriptor uuid = %s", uuid);
1237                         }
1238                 } else if (!g_strcmp0(key, "Value")) {
1239                         switch (desc_type) {
1240                         case CHAR_FORMAT:
1241                                 BT_DBG("Format descriptor");
1242                                 g_variant_get(value, "(yyqyq)",
1243                                                 &(characteristic->format.format),
1244                                                 &(characteristic->format.exponent),
1245                                                 &(characteristic->format.unit),
1246                                                 &(characteristic->format.name_space),
1247                                                 &(characteristic->format.description));
1248                                 break;
1249                         case USER_DESC:
1250                                 BT_DBG("User descriptor");
1251                                 g_variant_get(value, "ay", &desc_value_iter);
1252                                 len = g_variant_get_size((GVariant *)desc_value_iter);
1253
1254                                 if (len > 0) {
1255                                         characteristic->description = (char *)g_malloc0(len + 1);
1256                                         if (!characteristic->description) {
1257                                                 ret = BLUETOOTH_ERROR_OUT_OF_MEMORY;
1258                                                 goto done;
1259                                         }
1260                                 }
1261                                 for (i = 0; i < len; i++) {
1262                                         g_variant_iter_loop(desc_value_iter, "y",
1263                                                 &characteristic->description[i]);
1264                                         BT_DBG("description = %s", characteristic->description);
1265                                 }
1266                                 g_variant_iter_free(desc_value_iter);
1267                                 break;
1268                         case CLIENT_CONF:
1269                                 BT_DBG(" CLIENT_CONF");
1270                                 break;
1271                         case SERVER_CONF:
1272                                 BT_DBG(" SERVER_CONF");
1273                                 break;
1274                         default:
1275                                 break;
1276                         }
1277                 }
1278         }
1279
1280 done:
1281         g_variant_iter_free(property_iter);
1282         g_variant_unref(result);
1283         g_object_unref(properties_proxy);
1284
1285         BT_DBG("-");
1286         return ret;
1287 }
1288
1289
1290 static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
1291                         GAsyncResult *res, gpointer user_data)
1292 {
1293         BT_DBG("+");
1294         GVariant *value;
1295         GVariant        *char_value;
1296         GVariantIter *char_iter;
1297         char *char_handle;
1298         GError *error = NULL;
1299         bt_user_info_t *user_info;
1300         bt_gatt_char_property_t characteristic = {0, };
1301         int ret = BLUETOOTH_ERROR_INTERNAL;
1302
1303         user_info = _bt_get_user_data(BT_COMMON);
1304
1305         value = g_dbus_proxy_call_finish(proxy, res, &error);
1306
1307         if (value == NULL) {
1308                 if (error != NULL) {
1309                         BT_ERR("Get characteristic descriptor failed\n errCode[%x],"
1310                                         "message[%s]\n", error->code, error->message);
1311                         g_clear_error(&error);
1312                 } else {
1313                         BT_ERR("Get characteristic descriptor failed\n");
1314                 }
1315                 if (user_info) {
1316                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1317                                 BLUETOOTH_ERROR_INTERNAL, NULL,
1318                                 user_info->cb, user_info->user_data);
1319                 }
1320                 g_free(user_data);
1321                 g_object_unref(proxy);
1322                 return;
1323         }
1324
1325         g_variant_get(value, "(v)", &char_value);
1326         g_variant_get(char_value, "ao", &char_iter);
1327
1328         while (g_variant_iter_loop(char_iter, "&o",  &char_handle)) {
1329                 BT_DBG("object path of descriptor = %s", char_handle);
1330                 if (char_handle) {
1331                         ret = __bluetooth_gatt_descriptor_iter(char_handle,
1332                                                 &characteristic);
1333                         BT_DBG("Descriptor read status [%d]", ret);
1334                 }
1335         }
1336
1337         characteristic.handle = user_data;
1338         if (user_info) {
1339                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1340                                 ret, &characteristic, user_info->cb, user_info->user_data);
1341         }
1342         bluetooth_gatt_free_char_property(&characteristic);
1343
1344         g_variant_iter_free(char_iter);
1345         g_variant_unref(value);
1346         BT_DBG("-");
1347 }
1348
1349 BT_EXPORT_API int bluetooth_gatt_discover_characteristic_descriptor(
1350                         const char *characteristic_handle)
1351 {
1352         GDBusProxy *properties_proxy = NULL;
1353         GDBusConnection *g_conn;
1354         char *handle;
1355         GError *error = NULL;
1356
1357         BT_CHECK_PARAMETER(characteristic_handle, return);
1358         BT_CHECK_ENABLED(return);
1359
1360         g_conn = _bt_gdbus_get_system_gconn();
1361         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1362
1363         properties_proxy = g_dbus_proxy_new_sync(g_conn,
1364                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1365                         BT_BLUEZ_NAME,
1366                         characteristic_handle,
1367                         BT_PROPERTIES_INTERFACE,
1368                         NULL, &error);
1369
1370         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1371
1372         handle = g_strdup(characteristic_handle);
1373         g_dbus_proxy_call(properties_proxy,
1374                         "Get",
1375                         g_variant_new("(ss)",
1376                                 GATT_CHAR_INTERFACE, "Descriptors"),
1377                         G_DBUS_CALL_FLAGS_NONE,
1378                         -1, NULL,
1379                         (GAsyncReadyCallback)bluetooth_gatt_get_char_desc_cb,
1380                         (gpointer)handle);
1381
1382         return BLUETOOTH_ERROR_NONE;
1383 }
1384
1385 static void __bluetooth_internal_read_desc_cb(GObject *source_object,
1386                         GAsyncResult *res,
1387                         gpointer user_data)
1388 {
1389         GError *error = NULL;
1390         bt_user_info_t *user_info;
1391         bt_gatt_char_property_t char_value =  { 0, };
1392         GDBusConnection *system_gconn = NULL;
1393         GVariant *value;
1394         GByteArray *gp_byte_array = NULL;
1395         GVariantIter *iter;
1396         guint8 g_byte;
1397
1398         BT_DBG("+");
1399         user_info = _bt_get_user_data(BT_COMMON);
1400         system_gconn = _bt_gdbus_get_system_gconn();
1401
1402         char_value.handle = user_data;
1403         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1404
1405         if (error) {
1406                 BT_ERR("Error : %s \n", error->message);
1407                 g_clear_error(&error);
1408                 if (user_info) {
1409                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1410                                         BLUETOOTH_ERROR_INTERNAL, NULL,
1411                                         user_info->cb, user_info->user_data);
1412                 }
1413                 g_free(char_value.handle);
1414                 return;
1415         }
1416
1417         gp_byte_array = g_byte_array_new();
1418         g_variant_get(value, "(ay)", &iter);
1419
1420         while (g_variant_iter_loop(iter, "y",  &g_byte))
1421                 g_byte_array_append(gp_byte_array, &g_byte, 1);
1422
1423         if (gp_byte_array->len != 0) {
1424                 char_value.val_len = (unsigned int)gp_byte_array->len;
1425                 char_value.description = (char *)gp_byte_array->data;
1426         }
1427
1428         if (user_info) {
1429                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1430                                 BLUETOOTH_ERROR_NONE, &char_value,
1431                                 user_info->cb, user_info->user_data);
1432         }
1433
1434         g_byte_array_free(gp_byte_array, TRUE);
1435         g_free(char_value.handle);
1436         g_variant_unref(value);
1437         g_variant_iter_free(iter);
1438
1439         BT_DBG("-");
1440 }
1441
1442 BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *char_descriptor)
1443 {
1444         GDBusConnection *conn;
1445         char *handle;
1446
1447         BT_DBG("+");
1448         BT_CHECK_PARAMETER(char_descriptor, return);
1449         BT_CHECK_ENABLED(return);
1450
1451         conn = _bt_gdbus_get_system_gconn();
1452         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1453
1454         handle = g_strdup(char_descriptor);
1455
1456         g_dbus_connection_call(conn,
1457                         BT_BLUEZ_NAME,
1458                         char_descriptor,
1459                         GATT_DESC_INTERFACE,
1460                         "ReadValue",
1461                         NULL,
1462                         G_VARIANT_TYPE("(ay)"),
1463                         G_DBUS_CALL_FLAGS_NONE,
1464                         -1,
1465                         NULL,
1466                         (GAsyncReadyCallback)__bluetooth_internal_read_desc_cb,
1467                         (gpointer)handle);
1468
1469         BT_DBG("-");
1470         return BLUETOOTH_ERROR_NONE;
1471 }
1472
1473 static void __bluetooth_internal_write_desc_cb(GObject *source_object,
1474                         GAsyncResult *res,
1475                         gpointer user_data)
1476 {
1477         GError *error = NULL;
1478         bt_user_info_t *user_info;
1479         GDBusConnection *system_gconn = NULL;
1480         GVariant *value;
1481         int result = BLUETOOTH_ERROR_NONE;
1482         guint8 att_ecode = 0;
1483
1484         BT_DBG("+");
1485         user_info = _bt_get_user_data(BT_COMMON);
1486
1487         system_gconn = _bt_gdbus_get_system_gconn();
1488         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1489
1490         if (error) {
1491                 BT_ERR("Error : %s \n", error->message);
1492                 g_clear_error(&error);
1493                 result = BLUETOOTH_ERROR_INTERNAL;
1494         } else {
1495                 g_variant_get(value, "(y)", &att_ecode);
1496                 if (att_ecode) {
1497                         result =  att_ecode;
1498                         BT_ERR("ATT Error code: %d \n", att_ecode);
1499                 }
1500         }
1501
1502         if (user_info) {
1503                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1504                                 result, NULL,
1505                                 user_info->cb, user_info->user_data);
1506         }
1507
1508         if (value)
1509                 g_variant_unref(value);
1510
1511         BT_DBG("-");
1512 }
1513
1514 BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(
1515                         const char *desc_handle, const guint8 *value, int length)
1516 {
1517         GVariant *val;
1518         GDBusConnection *conn;
1519         GVariantBuilder *builder;
1520         int i;
1521
1522         BT_DBG("+");
1523         BT_CHECK_PARAMETER(desc_handle, return);
1524         BT_CHECK_PARAMETER(value, return);
1525         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1526         BT_CHECK_ENABLED(return);
1527
1528         conn = _bt_gdbus_get_system_gconn();
1529         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1530
1531         builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1532
1533         for (i = 0; i < length; i++) {
1534                 g_variant_builder_add(builder, "y", value[i]);
1535         }
1536
1537         val = g_variant_new("(ay)", builder);
1538
1539         g_dbus_connection_call(conn,
1540                                 BT_BLUEZ_NAME,
1541                                 desc_handle,
1542                                 GATT_DESC_INTERFACE,
1543                                 "WriteValue",
1544                                 val,
1545                                 G_VARIANT_TYPE("(y)"),
1546                                 G_DBUS_CALL_FLAGS_NONE,
1547                                 -1, NULL,
1548                                 (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
1549                                 NULL);
1550
1551         g_variant_builder_unref(builder);
1552
1553         BT_DBG("-");
1554         return BLUETOOTH_ERROR_NONE;
1555 }
1556
1557 #ifndef GATT_NO_RELAY
1558 static int __bluetooth_gatt_watch_characteristics(void)
1559 {
1560         int result = BLUETOOTH_ERROR_NONE;
1561
1562         BT_INIT_PARAMS();
1563         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1564
1565         result = _bt_send_request(BT_BLUEZ_SERVICE,
1566                         BT_GATT_WATCH_CHARACTERISTIC,
1567                         in_param1, in_param2, in_param3, in_param4, &out_param);
1568
1569         if (result != BLUETOOTH_ERROR_NONE)
1570                         BT_ERR("Watch Characteristic request failed !");
1571
1572         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1573
1574         return result;
1575 }
1576 #endif
1577
1578 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle)
1579 {
1580         GDBusConnection *conn;
1581         GError *error = NULL;
1582         int ret = BLUETOOTH_ERROR_NONE;
1583
1584         BT_CHECK_PARAMETER(char_handle, return);
1585         BT_CHECK_ENABLED(return);
1586
1587         BT_INFO_C("### Enable CCCD : %s", char_handle);
1588
1589         conn = _bt_gdbus_get_system_gconn();
1590         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1591
1592         g_dbus_connection_call_sync(conn,
1593                         BT_BLUEZ_NAME,
1594                         char_handle,
1595                         GATT_CHAR_INTERFACE,
1596                         "StartNotify",
1597                         NULL,
1598                         NULL,
1599                         G_DBUS_CALL_FLAGS_NONE,
1600                         GATT_DEFAULT_TIMEOUT, NULL, &error);
1601
1602         if (error) {
1603                 g_dbus_error_strip_remote_error(error);
1604                 BT_ERR_C("### Watch Failed: %s", error->message);
1605                 if (g_strrstr(error->message, "Already notifying"))
1606                         ret = BLUETOOTH_ERROR_NONE;
1607                 else if (g_strrstr(error->message, "In Progress"))
1608                         ret = BLUETOOTH_ERROR_IN_PROGRESS;
1609                 else if (g_strrstr(error->message, "Operation is not supported"))
1610                         ret = BLUETOOTH_ERROR_NOT_SUPPORT;
1611 /*failed because of either Insufficient Authorization or Write Not Permitted */
1612                 else if (g_strrstr(error->message, "Write not permitted") ||
1613                                 g_strrstr(error->message, "Operation Not Authorized"))
1614                         ret = BLUETOOTH_ERROR_PERMISSION_DEINED;
1615 /* failed because of either Insufficient Authentication,
1616         Insufficient Encryption Key Size, or Insufficient Encryption. */
1617                 else if (g_strrstr(error->message, "Not paired"))
1618                         ret = BLUETOOTH_ERROR_NOT_PAIRED;
1619                 else
1620                         ret = BLUETOOTH_ERROR_INTERNAL;
1621
1622                 g_clear_error(&error);
1623         }
1624 #ifndef GATT_NO_RELAY
1625         else {
1626                 /* Register the client sender to bt-service */
1627                 ret = __bluetooth_gatt_watch_characteristics();
1628         }
1629 #endif
1630
1631         return ret;
1632 }
1633
1634 #ifndef GATT_NO_RELAY
1635 static int __bluetooth_gatt_unwatch_characteristics(void)
1636 {
1637         int result = BLUETOOTH_ERROR_NONE;
1638
1639         BT_INIT_PARAMS();
1640         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1641
1642         result = _bt_send_request(BT_BLUEZ_SERVICE,
1643                         BT_GATT_UNWATCH_CHARACTERISTIC,
1644                         in_param1, in_param2, in_param3, in_param4, &out_param);
1645
1646         if (result != BLUETOOTH_ERROR_NONE)
1647                         BT_ERR("Unwatch Characteristic request failed !");
1648
1649         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1650
1651         return result;
1652 }
1653 #endif
1654
1655 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle)
1656 {
1657
1658         GDBusConnection *conn;
1659         GError *error = NULL;
1660         int ret = BLUETOOTH_ERROR_NONE;
1661         BT_DBG("+");
1662         BT_CHECK_PARAMETER(char_handle, return);
1663
1664         BT_CHECK_ENABLED(return);
1665
1666         BT_INFO("Disable CCCD : %s", char_handle);
1667
1668         conn = _bt_gdbus_get_system_gconn();
1669         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1670
1671         g_dbus_connection_call_sync(conn,
1672                         BT_BLUEZ_NAME,
1673                         char_handle,
1674                         GATT_CHAR_INTERFACE,
1675                         "StopNotify",
1676                         NULL,
1677                         NULL,
1678                         G_DBUS_CALL_FLAGS_NONE,
1679                         GATT_DEFAULT_TIMEOUT, NULL, &error);
1680
1681         if (error) {
1682                 BT_ERR("Watch Failed: %s", error->message);
1683                 g_clear_error(&error);
1684                 ret =  BLUETOOTH_ERROR_INTERNAL;
1685         }
1686 #ifndef GATT_NO_RELAY
1687         else {
1688                 /* Unregister the client sender to bt-service */
1689                 ret = __bluetooth_gatt_unwatch_characteristics();
1690         }
1691 #endif
1692         BT_DBG("-");
1693         return ret;
1694 }