Merge "Modify the PBAP connection event implementation" 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
178                 } else if(!g_strcmp0(key, "Primary")) {
179                         service->primary = g_variant_get_boolean(value);
180
181                 } else if (!g_strcmp0(key, "Includes")) {
182                         g_variant_get(value, "ao", &char_iter);
183                         gp_array = g_ptr_array_new();
184                         while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
185                                 g_ptr_array_add(gp_array, (gpointer)char_handle);
186                         }
187                         if (gp_array->len != 0) {
188                                 service->include_handles.count = gp_array->len;
189                                 service->include_handles.handle =
190                                                 __get_string_array_from_gptr_array(gp_array);
191                         }
192                         g_ptr_array_free(gp_array, TRUE);
193                 } else if (!g_strcmp0(key, "Characteristics")) {
194                         g_variant_get(value, "ao", &char_iter);
195                         gp_array = g_ptr_array_new();
196                         while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
197                                 g_ptr_array_add(gp_array, (gpointer)char_handle);
198                         }
199                         if (gp_array->len != 0) {
200                                 service->char_handle.count = gp_array->len;
201                                 service->char_handle.handle =
202                                                 __get_string_array_from_gptr_array(gp_array);
203                         }
204                         g_ptr_array_free(gp_array, TRUE);
205                 }
206         }
207
208         service->handle = g_strdup(service_handle);
209
210         g_variant_iter_free(property_iter);
211         g_variant_unref(result);
212         g_object_unref(properties_proxy);
213
214         return BLUETOOTH_ERROR_NONE;
215 }
216
217 BT_EXPORT_API int bluetooth_gatt_get_primary_services(
218                 const bluetooth_device_address_t *address,
219                 bt_gatt_handle_info_t *prim_svc)
220 {
221         GVariant *result = NULL;
222         GVariantIter *iter;
223         GVariantIter *svc_iter;
224         GVariantIter *interface_iter;
225         char *object_path = NULL;
226         char *interface_str = NULL;
227         const gchar *key = NULL;
228         GVariant *value = NULL;
229         GPtrArray *gp_array  = NULL;
230         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
231         char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
232         int ret = BLUETOOTH_ERROR_INTERNAL;
233
234         BT_INFO("+");
235         BT_CHECK_PARAMETER(address, return);
236         BT_CHECK_PARAMETER(prim_svc, return);
237         BT_CHECK_ENABLED_ANY(return);
238
239         result = _bt_get_managed_objects();
240         if (result == NULL)
241                 return ret;
242
243         _bt_convert_addr_type_to_string(device_address,
244                         (unsigned char *)address->addr);
245
246         gp_array = g_ptr_array_new();
247         g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
248
249         while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
250                         &interface_iter)) {
251                 if (object_path == NULL)
252                         continue;
253
254                 _bt_convert_device_path_to_address(object_path, temp_address);
255
256                 if (g_strcmp0(temp_address, device_address) != 0)
257                         continue;
258
259                 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
260                                 &interface_str, &svc_iter)) {
261                         if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
262                                 continue;
263
264                         BT_DBG("Object Path: %s", object_path);
265                         while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
266                                 if (g_strcmp0(key, "Primary") == 0) {
267                                         if (g_variant_get_boolean(value))
268                                                 g_ptr_array_add(gp_array, (gpointer)object_path);
269                                 }
270                         }
271                 }
272         }
273
274         if (gp_array->len == 0) {
275                 BT_ERR("gp_array is NULL");
276                 ret = BLUETOOTH_ERROR_NOT_FOUND;
277         } else {
278                 ret = BLUETOOTH_ERROR_NONE;
279                 prim_svc->count = gp_array->len;
280                 prim_svc->handle = __get_string_array_from_gptr_array(gp_array);
281         }
282
283         g_ptr_array_free(gp_array, TRUE);
284         g_variant_iter_free(iter);
285         g_variant_unref(result);
286         BT_DBG("-");
287         return ret;
288 }
289
290 BT_EXPORT_API int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address,
291                         const char *service_uuid,
292                         bt_gatt_service_property_t *service)
293 {
294         GVariant *result = NULL;
295         GVariantIter *iter;
296         GVariantIter *svc_iter;
297         GVariantIter *interface_iter;
298         char *object_path = NULL;
299         char *interface_str = NULL;
300         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
301         char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
302         int ret = BLUETOOTH_ERROR_INTERNAL;
303
304         BT_CHECK_PARAMETER(address, return);
305         BT_CHECK_PARAMETER(service_uuid, return);
306         BT_CHECK_PARAMETER(service, return);
307         BT_CHECK_ENABLED_ANY(return);
308
309         result = _bt_get_managed_objects();
310         if (result == NULL)
311                 return ret;
312
313         _bt_convert_addr_type_to_string(device_address,
314                                 (unsigned char *)address->addr);
315
316         g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
317
318         while (g_variant_iter_loop(iter, "{oa{sa{sv}}}", &object_path,
319                         &interface_iter)) {
320                 if (object_path == NULL)
321                         continue;
322
323                 _bt_convert_device_path_to_address(object_path,
324                                 temp_address);
325
326                 if (g_strcmp0(temp_address, device_address) != 0)
327                         continue;
328
329                 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
330                                 &interface_str, &svc_iter)) {
331                         if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
332                                 continue;
333
334                         BT_DBG("Object Path: %s", object_path);
335                         ret = bluetooth_gatt_get_service_property(object_path,
336                                         service);
337
338                         if (ret != BLUETOOTH_ERROR_NONE) {
339                                 BT_ERR("Get service property failed(0x%08x)", ret);
340                         } else {
341                                 if (service->primary == TRUE &&
342                                                 g_strstr_len(service->uuid, -1,
343                                                                 service_uuid)) {
344                                         ret = BLUETOOTH_ERROR_NONE;
345                                         goto done;
346                                 }
347                         }
348                         bluetooth_gatt_free_service_property(service);
349                 }
350         }
351
352 done:
353         g_variant_iter_free(iter);
354         g_variant_unref(result);
355
356         return ret;
357 }
358
359 static void __bluetooth_internal_get_char_cb(GDBusProxy *proxy,
360                 GAsyncResult *res, gpointer user_data)
361 {
362         GVariant *value;
363         GVariant *char_value;
364         GVariantIter *char_iter;
365         GPtrArray *gp_array = NULL;
366         bt_gatt_discovered_char_t svc_char = { 0, };
367         char *char_handle;
368         GError *error = NULL;
369         bt_user_info_t *user_info;
370
371         BT_DBG("+");
372
373         user_info = _bt_get_user_data(BT_COMMON);
374         svc_char.service_handle = user_data;
375
376         value = g_dbus_proxy_call_finish(proxy, res, &error);
377
378         if (value == NULL) {
379                 if (error != NULL) {
380                         BT_ERR("Get service characteristics failed\n errCode[%x],"
381                                         "message[%s]\n", error->code, error->message);
382                         g_clear_error(&error);
383                 } else {
384                         BT_ERR("Get service characteristics failed\n");
385                 }
386                 if (user_info) {
387                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
388                                 BLUETOOTH_ERROR_INTERNAL, NULL,
389                                 user_info->cb, user_info->user_data);
390                 }
391                 g_free(svc_char.service_handle);
392                 g_object_unref(proxy);
393                 return;
394         }
395
396         g_variant_get(value, "(v)", &char_value);
397         g_variant_get(char_value, "ao", &char_iter);
398
399         gp_array = g_ptr_array_new();
400         while(g_variant_iter_loop(char_iter, "&o",  &char_handle));
401                 g_ptr_array_add(gp_array, (gpointer)char_handle);
402
403         if (gp_array->len != 0) {
404                 svc_char.handle_info.count = gp_array->len;
405                 svc_char.handle_info.handle =
406                         __get_string_array_from_gptr_array(gp_array);
407         }
408         g_ptr_array_free(gp_array, TRUE);
409
410         if (user_info) {
411                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
412                         BLUETOOTH_ERROR_NONE, &svc_char,
413                         user_info->cb, user_info->user_data);
414         }
415
416         g_strfreev(svc_char.handle_info.handle);
417         g_free(svc_char.service_handle);
418         g_variant_iter_free(char_iter);
419         g_object_unref(proxy);
420 }
421
422 BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(
423                         const char *service_handle)
424 {
425         GDBusProxy *properties_proxy = NULL;
426         GDBusConnection *g_conn;
427         GError *error = NULL;
428         char *handle;
429
430         BT_DBG("+");
431
432         BT_CHECK_PARAMETER(service_handle, return);
433         BT_CHECK_ENABLED_ANY(return);
434
435         g_conn = _bt_gdbus_get_system_gconn();
436         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
437
438         properties_proxy = g_dbus_proxy_new_sync(g_conn,
439                         G_DBUS_PROXY_FLAGS_NONE, NULL,
440                         BT_BLUEZ_NAME,
441                         service_handle,
442                         BT_PROPERTIES_INTERFACE,
443                         NULL, &error);
444
445         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
446
447         handle = g_strdup(service_handle);
448         g_dbus_proxy_call(properties_proxy,
449                         "Get",
450                         g_variant_new("(ss)",
451                                 GATT_SERV_INTERFACE, "Characteristics"),
452                         G_DBUS_CALL_FLAGS_NONE,
453                         -1,
454                         NULL,
455                         (GAsyncReadyCallback)__bluetooth_internal_get_char_cb,
456                         (gpointer)handle);
457
458         BT_DBG("-");
459         return BLUETOOTH_ERROR_NONE;
460 }
461
462
463 static int __get_permission_flag(char *permission)
464 {
465         int ret = 0;
466
467         retv_if(permission == NULL, ret);
468
469         BT_DBG("permission = %s",permission);
470
471         if (!g_strcmp0(permission,"broadcast")) {
472                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
473         } else if (!g_strcmp0(permission,"read")) {
474                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
475         } else if (!g_strcmp0(permission,"write-without-response")) {
476                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
477         } else if (!g_strcmp0(permission,"write")) {
478                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
479         } else if (!g_strcmp0(permission,"notify")) {
480                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
481         } else if (!g_strcmp0(permission,"indicate")) {
482                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
483         } else if (!g_strcmp0(permission,"authenticated-signed-writes")) {
484                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
485         } else if (!g_strcmp0(permission,"reliable-write")) {
486                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS;
487         } else if (!g_strcmp0(permission,"writable-auxiliaries")) {
488                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS;
489         }
490
491         return ret;
492 }
493
494 BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
495                 const char *char_handle, bt_gatt_char_property_t *characteristic)
496 {
497         GDBusProxy *properties_proxy = NULL;
498         GError *error = NULL;
499         GVariant *value = NULL;
500         GVariant *result = NULL;
501         GByteArray *gb_array = NULL;
502         GPtrArray *gp_array  = NULL ;
503         GDBusConnection *g_conn;
504         guint8 char_value;
505         const gchar *key;
506         gchar* permission;
507         char *char_desc_handle = NULL;
508         gsize len;
509         GVariantIter *property_iter;
510         GVariantIter *char_value_iter;
511         GVariantIter *char_perm_iter;
512         GVariantIter *char_desc_iter;
513
514         BT_DBG("+");
515         BT_CHECK_PARAMETER(char_handle, return);
516         BT_CHECK_PARAMETER(characteristic, return);
517
518         BT_CHECK_ENABLED_ANY(return);
519
520         g_conn = _bt_gdbus_get_system_gconn();
521         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
522
523         properties_proxy = g_dbus_proxy_new_sync(g_conn,
524                         G_DBUS_PROXY_FLAGS_NONE, NULL,
525                         BT_BLUEZ_NAME,
526                         char_handle,
527                         BT_PROPERTIES_INTERFACE,
528                         NULL, &error);
529
530         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
531
532         result = g_dbus_proxy_call_sync(properties_proxy,
533                                 "GetAll",
534                                         g_variant_new("(s)", GATT_CHAR_INTERFACE),
535                                 G_DBUS_CALL_FLAGS_NONE,
536                                 -1,
537                                 NULL,
538                                 &error);
539
540         if (!result) {
541                 if (error != NULL) {
542                         BT_ERR("Fail to get properties (Error: %s)", error->message);
543                         g_clear_error(&error);
544                 } else
545                         BT_ERR("Fail to get properties");
546                 g_object_unref(properties_proxy);
547                 return BLUETOOTH_ERROR_INTERNAL;
548         }
549
550         g_variant_get(result, "(a{sv})", &property_iter);
551
552         memset(characteristic, 0, sizeof(bt_gatt_char_property_t));
553         characteristic->handle = g_strdup(char_handle);
554
555         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
556                 BT_DBG("property");
557                 if (!g_strcmp0(key,"UUID")) {
558                         characteristic->uuid = g_variant_dup_string(value,&len);
559                         BT_DBG("UUID of the char = %s",characteristic->uuid);
560                 } else if(!g_strcmp0(key, "Value")) {
561                         gb_array = g_byte_array_new();
562                         g_variant_get(value, "ay", &char_value_iter);
563                         while(g_variant_iter_loop(char_value_iter, "y",  &char_value)) {
564                                 BT_DBG("value of char = %d",char_value);
565                                 g_byte_array_append(gb_array, &char_value, 1);
566                         }
567                         g_variant_iter_free(char_value_iter);
568
569                         if (gb_array->len != 0) {
570                                 characteristic->val = g_malloc0(gb_array->len *
571                                                                 sizeof(unsigned char));
572                                 memcpy(characteristic->val, gb_array->data, gb_array->len);
573                         }
574                         characteristic->val_len = gb_array->len;
575                         g_byte_array_free(gb_array, TRUE);
576                 } else if(!g_strcmp0(key, "Flags")) {
577                         g_variant_get(value, "as", &char_perm_iter);
578                         characteristic->permission = 0x00;
579                         while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
580                                 BT_DBG("permission = %s",permission);
581                                 characteristic->permission |= __get_permission_flag(permission);
582                                 BT_DBG("permission check = %d",characteristic->permission);
583                         }
584                         g_variant_iter_free(char_perm_iter);
585                 } else if (!g_strcmp0(key, "Descriptors")) {
586                         g_variant_get(value, "ao", &char_desc_iter);
587                         gp_array = g_ptr_array_new();
588                         while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
589                                 g_ptr_array_add(gp_array, (gpointer)char_desc_handle);
590                         }
591                         g_variant_iter_free(char_desc_iter);
592                         if (gp_array->len != 0) {
593                                 characteristic->char_desc_handle.count = gp_array->len;
594                                 characteristic->char_desc_handle.handle =
595                                                 __get_string_array_from_gptr_array(gp_array);
596                         }
597                         g_ptr_array_free(gp_array, TRUE);
598                 }
599         }
600
601         g_variant_iter_free(property_iter);
602         g_variant_unref(result);
603         g_object_unref(properties_proxy);
604
605         BT_DBG("-");
606         return BLUETOOTH_ERROR_NONE;
607 }
608
609 void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy,
610                         GAsyncResult *res, gpointer user_data)
611 {
612         GVariant *value;
613         GVariantIter *char_iter;
614         int i, len;
615         char *char_handle;
616         GError *error = NULL;
617         bt_user_info_t *user_info;
618         int ret = BLUETOOTH_ERROR_INTERNAL;
619         bt_gatt_char_property_t characteristic;
620
621         user_info = _bt_get_user_data(BT_COMMON);
622
623         value = g_dbus_proxy_call_finish(proxy, res, &error);
624
625         if (value == NULL) {
626                 if (error != NULL) {
627                         BT_ERR("Get service characteristics failed\n errCode[%x],"
628                                         "message[%s]\n", error->code, error->message);
629                         g_clear_error(&error);
630                 } else {
631                         BT_ERR("Get service characteristics failed\n");
632                 }
633                 if (user_info) {
634                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
635                                 BLUETOOTH_ERROR_INTERNAL, NULL,
636                                 user_info->cb, user_info->user_data);
637                 }
638                 g_object_unref(proxy);
639                 g_free(user_data);
640                 return;
641         }
642
643         g_variant_get(value, "(ao)", &char_iter);
644
645         len = g_variant_get_size((GVariant *)char_iter);
646
647         for (i = 0; i < len; i++) {
648                 g_variant_iter_loop(char_iter, "o",  &char_handle);
649                 if (!char_handle)
650                         continue;
651                 ret = bluetooth_gatt_get_characteristics_property(char_handle,
652                                 &characteristic);
653
654                 if (ret != BLUETOOTH_ERROR_NONE) {
655                         BT_ERR("Get characteristic property failed(0x%08x)", ret);
656                 } else {
657                         if (g_strstr_len(characteristic.uuid, -1, user_data)) {
658                                 ret = BLUETOOTH_ERROR_NONE;
659                                 break;
660                         }
661                 }
662                 bluetooth_gatt_free_char_property(&characteristic);
663         }
664
665         if (user_info) {
666                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret,
667                                 &characteristic, user_info->cb, user_info->user_data);
668         }
669
670         bluetooth_gatt_free_char_property(&characteristic);
671         g_variant_iter_free(char_iter);
672         g_free(user_data);
673 }
674
675 BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
676                                                 const char *char_uuid)
677 {
678         GDBusProxy *properties_proxy = NULL;
679         GDBusConnection *g_conn;
680         GError *error = NULL;
681         char *uuid;
682
683         BT_CHECK_PARAMETER(service_handle, return);
684         BT_CHECK_PARAMETER(char_uuid, return);
685         BT_CHECK_ENABLED_ANY(return);
686
687         g_conn = _bt_gdbus_get_system_gconn();
688         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
689
690         properties_proxy = g_dbus_proxy_new_sync(g_conn,
691                         G_DBUS_PROXY_FLAGS_NONE, NULL,
692                         BT_BLUEZ_NAME,
693                         service_handle,
694                         BT_PROPERTIES_INTERFACE,
695                         NULL, &error);
696
697         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
698
699         uuid = g_strdup(char_uuid);
700         g_dbus_proxy_call(properties_proxy,
701                         "Get",
702                         g_variant_new("(ss)",
703                                 GATT_SERV_INTERFACE, "Characteristics"),
704                         G_DBUS_CALL_FLAGS_NONE,
705                         -1,
706                         NULL,
707                         (GAsyncReadyCallback)bluetooth_gatt_get_char_from_uuid_cb,
708                         (gpointer)uuid);
709
710         return BLUETOOTH_ERROR_NONE;
711 }
712
713 BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
714                 const char *descriptor_handle, bt_gatt_char_descriptor_property_t *descriptor)
715 {
716         GDBusProxy *properties_proxy = NULL;
717         GError *error = NULL;
718         GDBusConnection *g_conn;
719         GVariant *result = NULL;
720         GVariantIter *property_iter;
721         const gchar *key;
722         guint8 char_value;
723         gsize len;
724         GVariant *value = NULL;
725         GByteArray *gb_array = NULL;
726         GVariantIter *desc_value_iter;
727
728         BT_DBG("+");
729         BT_CHECK_PARAMETER(descriptor_handle, return);
730         BT_CHECK_PARAMETER(descriptor, return);
731
732         BT_CHECK_ENABLED_ANY(return);
733
734         g_conn = _bt_gdbus_get_system_gconn();
735         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
736
737         properties_proxy = g_dbus_proxy_new_sync(g_conn,
738                         G_DBUS_PROXY_FLAGS_NONE, NULL,
739                         BT_BLUEZ_NAME,
740                         descriptor_handle,
741                         BT_PROPERTIES_INTERFACE,
742                         NULL, &error);
743
744         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
745
746         result = g_dbus_proxy_call_sync(properties_proxy,
747                                 "GetAll",
748                                         g_variant_new("(s)", GATT_DESC_INTERFACE),
749                                 G_DBUS_CALL_FLAGS_NONE,
750                                 -1,
751                                 NULL,
752                                 &error);
753
754         if (!result) {
755                 if (error != NULL) {
756                         BT_ERR("Fail to get properties (Error: %s)", error->message);
757                         g_clear_error(&error);
758                 } else
759                         BT_ERR("Fail to get properties");
760                 g_object_unref(properties_proxy);
761                 return BLUETOOTH_ERROR_INTERNAL;
762         }
763
764         g_variant_get(result, "(a{sv})", &property_iter);
765
766         memset(descriptor, 0, sizeof(bt_gatt_char_descriptor_property_t));
767         descriptor->handle = g_strdup(descriptor_handle);
768
769         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
770                 BT_DBG("property");
771                 if (!g_strcmp0(key,"UUID")) {
772                         descriptor->uuid = g_variant_dup_string(value,&len);
773                         BT_DBG("UUID of the char_desc = %s",descriptor->uuid);
774                 } else if(!g_strcmp0(key, "Value")) {
775                         gb_array = g_byte_array_new();
776                         g_variant_get(value, "ay", &desc_value_iter);
777                         while(g_variant_iter_loop(desc_value_iter, "y",  &char_value)) {
778                                 BT_DBG("value of descriptor = %d",char_value);
779                                 g_byte_array_append(gb_array, &char_value, 1);
780                         }
781                         g_variant_iter_free(desc_value_iter);
782                         if (gb_array->len != 0) {
783                                 descriptor->val = g_malloc0(gb_array->len *
784                                                                 sizeof(unsigned char));
785                                 memcpy(descriptor->val, gb_array->data, gb_array->len);
786                         }
787                         descriptor->val_len = gb_array->len;
788                         g_byte_array_free(gb_array, TRUE);
789                 }
790         }
791
792         g_variant_iter_free(property_iter);
793         g_variant_unref(result);
794         g_object_unref(properties_proxy);
795
796         BT_DBG("-");
797         return BLUETOOTH_ERROR_NONE;
798 }
799
800 static void __bluetooth_internal_read_cb(GObject *source_object,
801                         GAsyncResult *res,
802                         gpointer user_data)
803 {
804         GError *error = NULL;
805         bt_user_info_t *user_info;
806         bt_gatt_char_value_t char_value =  { 0, };
807         GDBusConnection *system_gconn = NULL;
808         GVariant *value;
809         GByteArray *gp_byte_array = NULL;
810         GVariantIter *iter;
811         guint8 g_byte;
812
813         BT_DBG("+");
814         user_info = _bt_get_user_data(BT_COMMON);
815
816         system_gconn = _bt_gdbus_get_system_gconn();
817         value = g_dbus_connection_call_finish(system_gconn, res, &error);
818
819         if (error) {
820                 BT_ERR("Error : %s \n", error->message);
821                 g_clear_error(&error);
822                 if (user_info) {
823                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
824                                 BLUETOOTH_ERROR_INTERNAL, NULL,
825                                 user_info->cb, user_info->user_data);
826                 }
827                 g_free(user_data);
828                 return;
829         }
830
831         char_value.char_handle = user_data;
832         gp_byte_array = g_byte_array_new();
833         g_variant_get(value, "(ay)", &iter);
834
835         while (g_variant_iter_loop(iter, "y", &g_byte)) {
836                 g_byte_array_append(gp_byte_array, &g_byte, 1);
837         }
838
839         if (gp_byte_array->len != 0) {
840                 char_value.val_len = gp_byte_array->len;
841                 char_value.char_value = gp_byte_array->data;
842         }
843
844         if (user_info) {
845                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
846                                 BLUETOOTH_ERROR_NONE, &char_value,
847                                 user_info->cb, user_info->user_data);
848         }
849
850         g_free(char_value.char_handle);
851         g_byte_array_free(gp_byte_array, TRUE);
852         g_variant_unref(value);
853         g_variant_iter_free(iter);
854
855         BT_DBG("-");
856 }
857
858 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *characteristic)
859 {
860         GDBusConnection *conn;
861         char *handle;
862
863         BT_CHECK_PARAMETER(characteristic, return);
864         BT_CHECK_ENABLED_ANY(return);
865
866         conn = _bt_gdbus_get_system_gconn();
867         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
868
869         handle = g_strdup(characteristic);
870
871         g_dbus_connection_call(conn,
872                         BT_BLUEZ_NAME,
873                         characteristic,
874                         GATT_CHAR_INTERFACE,
875                         "ReadValue",
876                         NULL,
877                         G_VARIANT_TYPE("(ay)"),
878                         G_DBUS_CALL_FLAGS_NONE,
879                         -1,
880                         NULL,
881                         (GAsyncReadyCallback)__bluetooth_internal_read_cb,
882                         (gpointer)handle);
883
884         return BLUETOOTH_ERROR_NONE;
885 }
886
887 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
888                 const char *char_handle, const guint8 *value, int length)
889 {
890         GVariant *val;
891         GVariantBuilder *builder;
892         GError *error = NULL;
893         GDBusConnection *conn;
894         int i = 0;
895
896         BT_DBG("+");
897         BT_CHECK_PARAMETER(char_handle, return);
898         BT_CHECK_PARAMETER(value, return);
899         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
900         BT_CHECK_ENABLED_ANY(return);
901
902         conn = _bt_gdbus_get_system_gconn();
903         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
904
905         builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
906
907         for (i = 0; i < length; i++) {
908                 g_variant_builder_add(builder, "y", value[i]);
909         }
910
911         val = g_variant_new("(ay)", builder);
912
913         g_dbus_connection_call_sync(conn,
914                         BT_BLUEZ_NAME,
915                         char_handle,
916                         GATT_CHAR_INTERFACE,
917                         "WriteValue",
918                         val,
919                         NULL,
920                         G_DBUS_CALL_FLAGS_NONE,
921                         -1, NULL, &error);
922
923         if (error) {
924                 BT_ERR("Set value Failed: %s", error->message);
925                 g_clear_error(&error);
926                 g_variant_builder_unref(builder);
927                 return BLUETOOTH_ERROR_INTERNAL;
928         }
929
930         g_variant_builder_unref(builder);
931
932         BT_DBG("-");
933         return BLUETOOTH_ERROR_NONE;
934 }
935
936 static void __bluetooth_internal_write_cb(GObject *source_object,
937                         GAsyncResult *res,
938                         gpointer user_data)
939 {
940         BT_DBG("+");
941         GError *error = NULL;
942         bt_user_info_t *user_info;
943         GDBusConnection *system_gconn = NULL;
944         GVariant *value;
945         int result = BLUETOOTH_ERROR_NONE;
946
947         user_info = _bt_get_user_data(BT_COMMON);
948
949         system_gconn = _bt_gdbus_get_system_gconn();
950         value = g_dbus_connection_call_finish(system_gconn, res, &error);
951
952         if (error) {
953                 BT_ERR("Error : %s \n", error->message);
954                 g_clear_error(&error);
955                 result = BLUETOOTH_ERROR_INTERNAL;
956         }
957         if (user_info) {
958                 BT_DBG("result = %d", result);
959                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
960                                 result, NULL,
961                                 user_info->cb, user_info->user_data);
962         }
963
964         if (value)
965                 g_variant_unref(value);
966         BT_DBG("-");
967         return;
968 }
969
970 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
971                 const char *char_handle, const guint8 *value, int length, guint8 write_type)
972 {
973         GVariant *val;
974         GVariantBuilder *builder;
975         GDBusConnection *conn;
976         int i = 0;
977         int ret = BLUETOOTH_ERROR_NONE;
978
979         BT_CHECK_PARAMETER(char_handle, return);
980         BT_CHECK_PARAMETER(value, return);
981         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
982         BT_CHECK_ENABLED_ANY(return);
983
984         conn = _bt_gdbus_get_system_gconn();
985         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
986
987         builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
988
989         for (i = 0; i < length; i++) {
990                 g_variant_builder_add(builder, "y", value[i]);
991         }
992
993         val = g_variant_new("ay", builder);
994         g_dbus_connection_call(conn,
995                         BT_BLUEZ_NAME,
996                         char_handle,
997                         GATT_CHAR_INTERFACE,
998                         "WriteValuebyType",
999                         g_variant_new("(y@ay)", write_type, val),
1000                         NULL,
1001                         G_DBUS_CALL_FLAGS_NONE,
1002                         -1, NULL,
1003                         (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1004                         NULL);
1005
1006         g_variant_builder_unref(builder);
1007         return ret;
1008 }
1009
1010 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
1011                         const char *char_handle, const guint8 *value, int length)
1012 {
1013         GVariant *val;
1014         GDBusConnection *conn;
1015         GVariantBuilder *builder;
1016         int i;
1017
1018         BT_DBG("+");
1019         BT_CHECK_PARAMETER(char_handle, return);
1020         BT_CHECK_PARAMETER(value, return);
1021         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1022         BT_CHECK_ENABLED_ANY(return);
1023
1024         conn = _bt_gdbus_get_system_gconn();
1025         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1026
1027         builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1028
1029         for (i = 0; i < length; i++) {
1030                 g_variant_builder_add(builder, "y", value[i]);
1031                 BT_DBG("value [] = %d", value[i]);
1032         }
1033
1034         val = g_variant_new("(ay)", builder);
1035
1036         g_dbus_connection_call(conn,
1037                                 BT_BLUEZ_NAME,
1038                                 char_handle,
1039                                 GATT_CHAR_INTERFACE,
1040                                 "WriteValue",
1041                                 val,
1042                                 NULL,
1043                                 G_DBUS_CALL_FLAGS_NONE,
1044                                 -1, NULL,
1045                                 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1046                                 NULL);
1047
1048         g_variant_builder_unref(builder);
1049
1050         BT_DBG("-");
1051         return BLUETOOTH_ERROR_NONE;
1052 }
1053
1054 static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
1055                         bt_gatt_char_property_t *characteristic)
1056 {
1057         BT_DBG("+");
1058         GDBusProxy *properties_proxy = NULL;
1059         GError *error = NULL;
1060         GVariant *value = NULL;
1061         GVariant *result = NULL;
1062         GDBusConnection *g_conn;
1063         int i, ret = BLUETOOTH_ERROR_NONE;
1064         const char *uuid = NULL;
1065         gsize len = 0;
1066         GVariantIter *desc_value_iter, *property_iter;
1067         const gchar *key;
1068         char_descriptor_type_t desc_type = TYPE_NONE;
1069
1070         g_conn = _bt_gdbus_get_system_gconn();
1071         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1072
1073         properties_proxy = g_dbus_proxy_new_sync(g_conn,
1074                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1075                         BT_BLUEZ_NAME,
1076                         char_handle,
1077                         BT_PROPERTIES_INTERFACE,
1078                         NULL, &error);
1079
1080         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1081
1082         result = g_dbus_proxy_call_sync(properties_proxy,
1083                                 "GetAll",
1084                                 g_variant_new("(s)", GATT_DESC_INTERFACE),
1085                                 G_DBUS_CALL_FLAGS_NONE,
1086                                 -1,
1087                                 NULL,
1088                                 &error);
1089
1090         if (!result) {
1091                 if (error != NULL) {
1092                         BT_ERR("Fail to get properties (Error: %s)", error->message);
1093                         g_clear_error(&error);
1094                 } else
1095                         BT_ERR("Fail to get properties");
1096                 g_object_unref(properties_proxy);
1097                 return BLUETOOTH_ERROR_INTERNAL;
1098         }
1099         g_variant_get(result, "(a{sv})", &property_iter);
1100         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1101                 if (!g_strcmp0(key,"UUID")) {
1102                         uuid = g_variant_get_string(value, &len);
1103                         if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
1104                                 BT_DBG("GATT_USER_DESC_UUID");
1105                                 desc_type = USER_DESC;
1106                         } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) {
1107                                 BT_DBG("GATT_CHAR_FORMAT");
1108                                 desc_type = CHAR_FORMAT;
1109                         } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) {
1110                                 BT_DBG("GATT_CHAR_CLIENT_CONF");
1111                                 desc_type = CLIENT_CONF;
1112                         } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) {
1113                                 BT_DBG("GATT_CHAR_SERVER_CONF");
1114                                 desc_type = SERVER_CONF;
1115                         } else {
1116                                 BT_DBG("descriptor uuid = %s", uuid);
1117                         }
1118                 } else if (!g_strcmp0(key, "Value")) {
1119                         switch(desc_type) {
1120                                 case CHAR_FORMAT :
1121                                         BT_DBG("Format descriptor");
1122                                         g_variant_get(value, "(yyqyq)",
1123                                                         &(characteristic->format.format),
1124                                                         &(characteristic->format.exponent),
1125                                                         &(characteristic->format.unit),
1126                                                         &(characteristic->format.name_space),
1127                                                         &(characteristic->format.description));
1128                                         break;
1129                                 case USER_DESC:
1130                                         BT_DBG("User descriptor");
1131                                         g_variant_get(value, "ay", &desc_value_iter);
1132                                         len = g_variant_get_size((GVariant *)desc_value_iter);
1133
1134                                         if (len > 0) {
1135                                                 characteristic->description = (char *)g_malloc0(len + 1);
1136                                                 if (!characteristic->description) {
1137                                                         ret = BLUETOOTH_ERROR_OUT_OF_MEMORY;
1138                                                         goto done;
1139                                                 }
1140                                         }
1141                                         for (i = 0; i < len; i++) {
1142                                                 g_variant_iter_loop(desc_value_iter, "y",
1143                                                         &characteristic->description[i]);
1144                                                 BT_DBG("description = %s", characteristic->description);
1145                                         }
1146                                         g_variant_iter_free(desc_value_iter);
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 }