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