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