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