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