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