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