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