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