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