Fix the build error for Tizen 4.0 gcc62 toolchain
[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 void __bluetooth_internal_read_cb(GObject *source_object,
876                         GAsyncResult *res,
877                         gpointer user_data)
878 {
879         GError *error = NULL;
880         bt_user_info_t *user_info;
881         bt_gatt_char_value_t char_value =  { 0, };
882         GDBusConnection *system_gconn = NULL;
883         GVariant *value;
884         GByteArray *gp_byte_array = NULL;
885         GVariantIter *iter;
886         guint8 g_byte;
887         int ret = BLUETOOTH_ERROR_NONE;
888
889         BT_DBG("+");
890         user_info = _bt_get_user_data(BT_COMMON);
891
892         system_gconn = _bt_gdbus_get_system_gconn();
893         value = g_dbus_connection_call_finish(system_gconn, res, &error);
894
895         if (error) {
896                 BT_ERR("Error : %s \n", error->message);
897                 if (g_strrstr(error->message, "Not paired"))
898                         ret = BLUETOOTH_ERROR_NOT_PAIRED;
899                 else
900                         ret = BLUETOOTH_ERROR_INTERNAL;
901
902                 g_clear_error(&error);
903                 if (user_info) {
904                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
905                                 ret, NULL,
906                                 user_info->cb, user_info->user_data);
907                 }
908                 g_free(user_data);
909                 return;
910         }
911
912         char_value.char_handle = user_data;
913         gp_byte_array = g_byte_array_new();
914         g_variant_get(value, "(ay)", &iter);
915
916         while (g_variant_iter_loop(iter, "y", &g_byte))
917                 g_byte_array_append(gp_byte_array, &g_byte, 1);
918
919         if (gp_byte_array->len != 0) {
920                 char_value.val_len = gp_byte_array->len;
921                 char_value.char_value = gp_byte_array->data;
922         }
923
924         if (user_info) {
925                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
926                                 BLUETOOTH_ERROR_NONE, &char_value,
927                                 user_info->cb, user_info->user_data);
928         }
929
930         g_free(char_value.char_handle);
931         g_byte_array_free(gp_byte_array, TRUE);
932         g_variant_unref(value);
933         g_variant_iter_free(iter);
934
935         BT_DBG("-");
936 }
937
938 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *characteristic)
939 {
940         GDBusConnection *conn;
941         char *handle;
942
943         BT_CHECK_PARAMETER(characteristic, return);
944         BT_CHECK_ENABLED(return);
945
946         conn = _bt_gdbus_get_system_gconn();
947         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
948
949         handle = g_strdup(characteristic);
950
951         g_dbus_connection_call(conn,
952                         BT_BLUEZ_NAME,
953                         characteristic,
954                         GATT_CHAR_INTERFACE,
955                         "ReadValue",
956                         NULL,
957                         G_VARIANT_TYPE("(ay)"),
958                         G_DBUS_CALL_FLAGS_NONE,
959                         -1,
960                         NULL,
961                         (GAsyncReadyCallback)__bluetooth_internal_read_cb,
962                         (gpointer)handle);
963
964         return BLUETOOTH_ERROR_NONE;
965 }
966
967 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
968                 const char *char_handle, const guint8 *value, int length)
969 {
970         GVariant *val;
971         GVariantBuilder *builder;
972         GError *error = NULL;
973         GDBusConnection *conn;
974         int i = 0;
975
976         BT_DBG("+");
977         BT_CHECK_PARAMETER(char_handle, return);
978         BT_CHECK_PARAMETER(value, return);
979         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
980         BT_CHECK_ENABLED(return);
981
982         conn = _bt_gdbus_get_system_gconn();
983         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
984
985         builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
986
987         for (i = 0; i < length; i++)
988                 g_variant_builder_add(builder, "y", value[i]);
989
990         val = g_variant_new("(ay)", builder);
991
992         g_dbus_connection_call_sync(conn,
993                         BT_BLUEZ_NAME,
994                         char_handle,
995                         GATT_CHAR_INTERFACE,
996                         "WriteValue",
997                         val,
998                         NULL,
999                         G_DBUS_CALL_FLAGS_NONE,
1000                         -1, NULL, &error);
1001
1002         if (error) {
1003                 BT_ERR("Set value Failed: %s", error->message);
1004                 g_clear_error(&error);
1005                 g_variant_builder_unref(builder);
1006                 return BLUETOOTH_ERROR_INTERNAL;
1007         }
1008
1009         g_variant_builder_unref(builder);
1010
1011         BT_DBG("-");
1012         return BLUETOOTH_ERROR_NONE;
1013 }
1014
1015 static void __bluetooth_internal_write_cb(GObject *source_object,
1016                         GAsyncResult *res,
1017                         gpointer user_data)
1018 {
1019         GError *error = NULL;
1020         bt_user_info_t *user_info;
1021         GDBusConnection *system_gconn = NULL;
1022         GVariant *value;
1023         int result = BLUETOOTH_ERROR_NONE;
1024         guint8 att_ecode = 0;
1025
1026         user_info = _bt_get_user_data(BT_COMMON);
1027
1028         system_gconn = _bt_gdbus_get_system_gconn();
1029         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1030
1031         if (error) {
1032                 BT_ERR("Error : %s \n", error->message);
1033                 g_clear_error(&error);
1034                 result = BLUETOOTH_ERROR_INTERNAL;
1035         } else {
1036                 g_variant_get(value, "(y)", &att_ecode);
1037                 if (att_ecode) {
1038                         result =  att_ecode;
1039                         BT_ERR("ATT Error code: %d \n", att_ecode);
1040                 }
1041         }
1042
1043         if (user_info) {
1044                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
1045                                 result, NULL,
1046                                 user_info->cb, user_info->user_data);
1047         } else {
1048                 BT_ERR("user info is null");
1049         }
1050
1051         if (value)
1052                 g_variant_unref(value);
1053
1054         return;
1055 }
1056
1057 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
1058                 const char *char_handle, const guint8 *value, int length, guint8 write_type)
1059 {
1060         GVariant *val;
1061         GVariantBuilder *builder;
1062         GDBusConnection *conn;
1063         int i = 0;
1064         int ret = BLUETOOTH_ERROR_NONE;
1065
1066         BT_CHECK_PARAMETER(char_handle, return);
1067         BT_CHECK_PARAMETER(value, return);
1068         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1069         BT_CHECK_ENABLED_INTERNAL(return);
1070
1071         conn = _bt_gdbus_get_system_gconn();
1072         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1073
1074         builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1075
1076         for (i = 0; i < length; i++)
1077                 g_variant_builder_add(builder, "y", value[i]);
1078
1079         val = g_variant_new("ay", builder);
1080         g_dbus_connection_call(conn,
1081                         BT_BLUEZ_NAME,
1082                         char_handle,
1083                         GATT_CHAR_INTERFACE,
1084                         "WriteValuebyType",
1085                         g_variant_new("(y@ay)", write_type, val),
1086                         G_VARIANT_TYPE("(y)"),
1087                         G_DBUS_CALL_FLAGS_NONE,
1088                         -1, NULL,
1089                         (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1090                         NULL);
1091
1092         g_variant_builder_unref(builder);
1093         return ret;
1094 }
1095
1096 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
1097                         const char *char_handle, const guint8 *value, int length)
1098 {
1099         GVariant *val;
1100         GDBusConnection *conn;
1101         GVariantBuilder *builder;
1102         int i;
1103
1104         BT_DBG("+");
1105         BT_CHECK_PARAMETER(char_handle, return);
1106         BT_CHECK_PARAMETER(value, return);
1107         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1108         BT_CHECK_ENABLED(return);
1109
1110         conn = _bt_gdbus_get_system_gconn();
1111         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1112
1113         builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1114
1115         for (i = 0; i < length; i++) {
1116                 g_variant_builder_add(builder, "y", value[i]);
1117                 BT_DBG("value [] = %d", value[i]);
1118         }
1119
1120         val = g_variant_new("(ay)", builder);
1121
1122         g_dbus_connection_call(conn,
1123                                 BT_BLUEZ_NAME,
1124                                 char_handle,
1125                                 GATT_CHAR_INTERFACE,
1126                                 "WriteValue",
1127                                 val,
1128                                 NULL,
1129                                 G_DBUS_CALL_FLAGS_NONE,
1130                                 -1, NULL,
1131                                 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1132                                 NULL);
1133
1134         g_variant_builder_unref(builder);
1135
1136         BT_DBG("-");
1137         return BLUETOOTH_ERROR_NONE;
1138 }
1139
1140 static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
1141                         bt_gatt_char_property_t *characteristic)
1142 {
1143         BT_DBG("+");
1144         GDBusProxy *properties_proxy = NULL;
1145         GError *error = NULL;
1146         GVariant *value = NULL;
1147         GVariant *result = NULL;
1148         GDBusConnection *g_conn;
1149         int i, ret = BLUETOOTH_ERROR_NONE;
1150         const char *uuid = NULL;
1151         gsize len = 0;
1152         GVariantIter *desc_value_iter, *property_iter;
1153         const gchar *key;
1154         char_descriptor_type_t desc_type = TYPE_NONE;
1155
1156         g_conn = _bt_gdbus_get_system_gconn();
1157         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1158
1159         properties_proxy = g_dbus_proxy_new_sync(g_conn,
1160                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1161                         BT_BLUEZ_NAME,
1162                         char_handle,
1163                         BT_PROPERTIES_INTERFACE,
1164                         NULL, &error);
1165
1166         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1167
1168         result = g_dbus_proxy_call_sync(properties_proxy,
1169                                 "GetAll",
1170                                 g_variant_new("(s)", GATT_DESC_INTERFACE),
1171                                 G_DBUS_CALL_FLAGS_NONE,
1172                                 -1,
1173                                 NULL,
1174                                 &error);
1175
1176         if (!result) {
1177                 if (error != NULL) {
1178                         BT_ERR("Fail to get properties (Error: %s)", error->message);
1179                         g_clear_error(&error);
1180                 } else
1181                         BT_ERR("Fail to get properties");
1182                 g_object_unref(properties_proxy);
1183                 return BLUETOOTH_ERROR_INTERNAL;
1184         }
1185         g_variant_get(result, "(a{sv})", &property_iter);
1186         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1187                 if (!g_strcmp0(key, "UUID")) {
1188                         uuid = g_variant_get_string(value, &len);
1189                         if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
1190                                 BT_DBG("GATT_USER_DESC_UUID");
1191                                 desc_type = USER_DESC;
1192                         } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) {
1193                                 BT_DBG("GATT_CHAR_FORMAT");
1194                                 desc_type = CHAR_FORMAT;
1195                         } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) {
1196                                 BT_DBG("GATT_CHAR_CLIENT_CONF");
1197                                 desc_type = CLIENT_CONF;
1198                         } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) {
1199                                 BT_DBG("GATT_CHAR_SERVER_CONF");
1200                                 desc_type = SERVER_CONF;
1201                         } else {
1202                                 BT_DBG("descriptor uuid = %s", uuid);
1203                         }
1204                 } else if (!g_strcmp0(key, "Value")) {
1205                         switch (desc_type) {
1206                         case CHAR_FORMAT:
1207                                 BT_DBG("Format descriptor");
1208                                 g_variant_get(value, "(yyqyq)",
1209                                                 &(characteristic->format.format),
1210                                                 &(characteristic->format.exponent),
1211                                                 &(characteristic->format.unit),
1212                                                 &(characteristic->format.name_space),
1213                                                 &(characteristic->format.description));
1214                                 break;
1215                         case USER_DESC:
1216                                 BT_DBG("User descriptor");
1217                                 g_variant_get(value, "ay", &desc_value_iter);
1218                                 len = g_variant_get_size((GVariant *)desc_value_iter);
1219
1220                                 if (len > 0)
1221                                         characteristic->description = (char *)g_malloc0(len + 1);
1222
1223                                 for (i = 0; i < len; i++) {
1224                                         g_variant_iter_loop(desc_value_iter, "y",
1225                                                 &characteristic->description[i]);
1226                                         BT_DBG("description = %s", characteristic->description);
1227                                 }
1228                                 g_variant_iter_free(desc_value_iter);
1229                                 break;
1230                         case CLIENT_CONF:
1231                                 BT_DBG(" CLIENT_CONF");
1232                                 break;
1233                         case SERVER_CONF:
1234                                 BT_DBG(" SERVER_CONF");
1235                                 break;
1236                         default:
1237                                 break;
1238                         }
1239                 }
1240         }
1241
1242         g_variant_iter_free(property_iter);
1243         g_variant_unref(result);
1244         g_object_unref(properties_proxy);
1245
1246         BT_DBG("-");
1247         return ret;
1248 }
1249
1250
1251 static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
1252                         GAsyncResult *res, gpointer user_data)
1253 {
1254         BT_DBG("+");
1255         GVariant *value;
1256         GVariant        *char_value;
1257         GVariantIter *char_iter;
1258         char *char_handle;
1259         GError *error = NULL;
1260         bt_user_info_t *user_info;
1261         bt_gatt_char_property_t characteristic = {0, };
1262         int ret = BLUETOOTH_ERROR_INTERNAL;
1263
1264         user_info = _bt_get_user_data(BT_COMMON);
1265
1266         value = g_dbus_proxy_call_finish(proxy, res, &error);
1267
1268         if (value == NULL) {
1269                 if (error != NULL) {
1270                         BT_ERR("Get characteristic descriptor failed\n errCode[%x],"
1271                                         "message[%s]\n", error->code, error->message);
1272                         g_clear_error(&error);
1273                 } else {
1274                         BT_ERR("Get characteristic descriptor failed\n");
1275                 }
1276                 if (user_info) {
1277                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1278                                 BLUETOOTH_ERROR_INTERNAL, NULL,
1279                                 user_info->cb, user_info->user_data);
1280                 }
1281                 g_free(user_data);
1282                 g_object_unref(proxy);
1283                 return;
1284         }
1285
1286         g_variant_get(value, "(v)", &char_value);
1287         g_variant_get(char_value, "ao", &char_iter);
1288
1289         while (g_variant_iter_loop(char_iter, "&o",  &char_handle)) {
1290                 BT_DBG("object path of descriptor = %s", char_handle);
1291                 if (char_handle) {
1292                         ret = __bluetooth_gatt_descriptor_iter(char_handle,
1293                                                 &characteristic);
1294                         BT_DBG("Descriptor read status [%d]", ret);
1295                 }
1296         }
1297
1298         characteristic.handle = user_data;
1299         if (user_info) {
1300                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1301                                 ret, &characteristic, user_info->cb, user_info->user_data);
1302         }
1303         bluetooth_gatt_free_char_property(&characteristic);
1304
1305         g_variant_iter_free(char_iter);
1306         g_variant_unref(value);
1307         BT_DBG("-");
1308 }
1309
1310 BT_EXPORT_API int bluetooth_gatt_discover_characteristic_descriptor(
1311                         const char *characteristic_handle)
1312 {
1313         GDBusProxy *properties_proxy = NULL;
1314         GDBusConnection *g_conn;
1315         char *handle;
1316         GError *error = NULL;
1317
1318         BT_CHECK_PARAMETER(characteristic_handle, return);
1319         BT_CHECK_ENABLED(return);
1320
1321         g_conn = _bt_gdbus_get_system_gconn();
1322         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1323
1324         properties_proxy = g_dbus_proxy_new_sync(g_conn,
1325                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1326                         BT_BLUEZ_NAME,
1327                         characteristic_handle,
1328                         BT_PROPERTIES_INTERFACE,
1329                         NULL, &error);
1330
1331         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1332
1333         handle = g_strdup(characteristic_handle);
1334         g_dbus_proxy_call(properties_proxy,
1335                         "Get",
1336                         g_variant_new("(ss)",
1337                                 GATT_CHAR_INTERFACE, "Descriptors"),
1338                         G_DBUS_CALL_FLAGS_NONE,
1339                         -1, NULL,
1340                         (GAsyncReadyCallback)bluetooth_gatt_get_char_desc_cb,
1341                         (gpointer)handle);
1342
1343         return BLUETOOTH_ERROR_NONE;
1344 }
1345
1346 static void __bluetooth_internal_read_desc_cb(GObject *source_object,
1347                         GAsyncResult *res,
1348                         gpointer user_data)
1349 {
1350         GError *error = NULL;
1351         bt_user_info_t *user_info;
1352         bt_gatt_char_property_t char_value =  { 0, };
1353         GDBusConnection *system_gconn = NULL;
1354         GVariant *value;
1355         GByteArray *gp_byte_array = NULL;
1356         GVariantIter *iter;
1357         guint8 g_byte;
1358
1359         BT_DBG("+");
1360         user_info = _bt_get_user_data(BT_COMMON);
1361         system_gconn = _bt_gdbus_get_system_gconn();
1362
1363         char_value.handle = user_data;
1364         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1365
1366         if (error) {
1367                 BT_ERR("Error : %s \n", error->message);
1368                 g_clear_error(&error);
1369                 if (user_info) {
1370                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1371                                         BLUETOOTH_ERROR_INTERNAL, NULL,
1372                                         user_info->cb, user_info->user_data);
1373                 }
1374                 g_free(char_value.handle);
1375                 return;
1376         }
1377
1378         gp_byte_array = g_byte_array_new();
1379         g_variant_get(value, "(ay)", &iter);
1380
1381         while (g_variant_iter_loop(iter, "y",  &g_byte))
1382                 g_byte_array_append(gp_byte_array, &g_byte, 1);
1383
1384         if (gp_byte_array->len != 0) {
1385                 char_value.val_len = (unsigned int)gp_byte_array->len;
1386                 char_value.description = (char *)gp_byte_array->data;
1387         }
1388
1389         if (user_info) {
1390                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1391                                 BLUETOOTH_ERROR_NONE, &char_value,
1392                                 user_info->cb, user_info->user_data);
1393         }
1394
1395         g_byte_array_free(gp_byte_array, TRUE);
1396         g_free(char_value.handle);
1397         g_variant_unref(value);
1398         g_variant_iter_free(iter);
1399
1400         BT_DBG("-");
1401 }
1402
1403 BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *char_descriptor)
1404 {
1405         GDBusConnection *conn;
1406         char *handle;
1407
1408         BT_DBG("+");
1409         BT_CHECK_PARAMETER(char_descriptor, return);
1410         BT_CHECK_ENABLED(return);
1411
1412         conn = _bt_gdbus_get_system_gconn();
1413         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1414
1415         handle = g_strdup(char_descriptor);
1416
1417         g_dbus_connection_call(conn,
1418                         BT_BLUEZ_NAME,
1419                         char_descriptor,
1420                         GATT_DESC_INTERFACE,
1421                         "ReadValue",
1422                         NULL,
1423                         G_VARIANT_TYPE("(ay)"),
1424                         G_DBUS_CALL_FLAGS_NONE,
1425                         -1,
1426                         NULL,
1427                         (GAsyncReadyCallback)__bluetooth_internal_read_desc_cb,
1428                         (gpointer)handle);
1429
1430         BT_DBG("-");
1431         return BLUETOOTH_ERROR_NONE;
1432 }
1433
1434 static void __bluetooth_internal_write_desc_cb(GObject *source_object,
1435                         GAsyncResult *res,
1436                         gpointer user_data)
1437 {
1438         GError *error = NULL;
1439         bt_user_info_t *user_info;
1440         GDBusConnection *system_gconn = NULL;
1441         GVariant *value;
1442         int result = BLUETOOTH_ERROR_NONE;
1443         guint8 att_ecode = 0;
1444
1445         BT_DBG("+");
1446         user_info = _bt_get_user_data(BT_COMMON);
1447
1448         system_gconn = _bt_gdbus_get_system_gconn();
1449         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1450
1451         if (error) {
1452                 BT_ERR("Error : %s \n", error->message);
1453                 g_clear_error(&error);
1454                 result = BLUETOOTH_ERROR_INTERNAL;
1455         } else {
1456                 g_variant_get(value, "(y)", &att_ecode);
1457                 if (att_ecode) {
1458                         result =  att_ecode;
1459                         BT_ERR("ATT Error code: %d \n", att_ecode);
1460                 }
1461         }
1462
1463         if (user_info) {
1464                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1465                                 result, NULL,
1466                                 user_info->cb, user_info->user_data);
1467         }
1468
1469         if (value)
1470                 g_variant_unref(value);
1471
1472         BT_DBG("-");
1473 }
1474
1475 BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(
1476                         const char *desc_handle, const guint8 *value, int length)
1477 {
1478         GVariant *val;
1479         GDBusConnection *conn;
1480         GVariantBuilder *builder;
1481         int i;
1482
1483         BT_DBG("+");
1484         BT_CHECK_PARAMETER(desc_handle, return);
1485         BT_CHECK_PARAMETER(value, return);
1486         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1487         BT_CHECK_ENABLED(return);
1488
1489         conn = _bt_gdbus_get_system_gconn();
1490         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1491
1492         builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1493
1494         for (i = 0; i < length; i++)
1495                 g_variant_builder_add(builder, "y", value[i]);
1496
1497         val = g_variant_new("(ay)", builder);
1498
1499         g_dbus_connection_call(conn,
1500                                 BT_BLUEZ_NAME,
1501                                 desc_handle,
1502                                 GATT_DESC_INTERFACE,
1503                                 "WriteValue",
1504                                 val,
1505                                 G_VARIANT_TYPE("(y)"),
1506                                 G_DBUS_CALL_FLAGS_NONE,
1507                                 -1, NULL,
1508                                 (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
1509                                 NULL);
1510
1511         g_variant_builder_unref(builder);
1512
1513         BT_DBG("-");
1514         return BLUETOOTH_ERROR_NONE;
1515 }
1516
1517 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle)
1518 {
1519         GDBusConnection *conn;
1520         GError *error = NULL;
1521         int ret = BLUETOOTH_ERROR_NONE;
1522
1523         BT_CHECK_PARAMETER(char_handle, return);
1524         BT_CHECK_ENABLED(return);
1525
1526         BT_INFO_C("### Enable CCCD : %s", char_handle);
1527
1528         conn = _bt_gdbus_get_system_gconn();
1529         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1530
1531         g_dbus_connection_call_sync(conn,
1532                         BT_BLUEZ_NAME,
1533                         char_handle,
1534                         GATT_CHAR_INTERFACE,
1535                         "StartNotify",
1536                         NULL,
1537                         NULL,
1538                         G_DBUS_CALL_FLAGS_NONE,
1539                         GATT_DEFAULT_TIMEOUT, NULL, &error);
1540
1541         if (error) {
1542                 g_dbus_error_strip_remote_error(error);
1543                 BT_ERR_C("### Watch Failed: %s", error->message);
1544                 if (g_strrstr(error->message, "Already notifying"))
1545                         ret = BLUETOOTH_ERROR_NONE;
1546                 else if (g_strrstr(error->message, "In Progress"))
1547                         ret = BLUETOOTH_ERROR_IN_PROGRESS;
1548                 else if (g_strrstr(error->message, "Operation is not supported"))
1549                         ret = BLUETOOTH_ERROR_NOT_SUPPORT;
1550 /*failed because of either Insufficient Authorization or Write Not Permitted */
1551                 else if (g_strrstr(error->message, "Write not permitted") ||
1552                                 g_strrstr(error->message, "Operation Not Authorized"))
1553                         ret = BLUETOOTH_ERROR_PERMISSION_DEINED;
1554 /* failed because of either Insufficient Authentication,
1555         Insufficient Encryption Key Size, or Insufficient Encryption. */
1556                 else if (g_strrstr(error->message, "Not paired"))
1557                         ret = BLUETOOTH_ERROR_NOT_PAIRED;
1558                 else
1559                         ret = BLUETOOTH_ERROR_INTERNAL;
1560
1561                 g_clear_error(&error);
1562         }
1563
1564         return ret;
1565 }
1566
1567 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle)
1568 {
1569
1570         GDBusConnection *conn;
1571         GError *error = NULL;
1572         int ret = BLUETOOTH_ERROR_NONE;
1573         BT_CHECK_PARAMETER(char_handle, return);
1574
1575         BT_CHECK_ENABLED(return);
1576
1577         BT_INFO("Disable CCCD : %s", char_handle);
1578
1579         conn = _bt_gdbus_get_system_gconn();
1580         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1581
1582         g_dbus_connection_call_sync(conn,
1583                         BT_BLUEZ_NAME,
1584                         char_handle,
1585                         GATT_CHAR_INTERFACE,
1586                         "StopNotify",
1587                         NULL,
1588                         NULL,
1589                         G_DBUS_CALL_FLAGS_NONE,
1590                         GATT_DEFAULT_TIMEOUT, NULL, &error);
1591
1592         if (error) {
1593                 BT_ERR("Watch Failed: %s", error->message);
1594                 g_clear_error(&error);
1595                 ret =  BLUETOOTH_ERROR_INTERNAL;
1596         }
1597
1598         return ret;
1599 }