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