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