GATT-Clinet: Fix the Write and read dbus reply parameter mismatch.
[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         gint att_error_code;
888         int ret = BLUETOOTH_ERROR_NONE;
889
890         BT_DBG("+");
891         user_info = _bt_get_user_data(BT_COMMON);
892
893         system_gconn = _bt_gdbus_get_system_gconn();
894         value = g_dbus_connection_call_finish(system_gconn, res, &error);
895
896         if (error) {
897                 BT_ERR("Error : %s \n", error->message);
898                 if (g_strrstr(error->message, "Not paired"))
899                         ret = BLUETOOTH_ERROR_NOT_PAIRED;
900                 else
901                         ret = BLUETOOTH_ERROR_INTERNAL;
902
903                 g_clear_error(&error);
904                 if (user_info) {
905                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
906                                 ret, NULL,
907                                 user_info->cb, user_info->user_data);
908                 }
909                 g_free(user_data);
910                 return;
911         }
912
913         char_value.char_handle = user_data;
914
915         g_variant_get(value, "(yay)", &att_error_code, &iter);
916
917         if (att_error_code != 0) {
918                 if (user_info) {
919                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
920                                 att_error_code, NULL,
921                                 user_info->cb, user_info->user_data);
922                 }
923                 g_free(char_value.char_handle);
924                 g_variant_unref(value);
925                 g_variant_iter_free(iter);
926                 return;
927         }
928
929         gp_byte_array = g_byte_array_new();
930         while (g_variant_iter_loop(iter, "y", &g_byte))
931                 g_byte_array_append(gp_byte_array, &g_byte, 1);
932
933         if (gp_byte_array->len != 0) {
934                 char_value.val_len = gp_byte_array->len;
935                 char_value.char_value = gp_byte_array->data;
936         }
937
938         if (user_info) {
939                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
940                                 BLUETOOTH_ERROR_NONE, &char_value,
941                                 user_info->cb, user_info->user_data);
942         }
943
944         g_free(char_value.char_handle);
945         g_byte_array_free(gp_byte_array, TRUE);
946         g_variant_unref(value);
947         g_variant_iter_free(iter);
948
949         BT_DBG("-");
950 }
951
952 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *characteristic)
953 {
954         GDBusConnection *conn;
955         char *handle;
956         GVariantBuilder *builder = NULL;
957         guint16 offset = 0;
958
959         BT_CHECK_PARAMETER(characteristic, return);
960         BT_CHECK_ENABLED(return);
961
962         conn = _bt_gdbus_get_system_gconn();
963         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
964
965         handle = g_strdup(characteristic);
966
967         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
968
969         /*offset*/
970         g_variant_builder_add(builder, "{sv}", "offset",
971                 g_variant_new("q", offset));
972
973         /* Device Object path*/
974 //      g_variant_builder_add(builder, "{sv}", "device",
975 //      g_variant_new_object("o", NULL));
976
977         g_dbus_connection_call(conn,
978                         BT_BLUEZ_NAME,
979                         characteristic,
980                         GATT_CHAR_INTERFACE,
981                         "ReadValue",
982                         g_variant_new("(a{sv})", builder),
983                         G_VARIANT_TYPE("(yay)"),
984                         G_DBUS_CALL_FLAGS_NONE,
985                         -1,
986                         NULL,
987                         (GAsyncReadyCallback)__bluetooth_internal_read_cb,
988                         (gpointer)handle);
989         g_variant_builder_unref(builder);
990
991         return BLUETOOTH_ERROR_NONE;
992 }
993
994 static void __bluetooth_internal_write_cb(GObject *source_object,
995                         GAsyncResult *res,
996                         gpointer user_data)
997 {
998         GError *error = NULL;
999         bt_user_info_t *user_info;
1000         GDBusConnection *system_gconn = NULL;
1001         GVariant *value;
1002         int result = BLUETOOTH_ERROR_NONE;
1003         guint8 att_ecode = 0;
1004
1005         user_info = _bt_get_user_data(BT_COMMON);
1006
1007         system_gconn = _bt_gdbus_get_system_gconn();
1008         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1009
1010         if (error) {
1011                 BT_ERR("Error : %s \n", error->message);
1012                 g_clear_error(&error);
1013                 result = BLUETOOTH_ERROR_INTERNAL;
1014         } else {
1015                 g_variant_get(value, "(y)", &att_ecode);
1016                 if (att_ecode) {
1017                         result =  att_ecode;
1018                         BT_ERR("ATT Error code: %d \n", att_ecode);
1019                 }
1020         }
1021
1022         if (user_info) {
1023                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
1024                                 result, NULL,
1025                                 user_info->cb, user_info->user_data);
1026         } else {
1027                 BT_ERR("user info is null");
1028         }
1029
1030         if (value)
1031                 g_variant_unref(value);
1032
1033         return;
1034 }
1035
1036 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
1037                 const char *char_handle, const guint8 *value, int length)
1038 {
1039         GVariant *val, *options;
1040         GVariantBuilder *builder1;
1041         GVariantBuilder *builder2;
1042         GError *error = NULL;
1043         GDBusConnection *conn;
1044         int i = 0;
1045         guint16 offset = 0;
1046
1047         BT_DBG("+");
1048         BT_CHECK_PARAMETER(char_handle, return);
1049         BT_CHECK_PARAMETER(value, return);
1050         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1051         BT_CHECK_ENABLED(return);
1052
1053         conn = _bt_gdbus_get_system_gconn();
1054         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1055
1056         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1057         for (i = 0; i < length; i++)
1058                 g_variant_builder_add(builder1, "y", value[i]);
1059
1060         val = g_variant_new("ay", builder1);
1061
1062         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1063         /*offset*/
1064         g_variant_builder_add(builder2, "{sv}", "offset",
1065                                 g_variant_new_uint16(offset));
1066
1067         /* Device Object path*/
1068 //      g_variant_builder_add(builder2, "{sv}", "device",
1069 //      g_variant_new_object("o", NULL));
1070
1071         options = g_variant_new("a{sv}", builder2);
1072
1073         g_dbus_connection_call(conn,
1074                                 BT_BLUEZ_NAME,
1075                                 char_handle,
1076                                 GATT_CHAR_INTERFACE,
1077                                 "WriteValue",
1078                                 g_variant_new("(@ay@a{sv})",
1079                                 val, options),
1080                                 G_VARIANT_TYPE("(y)"),
1081                                 G_DBUS_CALL_FLAGS_NONE,
1082                                 -1, NULL,
1083                                 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1084                                 NULL);
1085
1086
1087         if (error) {
1088                 BT_ERR("Set value Failed: %s", error->message);
1089                 g_clear_error(&error);
1090                 g_variant_builder_unref(builder1);
1091                 return BLUETOOTH_ERROR_INTERNAL;
1092         }
1093         g_variant_builder_unref(builder1);
1094         g_variant_builder_unref(builder2);
1095
1096         BT_DBG("-");
1097         return BLUETOOTH_ERROR_NONE;
1098 }
1099
1100 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
1101                 const char *char_handle, const guint8 *value, int length, guint8 write_type)
1102 {
1103         GVariant *val, *options;
1104         GVariantBuilder *builder1;
1105         GVariantBuilder *builder2;
1106         GDBusConnection *conn;
1107         guint16 offset = 0;
1108         int i = 0;
1109         int ret = BLUETOOTH_ERROR_NONE;
1110
1111         BT_CHECK_PARAMETER(char_handle, return);
1112         BT_CHECK_PARAMETER(value, return);
1113         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1114         BT_CHECK_ENABLED_INTERNAL(return);
1115
1116         conn = _bt_gdbus_get_system_gconn();
1117         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1118
1119         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1120
1121         for (i = 0; i < length; i++)
1122                 g_variant_builder_add(builder1, "y", value[i]);
1123
1124         val = g_variant_new("ay", builder1);
1125
1126         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1127         /*offset*/
1128         g_variant_builder_add(builder2, "{sv}", "offset",
1129                         g_variant_new_uint16(offset));
1130
1131         /* Device Object path*/
1132 //      g_variant_builder_add(builder2, "{sv}", "device",
1133 //      g_variant_new_object("o", NULL));
1134
1135         options = g_variant_new("a{sv}", builder2);
1136
1137         g_dbus_connection_call(conn,
1138                         BT_BLUEZ_NAME,
1139                         char_handle,
1140                         GATT_CHAR_INTERFACE,
1141                         "WriteValuebyType",
1142                         g_variant_new("(y@ay@a{sv})",
1143                         write_type, val, options),
1144                         G_VARIANT_TYPE("(y)"),
1145                         G_DBUS_CALL_FLAGS_NONE,
1146                         -1, NULL,
1147                         (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1148                         NULL);
1149
1150         g_variant_builder_unref(builder1);
1151         g_variant_builder_unref(builder2);
1152         return ret;
1153 }
1154
1155 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
1156                         const char *char_handle, const guint8 *value, int length)
1157 {
1158         GVariant *val, *options;
1159         GDBusConnection *conn;
1160         GVariantBuilder *builder1;
1161         GVariantBuilder *builder2;
1162         guint offset = 0;
1163         int i;
1164
1165         BT_DBG("+");
1166         BT_CHECK_PARAMETER(char_handle, return);
1167         BT_CHECK_PARAMETER(value, return);
1168         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1169         BT_CHECK_ENABLED(return);
1170
1171         conn = _bt_gdbus_get_system_gconn();
1172         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1173
1174         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1175
1176         for (i = 0; i < length; i++) {
1177                 g_variant_builder_add(builder1, "y", value[i]);
1178                 BT_DBG("value [] = %d", value[i]);
1179         }
1180
1181         val = g_variant_new("ay", builder1);
1182
1183         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1184         /*offset*/
1185         g_variant_builder_add(builder2, "{sv}", "offset",
1186                                 g_variant_new_uint16(offset));
1187
1188         /* Device Object path*/
1189 //      g_variant_builder_add(builder2, "{sv}", "device",
1190 //      g_variant_new_object("o", NULL));
1191
1192         options = g_variant_new("a{sv}", builder2);
1193
1194         g_dbus_connection_call(conn,
1195                                 BT_BLUEZ_NAME,
1196                                 char_handle,
1197                                 GATT_CHAR_INTERFACE,
1198                                 "WriteValue",
1199                                 g_variant_new("(@ay@a{sv})",
1200                                 val, options),
1201                                 G_VARIANT_TYPE("(y)"),
1202                                 G_DBUS_CALL_FLAGS_NONE,
1203                                 -1, NULL,
1204                                 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1205                                 NULL);
1206
1207         g_variant_builder_unref(builder1);
1208         g_variant_builder_unref(builder2);
1209
1210         BT_DBG("-");
1211         return BLUETOOTH_ERROR_NONE;
1212 }
1213
1214 static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
1215                         bt_gatt_char_property_t *characteristic)
1216 {
1217         BT_DBG("+");
1218         GDBusProxy *properties_proxy = NULL;
1219         GError *error = NULL;
1220         GVariant *value = NULL;
1221         GVariant *result = NULL;
1222         GDBusConnection *g_conn;
1223         int i, ret = BLUETOOTH_ERROR_NONE;
1224         const char *uuid = NULL;
1225         gsize len = 0;
1226         GVariantIter *desc_value_iter, *property_iter;
1227         const gchar *key;
1228         char_descriptor_type_t desc_type = TYPE_NONE;
1229
1230         g_conn = _bt_gdbus_get_system_gconn();
1231         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1232
1233         properties_proxy = g_dbus_proxy_new_sync(g_conn,
1234                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1235                         BT_BLUEZ_NAME,
1236                         char_handle,
1237                         BT_PROPERTIES_INTERFACE,
1238                         NULL, &error);
1239
1240         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1241
1242         result = g_dbus_proxy_call_sync(properties_proxy,
1243                                 "GetAll",
1244                                 g_variant_new("(s)", GATT_DESC_INTERFACE),
1245                                 G_DBUS_CALL_FLAGS_NONE,
1246                                 -1,
1247                                 NULL,
1248                                 &error);
1249
1250         if (!result) {
1251                 if (error != NULL) {
1252                         BT_ERR("Fail to get properties (Error: %s)", error->message);
1253                         g_clear_error(&error);
1254                 } else
1255                         BT_ERR("Fail to get properties");
1256                 g_object_unref(properties_proxy);
1257                 return BLUETOOTH_ERROR_INTERNAL;
1258         }
1259         g_variant_get(result, "(a{sv})", &property_iter);
1260         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1261                 if (!g_strcmp0(key, "UUID")) {
1262                         uuid = g_variant_get_string(value, &len);
1263                         if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
1264                                 BT_DBG("GATT_USER_DESC_UUID");
1265                                 desc_type = USER_DESC;
1266                         } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) {
1267                                 BT_DBG("GATT_CHAR_FORMAT");
1268                                 desc_type = CHAR_FORMAT;
1269                         } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) {
1270                                 BT_DBG("GATT_CHAR_CLIENT_CONF");
1271                                 desc_type = CLIENT_CONF;
1272                         } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) {
1273                                 BT_DBG("GATT_CHAR_SERVER_CONF");
1274                                 desc_type = SERVER_CONF;
1275                         } else {
1276                                 BT_DBG("descriptor uuid = %s", uuid);
1277                         }
1278                 } else if (!g_strcmp0(key, "Value")) {
1279                         switch (desc_type) {
1280                         case CHAR_FORMAT:
1281                                 BT_DBG("Format descriptor");
1282                                 g_variant_get(value, "(yyqyq)",
1283                                                 &(characteristic->format.format),
1284                                                 &(characteristic->format.exponent),
1285                                                 &(characteristic->format.unit),
1286                                                 &(characteristic->format.name_space),
1287                                                 &(characteristic->format.description));
1288                                 break;
1289                         case USER_DESC:
1290                                 BT_DBG("User descriptor");
1291                                 g_variant_get(value, "ay", &desc_value_iter);
1292                                 len = g_variant_get_size((GVariant *)desc_value_iter);
1293
1294                                 if (len > 0)
1295                                         characteristic->description = (char *)g_malloc0(len + 1);
1296
1297                                 for (i = 0; i < len; i++) {
1298                                         g_variant_iter_loop(desc_value_iter, "y",
1299                                                 &characteristic->description[i]);
1300                                         BT_DBG("description = %s", characteristic->description);
1301                                 }
1302                                 g_variant_iter_free(desc_value_iter);
1303                                 break;
1304                         case CLIENT_CONF:
1305                                 BT_DBG(" CLIENT_CONF");
1306                                 break;
1307                         case SERVER_CONF:
1308                                 BT_DBG(" SERVER_CONF");
1309                                 break;
1310                         default:
1311                                 break;
1312                         }
1313                 }
1314         }
1315
1316         g_variant_iter_free(property_iter);
1317         g_variant_unref(result);
1318         g_object_unref(properties_proxy);
1319
1320         BT_DBG("-");
1321         return ret;
1322 }
1323
1324
1325 static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
1326                         GAsyncResult *res, gpointer user_data)
1327 {
1328         BT_DBG("+");
1329         GVariant *value;
1330         GVariant        *char_value;
1331         GVariantIter *char_iter;
1332         char *char_handle;
1333         GError *error = NULL;
1334         bt_user_info_t *user_info;
1335         bt_gatt_char_property_t characteristic = {0, };
1336         int ret = BLUETOOTH_ERROR_INTERNAL;
1337
1338         user_info = _bt_get_user_data(BT_COMMON);
1339
1340         value = g_dbus_proxy_call_finish(proxy, res, &error);
1341
1342         if (value == NULL) {
1343                 if (error != NULL) {
1344                         BT_ERR("Get characteristic descriptor failed\n errCode[%x],"
1345                                         "message[%s]\n", error->code, error->message);
1346                         g_clear_error(&error);
1347                 } else {
1348                         BT_ERR("Get characteristic descriptor failed\n");
1349                 }
1350                 if (user_info) {
1351                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1352                                 BLUETOOTH_ERROR_INTERNAL, NULL,
1353                                 user_info->cb, user_info->user_data);
1354                 }
1355                 g_free(user_data);
1356                 g_object_unref(proxy);
1357                 return;
1358         }
1359
1360         g_variant_get(value, "(v)", &char_value);
1361         g_variant_get(char_value, "ao", &char_iter);
1362
1363         while (g_variant_iter_loop(char_iter, "&o",  &char_handle)) {
1364                 BT_DBG("object path of descriptor = %s", char_handle);
1365                 if (char_handle) {
1366                         ret = __bluetooth_gatt_descriptor_iter(char_handle,
1367                                                 &characteristic);
1368                         BT_DBG("Descriptor read status [%d]", ret);
1369                 }
1370         }
1371
1372         characteristic.handle = user_data;
1373         if (user_info) {
1374                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1375                                 ret, &characteristic, user_info->cb, user_info->user_data);
1376         }
1377         bluetooth_gatt_free_char_property(&characteristic);
1378
1379         g_variant_iter_free(char_iter);
1380         g_variant_unref(value);
1381         BT_DBG("-");
1382 }
1383
1384 BT_EXPORT_API int bluetooth_gatt_discover_characteristic_descriptor(
1385                         const char *characteristic_handle)
1386 {
1387         GDBusProxy *properties_proxy = NULL;
1388         GDBusConnection *g_conn;
1389         char *handle;
1390         GError *error = NULL;
1391
1392         BT_CHECK_PARAMETER(characteristic_handle, return);
1393         BT_CHECK_ENABLED(return);
1394
1395         g_conn = _bt_gdbus_get_system_gconn();
1396         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1397
1398         properties_proxy = g_dbus_proxy_new_sync(g_conn,
1399                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1400                         BT_BLUEZ_NAME,
1401                         characteristic_handle,
1402                         BT_PROPERTIES_INTERFACE,
1403                         NULL, &error);
1404
1405         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1406
1407         handle = g_strdup(characteristic_handle);
1408         g_dbus_proxy_call(properties_proxy,
1409                         "Get",
1410                         g_variant_new("(ss)",
1411                                 GATT_CHAR_INTERFACE, "Descriptors"),
1412                         G_DBUS_CALL_FLAGS_NONE,
1413                         -1, NULL,
1414                         (GAsyncReadyCallback)bluetooth_gatt_get_char_desc_cb,
1415                         (gpointer)handle);
1416
1417         return BLUETOOTH_ERROR_NONE;
1418 }
1419
1420 static void __bluetooth_internal_read_desc_cb(GObject *source_object,
1421                         GAsyncResult *res,
1422                         gpointer user_data)
1423 {
1424         GError *error = NULL;
1425         bt_user_info_t *user_info;
1426         bt_gatt_char_property_t char_value =  { 0, };
1427         GDBusConnection *system_gconn = NULL;
1428         GVariant *value;
1429         GByteArray *gp_byte_array = NULL;
1430         GVariantIter *iter;
1431         guint8 g_byte;
1432         gint att_error_code;
1433
1434         BT_DBG("+");
1435         user_info = _bt_get_user_data(BT_COMMON);
1436         system_gconn = _bt_gdbus_get_system_gconn();
1437
1438         char_value.handle = user_data;
1439         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1440
1441         if (error) {
1442                 BT_ERR("Error : %s \n", error->message);
1443                 g_clear_error(&error);
1444                 if (user_info) {
1445                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1446                                         BLUETOOTH_ERROR_INTERNAL, NULL,
1447                                         user_info->cb, user_info->user_data);
1448                 }
1449                 g_free(char_value.handle);
1450                 return;
1451         }
1452
1453         g_variant_get(value, "(yay)", &att_error_code, &iter);
1454
1455         if (att_error_code != 0) {
1456                 if (user_info) {
1457                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1458                                 att_error_code, NULL,
1459                                 user_info->cb, user_info->user_data);
1460                 }
1461                 g_free(char_value.handle);
1462                 g_variant_unref(value);
1463                 g_variant_iter_free(iter);
1464                 return;
1465         }
1466
1467         gp_byte_array = g_byte_array_new();
1468         while (g_variant_iter_loop(iter, "y",  &g_byte))
1469                 g_byte_array_append(gp_byte_array, &g_byte, 1);
1470
1471         if (gp_byte_array->len != 0) {
1472                 char_value.val_len = (unsigned int)gp_byte_array->len;
1473                 char_value.description = (char *)gp_byte_array->data;
1474         }
1475
1476         if (user_info) {
1477                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1478                                 BLUETOOTH_ERROR_NONE, &char_value,
1479                                 user_info->cb, user_info->user_data);
1480         }
1481
1482         g_byte_array_free(gp_byte_array, TRUE);
1483         g_free(char_value.handle);
1484         g_variant_unref(value);
1485         g_variant_iter_free(iter);
1486
1487         BT_DBG("-");
1488 }
1489
1490 BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *char_descriptor)
1491 {
1492         GDBusConnection *conn;
1493         GVariantBuilder *builder;
1494         guint offset = 0;
1495         char *handle;
1496
1497         BT_DBG("+");
1498         BT_CHECK_PARAMETER(char_descriptor, return);
1499         BT_CHECK_ENABLED(return);
1500
1501         conn = _bt_gdbus_get_system_gconn();
1502         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1503
1504         handle = g_strdup(char_descriptor);
1505
1506         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1507
1508         /*offset*/
1509         g_variant_builder_add(builder, "{sv}", "offset",
1510                                 g_variant_new("q", offset));
1511         /* Device Object path*/
1512 //  g_variant_builder_add(builder, "{sv}", "device",
1513 //  g_variant_new("o", serv_info->serv_path));
1514
1515         g_dbus_connection_call(conn,
1516                         BT_BLUEZ_NAME,
1517                         char_descriptor,
1518                         GATT_DESC_INTERFACE,
1519                         "ReadValue",
1520                         g_variant_new("(a{sv})", builder),
1521                         G_VARIANT_TYPE("(yay)"),
1522                         G_DBUS_CALL_FLAGS_NONE,
1523                         -1,
1524                         NULL,
1525                         (GAsyncReadyCallback)__bluetooth_internal_read_desc_cb,
1526                         (gpointer)handle);
1527         g_variant_builder_unref(builder);
1528
1529         BT_DBG("-");
1530         return BLUETOOTH_ERROR_NONE;
1531 }
1532
1533 static void __bluetooth_internal_write_desc_cb(GObject *source_object,
1534                         GAsyncResult *res,
1535                         gpointer user_data)
1536 {
1537         GError *error = NULL;
1538         bt_user_info_t *user_info;
1539         GDBusConnection *system_gconn = NULL;
1540         GVariant *value;
1541         int result = BLUETOOTH_ERROR_NONE;
1542         guint8 att_ecode = 0;
1543
1544         BT_DBG("+");
1545         user_info = _bt_get_user_data(BT_COMMON);
1546
1547         system_gconn = _bt_gdbus_get_system_gconn();
1548         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1549
1550         if (error) {
1551                 BT_ERR("Error : %s \n", error->message);
1552                 g_clear_error(&error);
1553                 result = BLUETOOTH_ERROR_INTERNAL;
1554         } else {
1555                 g_variant_get(value, "(y)", &att_ecode);
1556                 if (att_ecode) {
1557                         result =  att_ecode;
1558                         BT_ERR("ATT Error code: %d \n", att_ecode);
1559                 }
1560         }
1561
1562         if (user_info) {
1563                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1564                                 result, NULL,
1565                                 user_info->cb, user_info->user_data);
1566         }
1567
1568         if (value)
1569                 g_variant_unref(value);
1570
1571         BT_DBG("-");
1572 }
1573
1574 BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(
1575                         const char *desc_handle, const guint8 *value, int length)
1576 {
1577         GVariant *val, *options;
1578         GDBusConnection *conn;
1579         GVariantBuilder *builder1;
1580         GVariantBuilder *builder2;
1581         guint offset = 0;
1582         int i;
1583
1584         BT_DBG("+");
1585         BT_CHECK_PARAMETER(desc_handle, return);
1586         BT_CHECK_PARAMETER(value, return);
1587         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1588         BT_CHECK_ENABLED(return);
1589
1590         conn = _bt_gdbus_get_system_gconn();
1591         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1592
1593         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1594
1595         for (i = 0; i < length; i++)
1596                 g_variant_builder_add(builder1, "y", value[i]);
1597
1598         val = g_variant_new("ay", builder1);
1599
1600         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1601         /*offset*/
1602         g_variant_builder_add(builder2, "{sv}", "offset",
1603                                 g_variant_new_uint16(offset));
1604
1605         /* Device Object path*/
1606 //      g_variant_builder_add(builder2, "{sv}", "device",
1607 //      g_variant_new_object("o", NULL));
1608
1609         options = g_variant_new("a{sv}", builder2);
1610
1611         g_dbus_connection_call(conn,
1612                                 BT_BLUEZ_NAME,
1613                                 desc_handle,
1614                                 GATT_DESC_INTERFACE,
1615                                 "WriteValue",
1616                                 g_variant_new("(@ay@a{sv})",
1617                                 val, options),
1618                                 G_VARIANT_TYPE("(y)"),
1619                                 G_DBUS_CALL_FLAGS_NONE,
1620                                 -1, NULL,
1621                                 (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
1622                                 NULL);
1623
1624         g_variant_builder_unref(builder1);
1625         g_variant_builder_unref(builder2);
1626
1627         BT_DBG("-");
1628         return BLUETOOTH_ERROR_NONE;
1629 }
1630
1631 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle)
1632 {
1633         GDBusConnection *conn;
1634         GError *error = NULL;
1635         int ret = BLUETOOTH_ERROR_NONE;
1636
1637         BT_CHECK_PARAMETER(char_handle, return);
1638         BT_CHECK_ENABLED(return);
1639
1640         BT_INFO_C("### Enable CCCD : %s", char_handle);
1641
1642         conn = _bt_gdbus_get_system_gconn();
1643         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1644
1645         g_dbus_connection_call_sync(conn,
1646                         BT_BLUEZ_NAME,
1647                         char_handle,
1648                         GATT_CHAR_INTERFACE,
1649                         "StartNotify",
1650                         NULL,
1651                         NULL,
1652                         G_DBUS_CALL_FLAGS_NONE,
1653                         GATT_DEFAULT_TIMEOUT, NULL, &error);
1654
1655         if (error) {
1656                 g_dbus_error_strip_remote_error(error);
1657                 BT_ERR_C("### Watch Failed: %s", error->message);
1658                 if (g_strrstr(error->message, "Already notifying"))
1659                         ret = BLUETOOTH_ERROR_NONE;
1660                 else if (g_strrstr(error->message, "In Progress"))
1661                         ret = BLUETOOTH_ERROR_IN_PROGRESS;
1662                 else if (g_strrstr(error->message, "Operation is not supported"))
1663                         ret = BLUETOOTH_ERROR_NOT_SUPPORT;
1664 /*failed because of either Insufficient Authorization or Write Not Permitted */
1665                 else if (g_strrstr(error->message, "Write not permitted") ||
1666                                 g_strrstr(error->message, "Operation Not Authorized"))
1667                         ret = BLUETOOTH_ERROR_PERMISSION_DEINED;
1668 /* failed because of either Insufficient Authentication,
1669         Insufficient Encryption Key Size, or Insufficient Encryption. */
1670                 else if (g_strrstr(error->message, "Not paired"))
1671                         ret = BLUETOOTH_ERROR_NOT_PAIRED;
1672                 else
1673                         ret = BLUETOOTH_ERROR_INTERNAL;
1674
1675                 g_clear_error(&error);
1676         }
1677
1678         return ret;
1679 }
1680
1681 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle)
1682 {
1683
1684         GDBusConnection *conn;
1685         GError *error = NULL;
1686         int ret = BLUETOOTH_ERROR_NONE;
1687         BT_CHECK_PARAMETER(char_handle, return);
1688
1689         BT_CHECK_ENABLED(return);
1690
1691         BT_INFO("Disable CCCD : %s", char_handle);
1692
1693         conn = _bt_gdbus_get_system_gconn();
1694         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1695
1696         g_dbus_connection_call_sync(conn,
1697                         BT_BLUEZ_NAME,
1698                         char_handle,
1699                         GATT_CHAR_INTERFACE,
1700                         "StopNotify",
1701                         NULL,
1702                         NULL,
1703                         G_DBUS_CALL_FLAGS_NONE,
1704                         GATT_DEFAULT_TIMEOUT, NULL, &error);
1705
1706         if (error) {
1707                 BT_ERR("Watch Failed: %s", error->message);
1708                 g_clear_error(&error);
1709                 ret =  BLUETOOTH_ERROR_INTERNAL;
1710         }
1711
1712         return ret;
1713 }