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