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