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