gatt client adaptation feature changes bt-api bt-service OAL
[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-event-handler.h"
27 #include "bt-gatt-client.h"
28 #include "bt-internal-types.h"
29 #include "bt-request-sender.h"
30
31 #ifdef TIZEN_GATT_CLIENT
32 #include "bluetooth-gatt-client-api.h"
33 #include <arpa/inet.h>
34 #endif
35
36 #define GATT_DEFAULT_TIMEOUT  (6 * 1000) // Dependent on supervision timeout 6 sec
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 static GSList *service_monitor_list = NULL;
47
48 BT_EXPORT_API int bluetooth_gatt_free_service_property(bt_gatt_service_property_t *svc_pty)
49 {
50         BT_DBG("+");
51
52         BT_CHECK_PARAMETER(svc_pty, return);
53
54 #ifdef TIZEN_GATT_CLIENT
55         g_free(svc_pty->uuid);
56 #else
57         g_free(svc_pty->uuid);
58         g_free(svc_pty->handle);
59         g_strfreev(svc_pty->include_handles.handle);
60         g_strfreev(svc_pty->char_handle.handle);
61 #endif
62
63         memset(svc_pty, 0, sizeof(bt_gatt_service_property_t));
64
65         BT_DBG("-");
66         return BLUETOOTH_ERROR_NONE;
67 }
68
69 BT_EXPORT_API int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty)
70 {
71         BT_DBG("+");
72
73         BT_CHECK_PARAMETER(char_pty, return);
74
75         g_free(char_pty->uuid);
76         g_free(char_pty->name);
77         g_free(char_pty->description);
78         g_free(char_pty->val);
79 #ifndef TIZEN_GATT_CLIENT
80         g_free(char_pty->handle);
81         g_strfreev(char_pty->char_desc_handle.handle);
82 #endif
83
84         memset(char_pty, 0, sizeof(bt_gatt_char_property_t));
85
86         BT_DBG("-");
87         return BLUETOOTH_ERROR_NONE;
88 }
89
90 BT_EXPORT_API int bluetooth_gatt_free_desc_property(bt_gatt_char_descriptor_property_t *desc_pty)
91 {
92         BT_DBG("+");
93
94         BT_CHECK_PARAMETER(desc_pty, return);
95
96         g_free(desc_pty->uuid);
97         g_free(desc_pty->val);
98 #ifndef TIZEN_GATT_CLIENT
99         g_free(desc_pty->handle);
100 #endif
101
102         memset(desc_pty, 0, sizeof(bt_gatt_char_descriptor_property_t));
103
104         BT_DBG("-");
105         return BLUETOOTH_ERROR_NONE;
106 }
107
108 static char **__get_string_array_from_gptr_array(GPtrArray *gp)
109 {
110         gchar *gp_path = NULL;
111         char **path = NULL;
112         int i;
113
114         if (gp->len == 0)
115                 return NULL;
116
117         path = g_malloc0((gp->len + 1) * sizeof(char *));
118
119         for (i = 0; i < gp->len; i++) {
120                 gp_path = g_ptr_array_index(gp, i);
121                 path[i] = g_strdup(gp_path);
122         //      BT_DBG("path[%d] : [%s]", i, path[i]);
123         }
124
125         return path;
126 }
127
128 gboolean _bluetooth_gatt_check_service_change_watcher_address(
129                 const bluetooth_device_address_t *device_addr)
130 {
131         GSList *l;
132         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
133         char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
134
135         _bt_convert_addr_type_to_string(device_address,
136                         (unsigned char *)device_addr->addr);
137
138         for (l = service_monitor_list; l != NULL; l = l->next) {
139                 char device_address2[BT_ADDRESS_STRING_SIZE] = { 0 };
140                 char secure_address2[BT_ADDRESS_STRING_SIZE] = { 0 };
141                 bluetooth_device_address_t *addr = l->data;
142
143                 _bt_convert_addr_type_to_string(device_address2,
144                                 (unsigned char *)addr->addr);
145                 _bt_convert_addr_string_to_secure_string(secure_address,
146                                 device_address);
147                 _bt_convert_addr_string_to_secure_string(secure_address2,
148                                 device_address2);
149                 BT_INFO("service_monitor_list [%s] - Input [%s]",
150                                 secure_address2, secure_address);
151
152                 if (!memcmp(device_addr, addr,
153                             sizeof(bluetooth_device_address_t)))
154                         return TRUE;
155         }
156
157         return FALSE;
158 }
159
160 BT_EXPORT_API int bluetooth_gatt_set_service_change_watcher(
161                 const bluetooth_device_address_t *address, gboolean enable)
162 {
163         GSList *l;
164         bluetooth_device_address_t *addr = NULL;
165         char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
166
167         _bt_convert_addr_type_to_secure_string(secure_address, (unsigned char *)address->addr);
168         BT_INFO("Set watcher for %s with %d", secure_address, enable);
169
170         if (enable == TRUE) {
171                 if (_bluetooth_gatt_check_service_change_watcher_address(address)
172                                 == TRUE) {
173                         BT_INFO("The watcher is already set");
174                         return BLUETOOTH_ERROR_NONE;
175                 }
176
177                 if (service_monitor_list == NULL)
178                         _bt_register_manager_subscribe_signal(TRUE);
179
180                 addr = g_malloc0(sizeof(bluetooth_device_address_t));
181                 memcpy(addr, address, sizeof(bluetooth_device_address_t));
182
183                 service_monitor_list =
184                         g_slist_append(service_monitor_list, addr);
185         } else {
186                 for (l = service_monitor_list; l != NULL; l = l->next) {
187                         addr = l->data;
188
189                         if (!memcmp(address, addr,
190                                     sizeof(bluetooth_device_address_t))) {
191                                 service_monitor_list =
192                                         g_slist_remove(service_monitor_list, addr);
193                                 g_free(addr);
194                                 break;
195                         }
196                 }
197
198                 if (service_monitor_list == NULL)
199                         _bt_register_manager_subscribe_signal(FALSE);
200         }
201
202         return BLUETOOTH_ERROR_NONE;
203 }
204
205 BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle,
206                                                 bt_gatt_service_property_t *service)
207 {
208         GDBusProxy *properties_proxy = NULL;
209         GError *error = NULL;
210         GVariant *result = NULL;
211         GDBusConnection *g_conn;
212         gsize len;
213         char *char_handle = NULL;
214         GPtrArray *gp_array  = NULL ;
215         GVariantIter *property_iter, *char_iter = NULL;
216         const gchar *key;
217         GVariant *value;
218
219         BT_CHECK_PARAMETER(service_handle, return);
220         BT_CHECK_PARAMETER(service, return);
221         BT_CHECK_ENABLED(return);
222
223         g_conn = _bt_gdbus_get_system_gconn();
224         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
225
226         properties_proxy = g_dbus_proxy_new_sync(g_conn,
227                         G_DBUS_PROXY_FLAGS_NONE, NULL,
228                         BT_BLUEZ_NAME,
229                         service_handle,
230                         BT_PROPERTIES_INTERFACE,
231                         NULL, &error);
232
233         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
234
235         result = g_dbus_proxy_call_sync(properties_proxy,
236                                 "GetAll",
237                                 g_variant_new("(s)", GATT_SERV_INTERFACE),
238                                 G_DBUS_CALL_FLAGS_NONE,
239                                 -1,
240                                 NULL,
241                                 &error);
242
243         if (!result) {
244                 if (error != NULL) {
245                         BT_ERR("Fail to get properties (Error: %s)", error->message);
246                         g_clear_error(&error);
247                 } else
248                         BT_ERR("Fail to get properties");
249                 g_object_unref(properties_proxy);
250                 return BLUETOOTH_ERROR_INTERNAL;
251         }
252
253         g_variant_get(result, "(a{sv})", &property_iter);
254
255         memset(service, 0, sizeof(bt_gatt_service_property_t));
256
257         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
258                 if (!g_strcmp0(key, "UUID")) {
259                         char *name = NULL;
260                         service->uuid = g_variant_dup_string(value, &len);
261                         bluetooth_get_uuid_name(service->uuid, &name);
262                         BT_INFO("%s %s [%s]", service_handle + 37, service->uuid, name);
263                         g_free(name);
264                 } else if (!g_strcmp0(key, "Primary")) {
265                         service->primary = g_variant_get_boolean(value);
266
267                 } else if (!g_strcmp0(key, "Includes")) {
268                         g_variant_get(value, "ao", &char_iter);
269                         if (char_iter != NULL) {
270                                 gp_array = g_ptr_array_new();
271                                 while (g_variant_iter_loop(char_iter, "&o", &char_handle))
272                                         g_ptr_array_add(gp_array, (gpointer)char_handle);
273
274                                 if (gp_array->len != 0) {
275                                         service->include_handles.count = gp_array->len;
276                                         service->include_handles.handle =
277                                                         __get_string_array_from_gptr_array(gp_array);
278                                 }
279                                 g_ptr_array_free(gp_array, TRUE);
280                                 g_variant_iter_free(char_iter);
281                         }
282                 } else if (!g_strcmp0(key, "Characteristics")) {
283                         g_variant_get(value, "ao", &char_iter);
284                         if (char_iter != NULL) {
285                                 gp_array = g_ptr_array_new();
286                                 while (g_variant_iter_loop(char_iter, "&o", &char_handle))
287                                         g_ptr_array_add(gp_array, (gpointer)char_handle);
288
289                                 if (gp_array->len != 0) {
290                                         service->char_handle.count = gp_array->len;
291                                         service->char_handle.handle =
292                                                         __get_string_array_from_gptr_array(gp_array);
293                                 }
294                                 g_ptr_array_free(gp_array, TRUE);
295                                 g_variant_iter_free(char_iter);
296                         }
297                         BT_DBG("Characteristics count : %d", service->char_handle.count);
298                 }
299         }
300
301         service->handle = g_strdup(service_handle);
302
303         g_variant_iter_free(property_iter);
304         g_variant_unref(result);
305         g_object_unref(properties_proxy);
306
307         return BLUETOOTH_ERROR_NONE;
308 }
309
310 BT_EXPORT_API int bluetooth_gatt_get_primary_services(
311                 const bluetooth_device_address_t *address,
312                 bt_gatt_handle_info_t *prim_svc)
313 {
314         GVariant *result = NULL;
315         GVariantIter *iter;
316         GVariantIter *svc_iter;
317         GVariantIter *interface_iter;
318         char *object_path = NULL;
319         char *interface_str = NULL;
320         const gchar *key = NULL;
321         GVariant *value = NULL;
322         GPtrArray *gp_array  = NULL;
323         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
324         char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
325         int ret = BLUETOOTH_ERROR_INTERNAL;
326         int idx = 0;
327
328         BT_INFO("+");
329         BT_CHECK_PARAMETER(address, return);
330         BT_CHECK_PARAMETER(prim_svc, return);
331         BT_CHECK_ENABLED(return);
332
333         result = _bt_get_managed_objects();
334         if (result == NULL)
335                 return ret;
336
337         _bt_convert_addr_type_to_string(device_address,
338                         (unsigned char *)address->addr);
339
340         gp_array = g_ptr_array_new();
341         g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
342
343         while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
344                         &interface_iter)) {
345                 if (object_path == NULL)
346                         continue;
347
348                 _bt_convert_device_path_to_address(object_path, temp_address);
349
350                 if (g_strcmp0(temp_address, device_address) != 0)
351                         continue;
352
353                 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
354                                 &interface_str, &svc_iter)) {
355                         if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
356                                 continue;
357
358                         BT_DBG("[%d] Object Path : %s", idx++, object_path);
359                         while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
360                                 if (g_strcmp0(key, "Primary") == 0) {
361                                         if (g_variant_get_boolean(value))
362                                                 g_ptr_array_add(gp_array, (gpointer)object_path);
363                                 }
364                         }
365                 }
366         }
367
368         if (gp_array->len == 0) {
369                 BT_ERR("gp_array is NULL");
370                 ret = BLUETOOTH_ERROR_NOT_FOUND;
371         } else {
372                 ret = BLUETOOTH_ERROR_NONE;
373                 prim_svc->count = gp_array->len;
374                 prim_svc->handle = __get_string_array_from_gptr_array(gp_array);
375         }
376
377         g_ptr_array_free(gp_array, TRUE);
378         g_variant_iter_free(iter);
379         g_variant_unref(result);
380         BT_DBG("-");
381         return ret;
382 }
383
384 BT_EXPORT_API int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address,
385                         const char *service_uuid,
386                         bt_gatt_service_property_t *service)
387 {
388         GVariant *result = NULL;
389         GVariantIter *iter;
390         GVariantIter *svc_iter;
391         GVariantIter *interface_iter;
392         char *object_path = NULL;
393         char *interface_str = NULL;
394         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
395         char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
396         int ret = BLUETOOTH_ERROR_INTERNAL;
397
398         BT_CHECK_PARAMETER(address, return);
399         BT_CHECK_PARAMETER(service_uuid, return);
400         BT_CHECK_PARAMETER(service, return);
401         BT_CHECK_ENABLED(return);
402
403         result = _bt_get_managed_objects();
404         if (result == NULL)
405                 return ret;
406
407         _bt_convert_addr_type_to_string(device_address,
408                                 (unsigned char *)address->addr);
409
410         g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
411
412         while (g_variant_iter_loop(iter, "{oa{sa{sv}}}", &object_path,
413                         &interface_iter)) {
414                 if (object_path == NULL)
415                         continue;
416
417                 _bt_convert_device_path_to_address(object_path,
418                                 temp_address);
419
420                 if (g_strcmp0(temp_address, device_address) != 0)
421                         continue;
422
423                 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
424                                 &interface_str, &svc_iter)) {
425                         if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
426                                 continue;
427
428                         BT_DBG("Object Path: %s", object_path);
429                         ret = bluetooth_gatt_get_service_property(object_path,
430                                         service);
431
432                         if (ret != BLUETOOTH_ERROR_NONE) {
433                                 BT_ERR("Get service property failed(0x%08x)", ret);
434                         } else {
435                                 if (service->primary == TRUE &&
436                                                 g_strstr_len(service->uuid, -1,
437                                                                 service_uuid)) {
438                                         ret = BLUETOOTH_ERROR_NONE;
439                                         goto done;
440                                 }
441                         }
442                         bluetooth_gatt_free_service_property(service);
443                 }
444         }
445
446 done:
447         g_variant_iter_free(iter);
448         g_variant_unref(result);
449
450         return ret;
451 }
452
453 static void __bluetooth_internal_get_char_cb(GDBusProxy *proxy,
454                 GAsyncResult *res, gpointer user_data)
455 {
456         GVariant *value;
457         GVariant *char_value;
458         GVariantIter *char_iter;
459         GPtrArray *gp_array = NULL;
460         bt_gatt_discovered_char_t svc_char = { 0, };
461         char *char_handle;
462         GError *error = NULL;
463         bt_user_info_t *user_info;
464
465         BT_DBG("+");
466
467         user_info = _bt_get_user_data(BT_COMMON);
468         svc_char.service_handle = user_data;
469
470         value = g_dbus_proxy_call_finish(proxy, res, &error);
471
472         if (value == NULL) {
473                 if (error != NULL) {
474                         BT_ERR("Get service characteristics failed\n errCode[%x],"
475                                         "message[%s]\n", error->code, error->message);
476                         g_clear_error(&error);
477                 } else {
478                         BT_ERR("Get service characteristics failed\n");
479                 }
480                 if (user_info) {
481                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
482                                 BLUETOOTH_ERROR_INTERNAL, NULL,
483                                 user_info->cb, user_info->user_data);
484                 }
485                 g_free(svc_char.service_handle);
486                 g_object_unref(proxy);
487                 return;
488         }
489
490         g_variant_get(value, "(v)", &char_value);
491         g_variant_get(char_value, "ao", &char_iter);
492
493         gp_array = g_ptr_array_new();
494         while (g_variant_iter_loop(char_iter, "&o",  &char_handle))
495                 g_ptr_array_add(gp_array, (gpointer)char_handle);
496
497         if (gp_array->len != 0) {
498                 svc_char.handle_info.count = gp_array->len;
499                 svc_char.handle_info.handle =
500                         __get_string_array_from_gptr_array(gp_array);
501         }
502         g_ptr_array_free(gp_array, TRUE);
503
504         if (user_info) {
505                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
506                         BLUETOOTH_ERROR_NONE, &svc_char,
507                         user_info->cb, user_info->user_data);
508         }
509
510         g_strfreev(svc_char.handle_info.handle);
511         g_free(svc_char.service_handle);
512         g_variant_iter_free(char_iter);
513         g_variant_unref(value);
514         g_object_unref(proxy);
515 }
516
517 BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(
518                         const char *service_handle)
519 {
520         GDBusProxy *properties_proxy = NULL;
521         GDBusConnection *g_conn;
522         GError *error = NULL;
523         char *handle;
524
525         BT_DBG("+");
526
527         BT_CHECK_PARAMETER(service_handle, return);
528         BT_CHECK_ENABLED(return);
529
530         g_conn = _bt_gdbus_get_system_gconn();
531         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
532
533         properties_proxy = g_dbus_proxy_new_sync(g_conn,
534                         G_DBUS_PROXY_FLAGS_NONE, NULL,
535                         BT_BLUEZ_NAME,
536                         service_handle,
537                         BT_PROPERTIES_INTERFACE,
538                         NULL, &error);
539
540         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
541
542         handle = g_strdup(service_handle);
543         g_dbus_proxy_call(properties_proxy,
544                         "Get",
545                         g_variant_new("(ss)",
546                                 GATT_SERV_INTERFACE, "Characteristics"),
547                         G_DBUS_CALL_FLAGS_NONE,
548                         -1,
549                         NULL,
550                         (GAsyncReadyCallback)__bluetooth_internal_get_char_cb,
551                         (gpointer)handle);
552
553         BT_DBG("-");
554         return BLUETOOTH_ERROR_NONE;
555 }
556
557
558 static int __get_permission_flag(char *permission)
559 {
560         int ret = 0;
561
562         retv_if(permission == NULL, ret);
563
564         BT_INFO("permission = %s", permission);
565
566         if (!g_strcmp0(permission, "broadcast"))
567                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
568         else if (!g_strcmp0(permission, "read"))
569                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
570         else if (!g_strcmp0(permission, "write-without-response"))
571                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
572         else if (!g_strcmp0(permission, "write"))
573                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
574         else if (!g_strcmp0(permission, "notify"))
575                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
576         else if (!g_strcmp0(permission, "indicate"))
577                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
578         else if (!g_strcmp0(permission, "authenticated-signed-writes"))
579                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
580         else if (!g_strcmp0(permission, "reliable-write"))
581                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
582         else if (!g_strcmp0(permission, "writable-auxiliaries"))
583                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
584         else if (!g_strcmp0(permission, "encrypt-read"))
585                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
586         else if (!g_strcmp0(permission, "encrypt-write"))
587                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
588         else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
589                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
590         else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
591                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
592
593         return ret;
594 }
595
596 static void __convert_permission_flag_to_str(unsigned int permission)
597 {
598         char perm[200] = { 0, };
599
600         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST)
601                 g_strlcat(perm, "broadcast ", sizeof(perm));
602         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ)
603                 g_strlcat(perm, "read ", sizeof(perm));
604         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE)
605                 g_strlcat(perm, "write-without-response ", sizeof(perm));
606         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE)
607                 g_strlcat(perm, "write ", sizeof(perm));
608         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY)
609                 g_strlcat(perm, "notify ", sizeof(perm));
610         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE)
611                 g_strlcat(perm, "indicate ", sizeof(perm));
612         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE)
613                 g_strlcat(perm, "authenticated-signed-writes ", sizeof(perm));
614         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE)
615                 g_strlcat(perm, "reliable-write ", sizeof(perm));
616         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES)
617                 g_strlcat(perm, "writable-auxiliaries ", sizeof(perm));
618         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ)
619                 g_strlcat(perm, "encrypt-read ", sizeof(perm));
620         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE)
621                 g_strlcat(perm, "encrypt-write ", sizeof(perm));
622         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ)
623                 g_strlcat(perm, "encrypt-authenticated-read ", sizeof(perm));
624         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE)
625                 g_strlcat(perm, "encrypt-authenticated-write ", sizeof(perm));
626
627         BT_INFO("permission [0x%04x] : %s\n", permission, perm);
628         return;
629 }
630
631 BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
632                 const char *char_handle, bt_gatt_char_property_t *characteristic)
633 {
634         GDBusProxy *properties_proxy = NULL;
635         GError *error = NULL;
636         GVariant *value = NULL;
637         GVariant *result = NULL;
638         GByteArray *gb_array = NULL;
639         GPtrArray *gp_array  = NULL ;
640         GDBusConnection *g_conn;
641         guint8 char_value;
642         const gchar *key;
643         gchar* permission;
644         char *char_desc_handle = NULL;
645         gsize len;
646         GVariantIter *property_iter;
647         GVariantIter *char_value_iter;
648         GVariantIter *char_perm_iter;
649         GVariantIter *char_desc_iter;
650
651         BT_DBG("+");
652         BT_CHECK_PARAMETER(char_handle, return);
653         BT_CHECK_PARAMETER(characteristic, return);
654
655         BT_CHECK_ENABLED(return);
656
657         g_conn = _bt_gdbus_get_system_gconn();
658         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
659
660         properties_proxy = g_dbus_proxy_new_sync(g_conn,
661                         G_DBUS_PROXY_FLAGS_NONE, NULL,
662                         BT_BLUEZ_NAME,
663                         char_handle,
664                         BT_PROPERTIES_INTERFACE,
665                         NULL, &error);
666
667         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
668
669         result = g_dbus_proxy_call_sync(properties_proxy,
670                                 "GetAll",
671                                         g_variant_new("(s)", GATT_CHAR_INTERFACE),
672                                 G_DBUS_CALL_FLAGS_NONE,
673                                 -1,
674                                 NULL,
675                                 &error);
676
677         if (!result) {
678                 if (error != NULL) {
679                         BT_ERR("Fail to get properties (Error: %s)", error->message);
680                         g_clear_error(&error);
681                 } else
682                         BT_ERR("Fail to get properties");
683                 g_object_unref(properties_proxy);
684                 return BLUETOOTH_ERROR_INTERNAL;
685         }
686
687         g_variant_get(result, "(a{sv})", &property_iter);
688
689         memset(characteristic, 0, sizeof(bt_gatt_char_property_t));
690         characteristic->handle = g_strdup(char_handle);
691
692         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
693                 if (!g_strcmp0(key, "UUID")) {
694                         char *name = NULL;
695                         characteristic->uuid = g_variant_dup_string(value, &len);
696                         bluetooth_get_uuid_name(characteristic->uuid, &name);
697                         BT_INFO("%s %s [%s]", char_handle + 37, characteristic->uuid, name);
698                         g_free(name);
699                 } else if (!g_strcmp0(key, "Value")) {
700                         gb_array = g_byte_array_new();
701                         g_variant_get(value, "ay", &char_value_iter);
702                         while (g_variant_iter_loop(char_value_iter, "y",  &char_value)) {
703                         //      BT_DBG("value of char = %d",char_value);
704                                 g_byte_array_append(gb_array, &char_value, 1);
705                         }
706                         g_variant_iter_free(char_value_iter);
707
708                         if (gb_array->len != 0) {
709                                 characteristic->val = g_malloc0(gb_array->len *
710                                                                 sizeof(unsigned char));
711                                 memcpy(characteristic->val, gb_array->data, gb_array->len);
712                         }
713                         characteristic->val_len = gb_array->len;
714                         g_byte_array_free(gb_array, TRUE);
715                 } else if (!g_strcmp0(key, "Flags")) {
716                         g_variant_get(value, "as", &char_perm_iter);
717                         characteristic->permission = 0x00;
718
719                         while (g_variant_iter_loop(char_perm_iter, "s", &permission))
720                                 characteristic->permission |= __get_permission_flag(permission);
721                         __convert_permission_flag_to_str(characteristic->permission);
722
723                         g_variant_iter_free(char_perm_iter);
724                 } else if (!g_strcmp0(key, "Descriptors")) {
725                         g_variant_get(value, "ao", &char_desc_iter);
726                         gp_array = g_ptr_array_new();
727                         while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle))
728                                 g_ptr_array_add(gp_array, (gpointer)char_desc_handle);
729
730                         g_variant_iter_free(char_desc_iter);
731                         if (gp_array->len != 0) {
732                                 characteristic->char_desc_handle.count = gp_array->len;
733                                 characteristic->char_desc_handle.handle =
734                                                 __get_string_array_from_gptr_array(gp_array);
735                         }
736                         g_ptr_array_free(gp_array, TRUE);
737                 }
738         }
739
740         g_variant_iter_free(property_iter);
741         g_variant_unref(result);
742         g_object_unref(properties_proxy);
743
744         BT_DBG("-");
745         return BLUETOOTH_ERROR_NONE;
746 }
747
748 void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy,
749                         GAsyncResult *res, gpointer user_data)
750 {
751         GVariant *value;
752         GVariantIter *char_iter;
753         char *char_handle;
754         GError *error = NULL;
755         bt_user_info_t *user_info;
756         int ret = BLUETOOTH_ERROR_INTERNAL;
757         bt_gatt_char_property_t characteristic;
758
759         user_info = _bt_get_user_data(BT_COMMON);
760
761         value = g_dbus_proxy_call_finish(proxy, res, &error);
762
763         if (value == NULL) {
764                 if (error != NULL) {
765                         BT_ERR("Get service characteristics failed\n errCode[%x],"
766                                         "message[%s]\n", error->code, error->message);
767                         g_clear_error(&error);
768                 } else {
769                         BT_ERR("Get service characteristics failed\n");
770                 }
771                 if (user_info) {
772                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
773                                 BLUETOOTH_ERROR_INTERNAL, NULL,
774                                 user_info->cb, user_info->user_data);
775                 }
776                 g_object_unref(proxy);
777                 g_free(user_data);
778                 return;
779         }
780
781         g_variant_get(value, "(ao)", &char_iter);
782
783         while (g_variant_iter_loop(char_iter, "&o",  &char_handle)) {
784                 if (!char_handle)
785                         continue;
786                 ret = bluetooth_gatt_get_characteristics_property(char_handle,
787                                 &characteristic);
788
789                 if (ret != BLUETOOTH_ERROR_NONE) {
790                         BT_ERR("Get characteristic property failed(0x%08x)", ret);
791                 } else {
792                         if (g_strstr_len(characteristic.uuid, -1, user_data)) {
793                                 ret = BLUETOOTH_ERROR_NONE;
794                                 break;
795                         }
796                 }
797                 bluetooth_gatt_free_char_property(&characteristic);
798         }
799
800         if (user_info) {
801                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret,
802                                 &characteristic, user_info->cb, user_info->user_data);
803         }
804
805         bluetooth_gatt_free_char_property(&characteristic);
806         g_variant_iter_free(char_iter);
807         g_variant_unref(value);
808         g_free(user_data);
809 }
810
811 BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
812                                                 const char *char_uuid)
813 {
814         GDBusProxy *properties_proxy = NULL;
815         GDBusConnection *g_conn;
816         GError *error = NULL;
817         char *uuid;
818
819         BT_CHECK_PARAMETER(service_handle, return);
820         BT_CHECK_PARAMETER(char_uuid, return);
821         BT_CHECK_ENABLED(return);
822
823         g_conn = _bt_gdbus_get_system_gconn();
824         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
825
826         properties_proxy = g_dbus_proxy_new_sync(g_conn,
827                         G_DBUS_PROXY_FLAGS_NONE, NULL,
828                         BT_BLUEZ_NAME,
829                         service_handle,
830                         BT_PROPERTIES_INTERFACE,
831                         NULL, &error);
832
833         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
834
835         uuid = g_strdup(char_uuid);
836         g_dbus_proxy_call(properties_proxy,
837                         "Get",
838                         g_variant_new("(ss)",
839                                 GATT_SERV_INTERFACE, "Characteristics"),
840                         G_DBUS_CALL_FLAGS_NONE,
841                         -1,
842                         NULL,
843                         (GAsyncReadyCallback)bluetooth_gatt_get_char_from_uuid_cb,
844                         (gpointer)uuid);
845
846         return BLUETOOTH_ERROR_NONE;
847 }
848
849 BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
850                 const char *descriptor_handle, bt_gatt_char_descriptor_property_t *descriptor)
851 {
852         GDBusProxy *properties_proxy = NULL;
853         GError *error = NULL;
854         GDBusConnection *g_conn;
855         GVariant *result = NULL;
856         GVariantIter *property_iter;
857         const gchar *key;
858         guint8 char_value;
859         gsize len;
860         GVariant *value = NULL;
861         GByteArray *gb_array = NULL;
862         GVariantIter *desc_value_iter;
863
864         BT_INFO("+");
865         BT_CHECK_PARAMETER(descriptor_handle, return);
866         BT_CHECK_PARAMETER(descriptor, return);
867
868         BT_CHECK_ENABLED(return);
869
870         g_conn = _bt_gdbus_get_system_gconn();
871         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
872
873         properties_proxy = g_dbus_proxy_new_sync(g_conn,
874                         G_DBUS_PROXY_FLAGS_NONE, NULL,
875                         BT_BLUEZ_NAME,
876                         descriptor_handle,
877                         BT_PROPERTIES_INTERFACE,
878                         NULL, &error);
879
880         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
881
882         result = g_dbus_proxy_call_sync(properties_proxy,
883                                 "GetAll",
884                                         g_variant_new("(s)", GATT_DESC_INTERFACE),
885                                 G_DBUS_CALL_FLAGS_NONE,
886                                 -1,
887                                 NULL,
888                                 &error);
889
890         if (!result) {
891                 if (error != NULL) {
892                         BT_ERR("Fail to get properties (Error: %s)", error->message);
893                         g_clear_error(&error);
894                 } else
895                         BT_ERR("Fail to get properties");
896                 g_object_unref(properties_proxy);
897                 return BLUETOOTH_ERROR_INTERNAL;
898         }
899
900         g_variant_get(result, "(a{sv})", &property_iter);
901
902         memset(descriptor, 0, sizeof(bt_gatt_char_descriptor_property_t));
903         descriptor->handle = g_strdup(descriptor_handle);
904
905         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
906                 if (!g_strcmp0(key, "UUID")) {
907                         char *name = NULL;
908                         descriptor->uuid = g_variant_dup_string(value, &len);
909                         bluetooth_get_uuid_name(descriptor->uuid, &name);
910                         BT_INFO("Descriptor : %s [%s]", descriptor->uuid, name);
911                         g_free(name);
912                 } else if (!g_strcmp0(key, "Value")) {
913                         gb_array = g_byte_array_new();
914                         g_variant_get(value, "ay", &desc_value_iter);
915                         while (g_variant_iter_loop(desc_value_iter, "y",  &char_value)) {
916                                 BT_DBG("value of descriptor = %d", char_value);
917                                 g_byte_array_append(gb_array, &char_value, 1);
918                         }
919                         g_variant_iter_free(desc_value_iter);
920
921                         if (gb_array->len != 0) {
922                                 descriptor->val = g_malloc0(gb_array->len *
923                                                                 sizeof(unsigned char));
924                                 memcpy(descriptor->val, gb_array->data, gb_array->len);
925                         }
926                         descriptor->val_len = gb_array->len;
927                         g_byte_array_free(gb_array, TRUE);
928                 }
929         }
930
931         g_variant_iter_free(property_iter);
932         g_variant_unref(result);
933         g_object_unref(properties_proxy);
934
935         BT_INFO("-");
936         return BLUETOOTH_ERROR_NONE;
937 }
938
939 static int __bluetooth_get_att_error_code(GError *error)
940 {
941         int att_ecode = 0;
942         int len;
943         char *str = NULL;
944
945         BT_ERR("Error : %s", error->message);
946         str = g_strrstr(error->message, "ATT error: 0x");
947         if (str) {
948                 len = strlen(str);
949                 att_ecode =  g_ascii_xdigit_value(str[len - 2]) << 4;
950                 att_ecode += g_ascii_xdigit_value(str[len - 1]);
951         } else
952                 return BLUETOOTH_ATT_ERROR_INTERNAL;
953
954         switch (att_ecode) {
955         case BLUETOOTH_ATT_ERROR_READ_NOT_PERMITTED:
956                 BT_ERR("Read not permitted");
957                 break;
958         case BLUETOOTH_ATT_ERROR_WRITE_NOT_PERMITTED:
959                 BT_ERR("Write not permitted");
960                 break;
961         case BLUETOOTH_ATT_ERROR_AUTHENTICATION:
962         case BLUETOOTH_ATT_ERROR_INSUFFICIENT_ENCRYPTION:
963         case BLUETOOTH_ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE:
964                 BT_ERR("Not paired");
965                 break;
966         case BLUETOOTH_ATT_ERROR_INVALID_OFFSET:
967                 BT_ERR("Invalid offset");
968                 break;
969         case BLUETOOTH_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN:
970                 BT_ERR("Invalid Length");
971                 break;
972         case BLUETOOTH_ATT_ERROR_AUTHORIZATION:
973                 BT_ERR("Operation not Authorized");
974                 break;
975         default:
976                 BT_ERR("default ecode");
977                 break;
978         }
979
980         if (att_ecode >= 0x80 && att_ecode <= 0x9F)
981                 BT_ERR("Application error");
982
983         return att_ecode;
984 }
985
986 static void __bluetooth_internal_read_cb(GObject *source_object,
987                                          GAsyncResult *res, gpointer user_data)
988 {
989         GError *error = NULL;
990         GDBusConnection *system_gconn = NULL;
991         GVariant *value;
992         bt_user_info_t *user_info;
993         GVariantIter *iter;
994         GByteArray *gp_byte_array = NULL;
995         guint8 g_byte;
996         int att_ecode = 0;
997         bt_gatt_resp_data_t *resp_data = user_data;
998
999         BT_DBG("+");
1000
1001         system_gconn = _bt_gdbus_get_system_gconn();
1002         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1003
1004         user_info = _bt_get_user_data(BT_COMMON);
1005         if (!user_info) {
1006                 g_free(resp_data);
1007                 if (error) {
1008                         BT_ERR("Error : %s", error->message);
1009                         g_clear_error(&error);
1010                         return;
1011                 }
1012                 g_variant_unref(value);
1013                 return;
1014         }
1015
1016         if (error) {
1017                 att_ecode = __bluetooth_get_att_error_code(error);
1018                 g_clear_error(&error);
1019
1020                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
1021                                     att_ecode, resp_data,
1022                                     user_info->cb, user_info->user_data);
1023                 g_free(resp_data);
1024                 return;
1025         }
1026
1027         gp_byte_array = g_byte_array_new();
1028         g_variant_get(value, "(ay)", &iter);
1029
1030         while (g_variant_iter_loop(iter, "y", &g_byte))
1031                 g_byte_array_append(gp_byte_array, &g_byte, 1);
1032
1033         if (gp_byte_array->len != 0) {
1034                 resp_data->len = gp_byte_array->len;
1035                 resp_data->value = gp_byte_array->data;
1036         }
1037
1038         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
1039                             BLUETOOTH_ATT_ERROR_NONE, resp_data,
1040                             user_info->cb, user_info->user_data);
1041         g_free(resp_data);
1042
1043         g_byte_array_free(gp_byte_array, TRUE);
1044         g_variant_iter_free(iter);
1045         g_variant_unref(value);
1046
1047         BT_DBG("-");
1048 }
1049
1050 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *chr,
1051                                                            gpointer user_data)
1052 {
1053         GDBusConnection *conn;
1054         bt_gatt_resp_data_t *resp_data;
1055         GVariantBuilder *builder = NULL;
1056         guint16 offset = 0;
1057
1058         BT_CHECK_PARAMETER(chr, return);
1059         BT_CHECK_ENABLED(return);
1060
1061         conn = _bt_gdbus_get_system_gconn();
1062         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1063
1064         resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1065         resp_data->user_data = user_data;
1066
1067         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1068
1069         /*offset*/
1070         g_variant_builder_add(builder, "{sv}", "offset",
1071                 g_variant_new("q", offset));
1072
1073         /* Device Object path*/
1074 //      g_variant_builder_add(builder, "{sv}", "device",
1075 //      g_variant_new_object("o", NULL));
1076
1077         g_dbus_connection_call(conn, BT_BLUEZ_NAME, chr, GATT_CHAR_INTERFACE,
1078                         "ReadValue", g_variant_new("(a{sv})", builder),
1079                         G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1080                         (GAsyncReadyCallback)__bluetooth_internal_read_cb,
1081                         (gpointer)resp_data);
1082         g_variant_builder_unref(builder);
1083
1084         return BLUETOOTH_ERROR_NONE;
1085 }
1086
1087 static void __bluetooth_internal_write_cb(GObject *source_object,
1088                                           GAsyncResult *res, gpointer user_data)
1089 {
1090         GError *error = NULL;
1091         GDBusConnection *system_gconn = NULL;
1092         bt_user_info_t *user_info;
1093         GVariant *value;
1094         int att_ecode = 0;
1095         bt_gatt_resp_data_t *resp_data = user_data;
1096
1097         system_gconn = _bt_gdbus_get_system_gconn();
1098         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1099
1100         user_info = _bt_get_user_data(BT_COMMON);
1101         if (!user_info) {
1102                 g_free(resp_data);
1103                 if (error) {
1104                         BT_ERR("Error : %s", error->message);
1105                         g_clear_error(&error);
1106                         return;
1107                 }
1108                 g_variant_unref(value);
1109                 return;
1110         }
1111
1112         if (error) {
1113                 att_ecode = __bluetooth_get_att_error_code(error);
1114                 g_clear_error(&error);
1115
1116                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
1117                                 att_ecode, resp_data,
1118                                 user_info->cb, user_info->user_data);
1119                 g_free(resp_data);
1120                 return;
1121         }
1122
1123         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
1124                         BLUETOOTH_ATT_ERROR_NONE, resp_data,
1125                         user_info->cb, user_info->user_data);
1126         g_free(resp_data);
1127
1128         g_variant_unref(value);
1129         return;
1130 }
1131
1132 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
1133                 const char *char_handle, const guint8 *value, int length)
1134 {
1135         GVariant *val, *options;
1136         GVariantBuilder *builder1;
1137         GVariantBuilder *builder2;
1138         GError *error = NULL;
1139         GDBusConnection *conn;
1140         int i = 0;
1141         guint16 offset = 0;
1142
1143         BT_DBG("+");
1144         BT_CHECK_PARAMETER(char_handle, return);
1145         BT_CHECK_PARAMETER(value, return);
1146         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1147         BT_CHECK_ENABLED(return);
1148
1149         conn = _bt_gdbus_get_system_gconn();
1150         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1151
1152         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1153         for (i = 0; i < length; i++)
1154                 g_variant_builder_add(builder1, "y", value[i]);
1155
1156         val = g_variant_new("ay", builder1);
1157
1158         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1159         /*offset*/
1160         g_variant_builder_add(builder2, "{sv}", "offset",
1161                                 g_variant_new_uint16(offset));
1162
1163         /* Device Object path*/
1164 //      g_variant_builder_add(builder2, "{sv}", "device",
1165 //      g_variant_new_object("o", NULL));
1166
1167         options = g_variant_new("a{sv}", builder2);
1168
1169         g_dbus_connection_call(conn,
1170                                 BT_BLUEZ_NAME,
1171                                 char_handle,
1172                                 GATT_CHAR_INTERFACE,
1173                                 "WriteValue",
1174                                 g_variant_new("(@ay@a{sv})",
1175                                 val, options),
1176                                 NULL,
1177                                 G_DBUS_CALL_FLAGS_NONE,
1178                                 -1, NULL,
1179                                 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1180                                 NULL);
1181
1182
1183         if (error) {
1184                 BT_ERR("Set value Failed: %s", error->message);
1185                 g_clear_error(&error);
1186                 g_variant_builder_unref(builder1);
1187                 return BLUETOOTH_ERROR_INTERNAL;
1188         }
1189         g_variant_builder_unref(builder1);
1190         g_variant_builder_unref(builder2);
1191
1192         BT_DBG("-");
1193         return BLUETOOTH_ERROR_NONE;
1194 }
1195
1196 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
1197                         const char *chr, const guint8 *value, int length,
1198                         guint8 write_type, gpointer user_data)
1199 {
1200         GVariant *val, *options;
1201         GVariantBuilder *builder1;
1202         GVariantBuilder *builder2;
1203         GDBusConnection *conn;
1204         guint16 offset = 0;
1205         int i = 0;
1206         int ret = BLUETOOTH_ERROR_NONE;
1207         bt_gatt_resp_data_t *resp_data;
1208
1209         BT_CHECK_PARAMETER(chr, return);
1210         BT_CHECK_PARAMETER(value, return);
1211         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1212         BT_CHECK_ENABLED_INTERNAL(return);
1213
1214         conn = _bt_gdbus_get_system_gconn();
1215         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1216
1217         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1218
1219         for (i = 0; i < length; i++)
1220                 g_variant_builder_add(builder1, "y", value[i]);
1221
1222         val = g_variant_new("ay", builder1);
1223
1224         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1225         /*offset*/
1226         g_variant_builder_add(builder2, "{sv}", "offset",
1227                         g_variant_new_uint16(offset));
1228
1229         /* Device Object path*/
1230 //      g_variant_builder_add(builder2, "{sv}", "device",
1231 //      g_variant_new_object("o", NULL));
1232
1233         options = g_variant_new("a{sv}", builder2);
1234
1235         resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1236         resp_data->user_data = user_data;
1237
1238         g_dbus_connection_call(conn, BT_BLUEZ_NAME, chr, GATT_CHAR_INTERFACE,
1239                         "WriteValuebyType",
1240                         g_variant_new("(y@ay@a{sv})", write_type, val, options),
1241                         NULL,
1242                         G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1243                         (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1244                         (gpointer)resp_data);
1245
1246         g_variant_builder_unref(builder1);
1247         g_variant_builder_unref(builder2);
1248
1249         return ret;
1250 }
1251
1252 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
1253                         const char *char_handle, const guint8 *value, int length)
1254 {
1255         GVariant *val, *options;
1256         GDBusConnection *conn;
1257         GVariantBuilder *builder1;
1258         GVariantBuilder *builder2;
1259         guint offset = 0;
1260         int i;
1261
1262         BT_DBG("+");
1263         BT_CHECK_PARAMETER(char_handle, return);
1264         BT_CHECK_PARAMETER(value, return);
1265         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1266         BT_CHECK_ENABLED(return);
1267
1268         conn = _bt_gdbus_get_system_gconn();
1269         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1270
1271         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1272
1273         for (i = 0; i < length; i++) {
1274                 g_variant_builder_add(builder1, "y", value[i]);
1275                 BT_DBG("value [] = %d", value[i]);
1276         }
1277
1278         val = g_variant_new("ay", builder1);
1279
1280         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1281         /*offset*/
1282         g_variant_builder_add(builder2, "{sv}", "offset",
1283                                 g_variant_new_uint16(offset));
1284
1285         /* Device Object path*/
1286 //      g_variant_builder_add(builder2, "{sv}", "device",
1287 //      g_variant_new_object("o", NULL));
1288
1289         options = g_variant_new("a{sv}", builder2);
1290
1291         g_dbus_connection_call(conn,
1292                                 BT_BLUEZ_NAME,
1293                                 char_handle,
1294                                 GATT_CHAR_INTERFACE,
1295                                 "WriteValue",
1296                                 g_variant_new("(@ay@a{sv})",
1297                                 val, options),
1298                                 NULL,
1299                                 G_DBUS_CALL_FLAGS_NONE,
1300                                 -1, NULL,
1301                                 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1302                                 NULL);
1303
1304         g_variant_builder_unref(builder1);
1305         g_variant_builder_unref(builder2);
1306
1307         BT_DBG("-");
1308         return BLUETOOTH_ERROR_NONE;
1309 }
1310
1311 static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
1312                         bt_gatt_char_property_t *characteristic)
1313 {
1314         BT_DBG("+");
1315         GDBusProxy *properties_proxy = NULL;
1316         GError *error = NULL;
1317         GVariant *value = NULL;
1318         GVariant *result = NULL;
1319         GDBusConnection *g_conn;
1320         int i, ret = BLUETOOTH_ERROR_NONE;
1321         const char *uuid = NULL;
1322         gsize len = 0;
1323         GVariantIter *desc_value_iter, *property_iter;
1324         const gchar *key;
1325         char_descriptor_type_t desc_type = TYPE_NONE;
1326
1327         g_conn = _bt_gdbus_get_system_gconn();
1328         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1329
1330         properties_proxy = g_dbus_proxy_new_sync(g_conn,
1331                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1332                         BT_BLUEZ_NAME,
1333                         char_handle,
1334                         BT_PROPERTIES_INTERFACE,
1335                         NULL, &error);
1336
1337         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1338
1339         result = g_dbus_proxy_call_sync(properties_proxy,
1340                                 "GetAll",
1341                                 g_variant_new("(s)", GATT_DESC_INTERFACE),
1342                                 G_DBUS_CALL_FLAGS_NONE,
1343                                 -1,
1344                                 NULL,
1345                                 &error);
1346
1347         if (!result) {
1348                 if (error != NULL) {
1349                         BT_ERR("Fail to get properties (Error: %s)", error->message);
1350                         g_clear_error(&error);
1351                 } else
1352                         BT_ERR("Fail to get properties");
1353                 g_object_unref(properties_proxy);
1354                 return BLUETOOTH_ERROR_INTERNAL;
1355         }
1356         g_variant_get(result, "(a{sv})", &property_iter);
1357         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1358                 if (!g_strcmp0(key, "UUID")) {
1359                         uuid = g_variant_get_string(value, &len);
1360                         if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
1361                                 BT_DBG("GATT_USER_DESC_UUID");
1362                                 desc_type = USER_DESC;
1363                         } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) {
1364                                 BT_DBG("GATT_CHAR_FORMAT");
1365                                 desc_type = CHAR_FORMAT;
1366                         } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) {
1367                                 BT_DBG("GATT_CHAR_CLIENT_CONF");
1368                                 desc_type = CLIENT_CONF;
1369                         } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) {
1370                                 BT_DBG("GATT_CHAR_SERVER_CONF");
1371                                 desc_type = SERVER_CONF;
1372                         } else {
1373                                 BT_DBG("descriptor uuid = %s", uuid);
1374                         }
1375                 } else if (!g_strcmp0(key, "Value")) {
1376                         switch (desc_type) {
1377                         case CHAR_FORMAT:
1378                                 BT_DBG("Format descriptor");
1379                                 g_variant_get(value, "(yyqyq)",
1380                                                 &(characteristic->format.format),
1381                                                 &(characteristic->format.exponent),
1382                                                 &(characteristic->format.unit),
1383                                                 &(characteristic->format.name_space),
1384                                                 &(characteristic->format.description));
1385                                 break;
1386                         case USER_DESC:
1387                                 BT_DBG("User descriptor");
1388                                 g_variant_get(value, "ay", &desc_value_iter);
1389                                 len = g_variant_get_size((GVariant *)desc_value_iter);
1390
1391                                 if (len > 0)
1392                                         characteristic->description = (char *)g_malloc0(len + 1);
1393
1394                                 for (i = 0; i < len; i++) {
1395                                         g_variant_iter_loop(desc_value_iter, "y",
1396                                                 &characteristic->description[i]);
1397                                         BT_DBG("description = %s", characteristic->description);
1398                                 }
1399                                 g_variant_iter_free(desc_value_iter);
1400                                 break;
1401                         case CLIENT_CONF:
1402                                 BT_DBG(" CLIENT_CONF");
1403                                 break;
1404                         case SERVER_CONF:
1405                                 BT_DBG(" SERVER_CONF");
1406                                 break;
1407                         default:
1408                                 break;
1409                         }
1410                 }
1411         }
1412
1413         g_variant_iter_free(property_iter);
1414         g_variant_unref(result);
1415         g_object_unref(properties_proxy);
1416
1417         BT_DBG("-");
1418         return ret;
1419 }
1420
1421
1422 static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
1423                         GAsyncResult *res, gpointer user_data)
1424 {
1425         BT_DBG("+");
1426         GVariant *value;
1427         GVariant        *char_value;
1428         GVariantIter *char_iter;
1429         char *char_handle;
1430         GError *error = NULL;
1431         bt_user_info_t *user_info;
1432         bt_gatt_char_property_t characteristic = {0, };
1433         int ret = BLUETOOTH_ERROR_INTERNAL;
1434
1435         user_info = _bt_get_user_data(BT_COMMON);
1436
1437         value = g_dbus_proxy_call_finish(proxy, res, &error);
1438         characteristic.handle = user_data;
1439
1440         if (value == NULL) {
1441                 if (error != NULL) {
1442                         BT_ERR("Get characteristic descriptor failed\n errCode[%x],"
1443                                         "message[%s]\n", error->code, error->message);
1444                         g_clear_error(&error);
1445                 } else {
1446                         BT_ERR("Get characteristic descriptor failed\n");
1447                 }
1448                 if (user_info) {
1449                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1450                                 BLUETOOTH_ERROR_INTERNAL, NULL,
1451                                 user_info->cb, user_info->user_data);
1452                 }
1453                 g_free(characteristic.handle);
1454                 g_object_unref(proxy);
1455                 return;
1456         }
1457
1458         g_variant_get(value, "(v)", &char_value);
1459         g_variant_get(char_value, "ao", &char_iter);
1460
1461         while (g_variant_iter_loop(char_iter, "&o",  &char_handle)) {
1462                 BT_DBG("object path of descriptor = %s", char_handle);
1463                 if (char_handle) {
1464                         ret = __bluetooth_gatt_descriptor_iter(char_handle,
1465                                                 &characteristic);
1466                         BT_DBG("Descriptor read status [%d]", ret);
1467                 }
1468         }
1469
1470         if (user_info) {
1471                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1472                                 ret, &characteristic, user_info->cb, user_info->user_data);
1473         }
1474         bluetooth_gatt_free_char_property(&characteristic);
1475
1476         g_variant_iter_free(char_iter);
1477         g_variant_unref(value);
1478         BT_DBG("-");
1479 }
1480
1481 BT_EXPORT_API int bluetooth_gatt_discover_characteristic_descriptor(
1482                         const char *characteristic_handle)
1483 {
1484         GDBusProxy *properties_proxy = NULL;
1485         GDBusConnection *g_conn;
1486         char *handle;
1487         GError *error = NULL;
1488
1489         BT_CHECK_PARAMETER(characteristic_handle, return);
1490         BT_CHECK_ENABLED(return);
1491
1492         g_conn = _bt_gdbus_get_system_gconn();
1493         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1494
1495         properties_proxy = g_dbus_proxy_new_sync(g_conn,
1496                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1497                         BT_BLUEZ_NAME,
1498                         characteristic_handle,
1499                         BT_PROPERTIES_INTERFACE,
1500                         NULL, &error);
1501
1502         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1503
1504         handle = g_strdup(characteristic_handle);
1505         g_dbus_proxy_call(properties_proxy,
1506                         "Get",
1507                         g_variant_new("(ss)",
1508                                 GATT_CHAR_INTERFACE, "Descriptors"),
1509                         G_DBUS_CALL_FLAGS_NONE,
1510                         -1, NULL,
1511                         (GAsyncReadyCallback)bluetooth_gatt_get_char_desc_cb,
1512                         (gpointer)handle);
1513
1514         return BLUETOOTH_ERROR_NONE;
1515 }
1516
1517 static void __bluetooth_internal_read_desc_cb(GObject *source_object,
1518                         GAsyncResult *res,
1519                         gpointer user_data)
1520 {
1521         GError *error = NULL;
1522         GDBusConnection *system_gconn = NULL;
1523         GVariant *value;
1524         bt_user_info_t *user_info;
1525         GByteArray *gp_byte_array = NULL;
1526         GVariantIter *iter;
1527         guint8 g_byte;
1528         int att_ecode = 0;
1529         bt_gatt_resp_data_t *resp_data = user_data;
1530
1531         BT_DBG("+");
1532
1533         system_gconn = _bt_gdbus_get_system_gconn();
1534         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1535
1536         user_info = _bt_get_user_data(BT_COMMON);
1537         if (!user_info) {
1538                 g_free(resp_data);
1539                 if (error) {
1540                         BT_ERR("Error : %s", error->message);
1541                         g_clear_error(&error);
1542                         return;
1543                 }
1544                 g_variant_unref(value);
1545                 return;
1546         }
1547
1548         if (error) {
1549                 att_ecode = __bluetooth_get_att_error_code(error);
1550                 g_clear_error(&error);
1551
1552                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1553                                 att_ecode, resp_data,
1554                                 user_info->cb, user_info->user_data);
1555                 g_free(resp_data);
1556                 return;
1557         }
1558
1559         gp_byte_array = g_byte_array_new();
1560         g_variant_get(value, "(ay)", &iter);
1561
1562         while (g_variant_iter_loop(iter, "y", &g_byte))
1563                 g_byte_array_append(gp_byte_array, &g_byte, 1);
1564
1565         if (gp_byte_array->len != 0) {
1566                 resp_data->len = gp_byte_array->len;
1567                 resp_data->value = gp_byte_array->data;
1568         }
1569
1570         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1571                         BLUETOOTH_ATT_ERROR_NONE, resp_data,
1572                         user_info->cb, user_info->user_data);
1573         g_free(resp_data);
1574
1575
1576         g_byte_array_free(gp_byte_array, TRUE);
1577         g_variant_iter_free(iter);
1578         g_variant_unref(value);
1579
1580         BT_DBG("-");
1581 }
1582
1583 BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *desc,
1584                                                        gpointer user_data)
1585 {
1586         GDBusConnection *conn;
1587         GVariantBuilder *builder;
1588         guint offset = 0;
1589         bt_gatt_resp_data_t *resp_data;
1590
1591         BT_DBG("+");
1592
1593         BT_CHECK_PARAMETER(desc, return);
1594         BT_CHECK_ENABLED(return);
1595
1596         conn = _bt_gdbus_get_system_gconn();
1597         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1598
1599         resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1600         resp_data->user_data = user_data;
1601
1602         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1603
1604         /*offset*/
1605         g_variant_builder_add(builder, "{sv}", "offset",
1606                                 g_variant_new("q", offset));
1607         /* Device Object path*/
1608 //  g_variant_builder_add(builder, "{sv}", "device",
1609 //  g_variant_new("o", serv_info->serv_path));
1610
1611         g_dbus_connection_call(conn, BT_BLUEZ_NAME, desc, GATT_DESC_INTERFACE,
1612                         "ReadValue", g_variant_new("(a{sv})", builder),
1613                         G_VARIANT_TYPE("(ay)"),
1614                         G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1615                         (GAsyncReadyCallback)__bluetooth_internal_read_desc_cb,
1616                         (gpointer)resp_data);
1617         g_variant_builder_unref(builder);
1618
1619         BT_DBG("-");
1620         return BLUETOOTH_ERROR_NONE;
1621 }
1622
1623 static void __bluetooth_internal_write_desc_cb(GObject *source_object,
1624                                         GAsyncResult *res, gpointer user_data)
1625 {
1626         GError *error = NULL;
1627         bt_user_info_t *user_info;
1628         GDBusConnection *system_gconn = NULL;
1629         GVariant *value;
1630         int att_ecode = BLUETOOTH_ATT_ERROR_NONE;
1631         bt_gatt_resp_data_t *resp_data = user_data;
1632
1633         BT_DBG("+");
1634
1635         system_gconn = _bt_gdbus_get_system_gconn();
1636         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1637
1638         user_info = _bt_get_user_data(BT_COMMON);
1639         if (!user_info) {
1640                 g_free(resp_data);
1641                 if (error) {
1642                         BT_ERR("Error : %s", error->message);
1643                         g_clear_error(&error);
1644                         return;
1645                 }
1646                 g_variant_unref(value);
1647                 return;
1648         }
1649
1650         if (error) {
1651                 att_ecode = __bluetooth_get_att_error_code(error);
1652                 g_clear_error(&error);
1653
1654                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1655                                 att_ecode, resp_data,
1656                                 user_info->cb, user_info->user_data);
1657                 g_free(resp_data);
1658                 return;
1659         }
1660
1661         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1662                                 BLUETOOTH_ATT_ERROR_NONE, resp_data,
1663                         user_info->cb, user_info->user_data);
1664         g_free(resp_data);
1665
1666         g_variant_unref(value);
1667         BT_DBG("-");
1668 }
1669
1670 BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(const char *desc,
1671                         const guint8 *value, int length, gpointer user_data)
1672 {
1673         GVariant *val, *options;
1674         GDBusConnection *conn;
1675         GVariantBuilder *builder1;
1676         GVariantBuilder *builder2;
1677         guint offset = 0;
1678         int i;
1679         bt_gatt_resp_data_t *resp_data;
1680
1681         BT_DBG("+");
1682
1683         BT_CHECK_PARAMETER(desc, return);
1684         BT_CHECK_PARAMETER(value, return);
1685         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1686         BT_CHECK_ENABLED(return);
1687
1688         conn = _bt_gdbus_get_system_gconn();
1689         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1690
1691         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1692
1693         for (i = 0; i < length; i++)
1694                 g_variant_builder_add(builder1, "y", value[i]);
1695
1696         val = g_variant_new("ay", builder1);
1697
1698         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1699         /*offset*/
1700         g_variant_builder_add(builder2, "{sv}", "offset",
1701                                 g_variant_new_uint16(offset));
1702
1703         /* Device Object path*/
1704 //      g_variant_builder_add(builder2, "{sv}", "device",
1705 //      g_variant_new_object("o", NULL));
1706
1707         options = g_variant_new("a{sv}", builder2);
1708
1709         resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1710         resp_data->user_data = user_data;
1711
1712         g_dbus_connection_call(conn, BT_BLUEZ_NAME, desc, GATT_DESC_INTERFACE,
1713                         "WriteValue", g_variant_new("(@ay@a{sv})",
1714                         val, options), NULL,
1715                         G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1716                         (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
1717                         (gpointer)resp_data);
1718
1719         g_variant_builder_unref(builder1);
1720         g_variant_builder_unref(builder2);
1721
1722         BT_DBG("-");
1723         return BLUETOOTH_ERROR_NONE;
1724 }
1725
1726 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle, const char *svc_name)
1727 {
1728         GDBusConnection *conn;
1729         GError *error = NULL;
1730         int ret = BLUETOOTH_ERROR_NONE;
1731
1732         BT_CHECK_PARAMETER(char_handle, return);
1733         BT_CHECK_ENABLED(return);
1734
1735         BT_INFO_C("### Enable CCCD : %s [%s]", char_handle + 15, svc_name);
1736
1737         conn = _bt_gdbus_get_system_gconn();
1738         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1739
1740         g_dbus_connection_call_sync(conn,
1741                         BT_BLUEZ_NAME,
1742                         char_handle,
1743                         GATT_CHAR_INTERFACE,
1744                         "StartNotify",
1745                         NULL,
1746                         NULL,
1747                         G_DBUS_CALL_FLAGS_NONE,
1748                         GATT_DEFAULT_TIMEOUT, NULL, &error);
1749
1750         if (error) {
1751                 g_dbus_error_strip_remote_error(error);
1752                 BT_ERR_C("### Watch Failed: %s", error->message);
1753                 if (g_strrstr(error->message, "Already notifying"))
1754                         ret = BLUETOOTH_ERROR_NONE;
1755                 else if (g_strrstr(error->message, "In Progress"))
1756                         ret = BLUETOOTH_ERROR_IN_PROGRESS;
1757                 else if (g_strrstr(error->message, "Operation is not supported"))
1758                         ret = BLUETOOTH_ERROR_NOT_SUPPORT;
1759 /*failed because of either Insufficient Authorization or Write Not Permitted */
1760                 else if (g_strrstr(error->message, "Write not permitted") ||
1761                                 g_strrstr(error->message, "Operation Not Authorized"))
1762                         ret = BLUETOOTH_ERROR_PERMISSION_DEINED;
1763 /* failed because of either Insufficient Authentication,
1764         Insufficient Encryption Key Size, or Insufficient Encryption. */
1765                 else if (g_strrstr(error->message, "Not paired"))
1766                         ret = BLUETOOTH_ERROR_NOT_PAIRED;
1767                 else
1768                         ret = BLUETOOTH_ERROR_INTERNAL;
1769
1770                 g_clear_error(&error);
1771         }
1772
1773         return ret;
1774 }
1775
1776 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle)
1777 {
1778
1779         GDBusConnection *conn;
1780         GError *error = NULL;
1781         int ret = BLUETOOTH_ERROR_NONE;
1782         BT_CHECK_PARAMETER(char_handle, return);
1783
1784         BT_CHECK_ENABLED(return);
1785
1786         BT_INFO("Disable CCCD : %s", char_handle);
1787
1788         conn = _bt_gdbus_get_system_gconn();
1789         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1790
1791         g_dbus_connection_call_sync(conn,
1792                         BT_BLUEZ_NAME,
1793                         char_handle,
1794                         GATT_CHAR_INTERFACE,
1795                         "StopNotify",
1796                         NULL,
1797                         NULL,
1798                         G_DBUS_CALL_FLAGS_NONE,
1799                         GATT_DEFAULT_TIMEOUT, NULL, &error);
1800
1801         if (error) {
1802                 BT_ERR("Watch Failed: %s", error->message);
1803                 g_clear_error(&error);
1804                 ret =  BLUETOOTH_ERROR_INTERNAL;
1805         }
1806
1807         return ret;
1808 }
1809
1810 #ifdef TIZEN_GATT_CLIENT
1811 void __bt_uuid_hex_to_string(unsigned char *uuid, char *str)
1812 {
1813         uint32_t uuid0, uuid4;
1814         uint16_t uuid1, uuid2, uuid3, uuid5;
1815
1816         memcpy(&uuid0, &(uuid[0]), 4);
1817         memcpy(&uuid1, &(uuid[4]), 2);
1818         memcpy(&uuid2, &(uuid[6]), 2);
1819         memcpy(&uuid3, &(uuid[8]), 2);
1820         memcpy(&uuid4, &(uuid[10]), 4);
1821         memcpy(&uuid5, &(uuid[14]), 2);
1822
1823         snprintf((char *)str, BLUETOOTH_UUID_STRING_MAX, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
1824                         ntohl(uuid0), ntohs(uuid1),
1825                         ntohs(uuid2), ntohs(uuid3),
1826                         ntohl(uuid4), ntohs(uuid5));
1827         return;
1828 }
1829
1830
1831 static void __bt_fill_service_handle_informations(bt_services_browse_info_t *props,
1832                 bt_gatt_handle_info_t *svcs)
1833 {
1834         int count;
1835         BT_INFO("Total services found [%d]", props->count);
1836
1837         if (props->count == 0)
1838                 return;
1839
1840         svcs->count = props->count;
1841
1842         for (count = 0; count < props->count; count++) {
1843                 BT_INFO("UUID[%d] = [%s] instance_id [%d] Is Primary [%d]",
1844                                 count, props->uuids[count], props->inst_id[count], props->primary[count]);
1845                 g_strlcpy(svcs->uuids[count], props->uuids[count],
1846                                 BLUETOOTH_UUID_STRING_MAX);
1847                 svcs->inst_id[count] = props->inst_id[count];
1848         }
1849 }
1850
1851 static void __bt_fill_char_handle_informations(bt_char_browse_info_t *props,
1852                 bt_gatt_service_property_t *service)
1853 {
1854         int count;
1855         char uuid_string[BLUETOOTH_UUID_STRING_MAX];
1856         BT_INFO("Total number of characteristics found [%d]",
1857                         props->count);
1858
1859         service->char_handle.count = props->count;
1860
1861         /* Before filling all char handles, fill the service's UUID and instance ID */
1862         __bt_uuid_hex_to_string(props->svc_uuid, uuid_string);
1863         service->uuid = g_strdup(uuid_string);
1864         service->primary = TRUE;
1865
1866         /* Now fill all the char handles [UUID and Instance ID's]*/
1867         for (count = 0; count < props->count; count++) {
1868                 BT_INFO("UUID[%d] = [%s] instance_id [%d] properties [%d]",
1869                                 count, props->uuids[count], props->inst_id[count], props->props[count]);
1870
1871                 g_strlcpy(service->char_handle.uuids[count],
1872                                 props->uuids[count],
1873                                 BLUETOOTH_UUID_STRING_MAX);
1874
1875                 service->char_handle.inst_id[count] = props->inst_id[count];
1876         }
1877 }
1878
1879 static void __bt_fill_desc_handle_informations(bt_descriptor_browse_info_t *props,
1880                 bt_gatt_char_property_t *charc)
1881 {
1882         int count;
1883         char uuid_string[BLUETOOTH_UUID_STRING_MAX];
1884         BT_INFO("Total descriptor count found [%d]", props->count);
1885
1886         charc->char_desc_handle.count = props->count;
1887
1888         /* Before filling all desc handles, fill the charac's UUID and instance ID */
1889         __bt_uuid_hex_to_string(props->char_uuid, uuid_string);
1890         charc->uuid = g_strdup(uuid_string);
1891
1892         /* Now fill all the descriptor handles [UUID and Instance ID's]*/
1893         for (count = 0; count < props->count; count++) {
1894                 BT_INFO("UUID[%d] = [%s] instance_id [%d]",
1895                                 count, props->uuids[count], props->inst_id[count]);
1896
1897                 g_strlcpy(charc->char_desc_handle.uuids[count],
1898                                 props->uuids[count],
1899                                 BLUETOOTH_UUID_STRING_MAX);
1900
1901                 charc->char_desc_handle.inst_id[count] = props->inst_id[count];
1902         }
1903         charc->permission = props->char_props_map;
1904         BT_INFO("Characteritic property map val [%d]", charc->permission);
1905 }
1906
1907
1908 BT_EXPORT_API int bluetooth_gatt_client_init(
1909                 int *client_id,
1910                 const bluetooth_device_address_t *address,
1911                 gatt_client_cb_func_ptr callback_ptr)
1912 {
1913         int ret = BLUETOOTH_ERROR_NONE;
1914         bt_event_info_t *event_info;
1915         int *count;
1916
1917         BT_CHECK_PARAMETER(client_id, return);
1918         BT_CHECK_PARAMETER(callback_ptr, return);
1919         BT_CHECK_ENABLED(return);
1920
1921         BT_INFO("+");
1922
1923         BT_INIT_PARAMS();
1924         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1925
1926         g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
1927
1928         ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_REGISTER,
1929                         in_param1, in_param2, in_param3, in_param4, &out_param);
1930
1931         /* App ID -1 is invalid */
1932         if (ret == BLUETOOTH_ERROR_NONE) {
1933
1934                 *client_id = g_array_index(out_param, int, 0);
1935
1936                 BT_INFO("GATT Client Registered successfully: Client instance ID [%d]", *client_id);
1937
1938                 event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
1939
1940                 if (event_info) {
1941                         count = (int*)event_info->user_data;
1942
1943                         BT_INFO("Total num of GATT client instances [%d]", *count);
1944
1945                         /* Increement the count */
1946                         *count += 1;
1947                 } else {
1948                         BT_INFO("No GATT Client instances found in this application: Set User data");
1949                         count = g_malloc0(sizeof(int));
1950                         *count = 1;
1951
1952                         /* Register event handler for GATT */
1953                         _bt_register_event(BT_GATT_CLIENT_EVENT,
1954                                         (void *)callback_ptr,
1955                                         (void *)count);
1956                         _bt_set_user_data(BT_GATT_CLIENT, (void *)callback_ptr, NULL);
1957                 }
1958         } else
1959                 BT_ERR("GATT Client Registration failed!! ret [%d]", ret);
1960
1961         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1962         return ret;
1963 }
1964
1965
1966
1967 /* GATT Client*/
1968 BT_EXPORT_API int bluetooth_gatt_client_get_primary_services(
1969                 const bluetooth_device_address_t *address, /* Remote GATT Server */
1970                 bt_gatt_handle_info_t *prim_svc) /* UUID & instance_id */
1971 {
1972
1973         int result = BLUETOOTH_ERROR_NONE;
1974         bt_services_browse_info_t service_props;
1975
1976         BT_DBG("+");
1977
1978         BT_CHECK_PARAMETER(address, return);
1979         BT_CHECK_PARAMETER(prim_svc, return);
1980         BT_CHECK_ENABLED(return);
1981
1982         BT_INIT_PARAMS();
1983         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1984         g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
1985
1986         result = _bt_send_request(BT_BLUEZ_SERVICE,
1987                         BT_GATT_GET_PRIMARY_SERVICES,
1988                         in_param1, in_param2, in_param3, in_param4, &out_param);
1989
1990         if (BLUETOOTH_ERROR_NONE != result)
1991                 goto done;
1992
1993         memset(&service_props, 0x00, sizeof(bt_services_browse_info_t));
1994
1995         service_props = g_array_index(
1996                         out_param, bt_services_browse_info_t, 0);
1997
1998         __bt_fill_service_handle_informations(
1999                         &service_props, prim_svc);
2000
2001 done:
2002         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2003         BT_DBG("result = %d", result);
2004         return result;
2005 }
2006
2007 BT_EXPORT_API int bluetooth_gatt_client_get_service_property(
2008                 const char *address,
2009                 bt_gatt_handle_property_t *service_handle,
2010                 bt_gatt_service_property_t *service)
2011 {
2012         int result = BLUETOOTH_ERROR_NONE;
2013         bluetooth_gatt_client_svc_prop_info_t svc_prop;
2014         bt_char_browse_info_t char_handles_info;
2015         BT_INFO("Remote Address [%s]", address);
2016
2017         BT_CHECK_PARAMETER(address, return);
2018         BT_CHECK_PARAMETER(service_handle, return);
2019         BT_CHECK_PARAMETER(service, return);
2020         BT_CHECK_ENABLED(return);
2021
2022         /* Call to bt-service (sync) and send address and service_handle info */
2023         BT_INIT_PARAMS();
2024         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2025
2026         memset(&svc_prop, 0x00, sizeof(bluetooth_gatt_client_svc_prop_info_t));
2027         /* All characteristics handles are discovered */
2028         memset(&char_handles_info, 0x00, sizeof(bt_char_browse_info_t));
2029
2030         svc_prop.svc.instance_id = service_handle->instance_id;
2031         memcpy(&svc_prop.svc.uuid, &service_handle->uuid, 16);
2032
2033         _bt_convert_addr_string_to_type(svc_prop.device_address.addr, address);
2034
2035         g_array_append_vals(in_param1, &svc_prop, sizeof(bluetooth_gatt_client_svc_prop_info_t));
2036
2037         result = _bt_send_request(BT_BLUEZ_SERVICE,
2038                         BT_GATT_GET_SERVICE_PROPERTIES,
2039                         in_param1, in_param2, in_param3, in_param4, &out_param);
2040
2041         if (BLUETOOTH_ERROR_NONE != result)
2042                 goto done;
2043
2044         char_handles_info = g_array_index(
2045                         out_param, bt_char_browse_info_t, 0);
2046         __bt_fill_char_handle_informations(&char_handles_info,
2047                         service);
2048         /* TODO Get all Included Services */
2049
2050 done:
2051         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2052         BT_INFO("result = %d", result);
2053         return result;
2054 }
2055
2056 BT_EXPORT_API int bluetooth_gatt_client_get_characteristics_property(
2057                 const char *address,
2058                 bt_gatt_handle_property_t *service_handle,
2059                 bt_gatt_handle_property_t *char_handle,
2060                 bt_gatt_char_property_t *char_property)
2061 {
2062         int result = BLUETOOTH_ERROR_NONE;
2063         bt_descriptor_browse_info_t desc_handles_info;
2064         bluetooth_gatt_client_char_prop_info_t char_prop;
2065         BT_INFO("Get Properties of characteristics from remote device [%s]", address);
2066
2067         BT_CHECK_PARAMETER(address, return);
2068         BT_CHECK_PARAMETER(service_handle, return);
2069         BT_CHECK_PARAMETER(char_handle, return);
2070         BT_CHECK_PARAMETER(char_property, return);
2071         BT_CHECK_ENABLED(return);
2072
2073
2074         /* Call to bt-service (sync) and send address service_handle info & char handle info  */
2075         BT_INIT_PARAMS();
2076         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2077
2078         memset(&char_prop, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2079         char_prop.svc.instance_id = service_handle->instance_id;
2080         memcpy(&char_prop.svc.uuid, &service_handle->uuid, 16);
2081
2082         char_prop.characteristic.instance_id = char_handle->instance_id;
2083         memcpy(&char_prop.characteristic.uuid, &char_handle->uuid, 16);
2084
2085         _bt_convert_addr_string_to_type(char_prop.device_address.addr, address);
2086
2087         g_array_append_vals(in_param1, &char_prop, sizeof(bluetooth_gatt_client_char_prop_info_t));
2088
2089         result = _bt_send_request(BT_BLUEZ_SERVICE,
2090                         BT_GATT_GET_CHARACTERISTIC_PROPERTIES,
2091                         in_param1, in_param2, in_param3, in_param4, &out_param);
2092
2093         BT_INFO("result = [%d]", result);
2094         if (BLUETOOTH_ERROR_NONE != result)
2095                 goto done;
2096
2097         /* All descriptors handles are discovered */
2098         memset(&desc_handles_info, 0x00, sizeof(bt_descriptor_browse_info_t));
2099
2100         desc_handles_info = g_array_index(
2101                         out_param, bt_descriptor_browse_info_t, 0);
2102
2103         __bt_fill_desc_handle_informations(&desc_handles_info,
2104                         char_property);
2105
2106 done:
2107         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2108         BT_INFO("result = %d", result);
2109         return result;
2110         /* Call to bt-service (sync) and send address, service_handle & char_handle infos */
2111
2112         /* After result is fetched, extract descriptor handles (UUID's & instance_id's) */
2113
2114         /* Fill the info in *char_prop */
2115
2116         /*No: Before returning, call bluetooth_gatt_client_read_characteristic_value as
2117                 an asyn function and leave every thing else in the callback */
2118 }
2119
2120 BT_EXPORT_API int bluetooth_gatt_client_get_char_descriptor_property(
2121                 const char *address,
2122                 bt_gatt_handle_property_t *service_handle,
2123                 bt_gatt_handle_property_t *char_handle,
2124                 bt_gatt_handle_property_t *descriptor_handle,
2125                 bt_gatt_char_descriptor_property_t *desc_prop)
2126 {
2127         char uuid_string[BLUETOOTH_UUID_STRING_MAX];
2128         BT_DBG("Remote Address [%s]", address);
2129
2130         BT_CHECK_PARAMETER(address, return);
2131         BT_CHECK_PARAMETER(service_handle, return);
2132         BT_CHECK_PARAMETER(char_handle, return);
2133         BT_CHECK_PARAMETER(descriptor_handle, return);
2134         BT_CHECK_PARAMETER(desc_prop, return);
2135         /* No Need to Call to bt-service (sync) and send address, service_handle,
2136                 char_handle & descriptor handle infos */
2137         /* After result is fetched, extract descriptior handles (UUID's & instance_id's) */
2138         /* Fill the info in *desc_prop */
2139         __bt_uuid_hex_to_string(descriptor_handle->uuid, uuid_string);
2140
2141         /* Before filling all desc handles, fill the charac's UUID and instance ID */
2142         desc_prop->uuid = g_strdup(uuid_string);
2143
2144         return BLUETOOTH_ERROR_NONE;
2145         /* No: Before returning, call bluetooth_gatt_client_read_descriptor_value
2146                 as an asyn function and leave every thing else in the callback */
2147 }
2148
2149 BT_EXPORT_API int bluetooth_gatt_client_watch_characteristics(
2150                         const char *address,
2151                         bt_gatt_handle_property_t *service_handle,
2152                         bt_gatt_handle_property_t *char_handle,
2153                         int client_id,
2154                         gboolean is_notify)
2155 {
2156         int result = BLUETOOTH_ERROR_NONE;
2157         bluetooth_gatt_client_char_prop_info_t param;
2158         BT_DBG("+");
2159
2160         BT_CHECK_PARAMETER(address, return);
2161         BT_CHECK_PARAMETER(service_handle, return);
2162         BT_CHECK_PARAMETER(char_handle, return);
2163
2164         /* ASync Function, result expected in callback from bt-service */
2165
2166         BT_INIT_PARAMS();
2167         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2168
2169         BT_INFO("Address [%s]", address);
2170         memset(&param, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2171
2172         memcpy(&param.svc.uuid, service_handle->uuid, 16);
2173         param.svc.instance_id = service_handle->instance_id;
2174
2175         memcpy(&param.characteristic.uuid, char_handle->uuid, 16);
2176         param.characteristic.instance_id = char_handle->instance_id;
2177
2178         _bt_convert_addr_string_to_type(param.device_address.addr, address);
2179
2180         g_array_append_vals(in_param1, &param, sizeof(bluetooth_gatt_client_char_prop_info_t));
2181         g_array_append_vals(in_param2, &client_id, sizeof(int));
2182         g_array_append_vals(in_param3, &is_notify, sizeof(gboolean));
2183
2184         result = _bt_send_request(BT_BLUEZ_SERVICE,
2185                         BT_GATT_WATCH_CHARACTERISTIC,
2186                         in_param1, in_param2, in_param3, in_param4, &out_param);
2187
2188         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2189
2190         BT_INFO("Result [%d]", result);
2191         return result;
2192 }
2193
2194 BT_EXPORT_API int bluetooth_gatt_client_read_characteristic_value(
2195                 const char *address,
2196                 bt_gatt_handle_property_t *service_handle,
2197                 bt_gatt_handle_property_t *char_handle)
2198 {
2199         int result = BLUETOOTH_ERROR_NONE;
2200         bt_user_info_t *user_info;
2201         bluetooth_gatt_client_char_prop_info_t param;
2202         BT_DBG("+");
2203
2204         BT_CHECK_PARAMETER(address, return);
2205         BT_CHECK_PARAMETER(service_handle, return);
2206         BT_CHECK_PARAMETER(char_handle, return);
2207
2208         user_info = _bt_get_user_data(BT_GATT_CLIENT);
2209         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2210
2211         BT_INIT_PARAMS();
2212         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2213
2214         /* Async Function, result expected in callback from bt-service */
2215         /* Call to bt-service (sync) and send address service_handle info & char handle info  */
2216         memset(&param, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2217
2218         memcpy(&param.svc.uuid, service_handle->uuid, 16);
2219         param.svc.instance_id = service_handle->instance_id;
2220
2221         memcpy(&param.characteristic.uuid, char_handle->uuid, 16);
2222         param.characteristic.instance_id = char_handle->instance_id;
2223
2224         _bt_convert_addr_string_to_type(param.device_address.addr, address);
2225
2226         g_array_append_vals(in_param1, &param,
2227                         sizeof(bluetooth_gatt_client_char_prop_info_t));
2228
2229
2230         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_GATT_READ_CHARACTERISTIC,
2231                         in_param1, in_param2, in_param3, in_param4,
2232                         user_info->cb, user_info->user_data);
2233
2234
2235         BT_INFO("result = [%d]", result);
2236         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2237         return result;
2238 }
2239
2240 BT_EXPORT_API int bluetooth_gatt_client_read_descriptor_value(
2241                 const char *address,
2242                 bt_gatt_handle_property_t *service_handle,
2243                 bt_gatt_handle_property_t *char_handle,
2244                 bt_gatt_handle_property_t *descriptor_handle)
2245 {
2246         int result = BLUETOOTH_ERROR_NONE;
2247         bt_user_info_t *user_info;
2248         bluetooth_gatt_client_desc_prop_info_t param;
2249         BT_DBG("+");
2250
2251         BT_CHECK_PARAMETER(address, return);
2252         BT_CHECK_PARAMETER(service_handle, return);
2253         BT_CHECK_PARAMETER(char_handle, return);
2254         BT_CHECK_PARAMETER(descriptor_handle, return);
2255
2256         user_info = _bt_get_user_data(BT_GATT_CLIENT);
2257         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2258
2259         BT_INIT_PARAMS();
2260         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2261
2262         /* Async Function, result expected in callback from bt-service */
2263         memset(&param, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2264
2265         memcpy(&param.svc.uuid, service_handle->uuid, 16);
2266         param.svc.instance_id = service_handle->instance_id;
2267
2268         memcpy(&param.characteristic.uuid, char_handle->uuid, 16);
2269         param.characteristic.instance_id = char_handle->instance_id;
2270
2271         memcpy(&param.descriptor.uuid, descriptor_handle->uuid, 16);
2272         param.descriptor.instance_id = descriptor_handle->instance_id;
2273
2274         _bt_convert_addr_string_to_type(param.device_address.addr, address);
2275
2276         g_array_append_vals(in_param1, &param,
2277                         sizeof(bluetooth_gatt_client_desc_prop_info_t));
2278
2279
2280         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_GATT_READ_DESCRIPTOR_VALUE,
2281                         in_param1, in_param2, in_param3, in_param4,
2282                         user_info->cb, user_info->user_data);
2283
2284         BT_INFO("result = [%d]", result);
2285         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2286         return result;
2287 }
2288
2289 BT_EXPORT_API int bluetooth_gatt_client_write_characteristic_value_by_type(
2290                 const char *address,
2291                 bt_gatt_handle_property_t *service_handle,
2292                 bt_gatt_handle_property_t *char_handle,
2293                 bluetooth_gatt_att_data_t *data,
2294                 bluetooth_gatt_write_type_e  write_type)
2295 {
2296         int result = BLUETOOTH_ERROR_NONE;
2297         bt_user_info_t *user_info;
2298         bluetooth_gatt_client_char_prop_info_t param;
2299         BT_DBG("+");
2300
2301         BT_CHECK_PARAMETER(address, return);
2302         BT_CHECK_PARAMETER(service_handle, return);
2303         BT_CHECK_PARAMETER(char_handle, return);
2304         BT_CHECK_PARAMETER(data, return);
2305
2306         /* ASync Function, result expected in callback from bt-service */
2307         user_info = _bt_get_user_data(BT_GATT_CLIENT);
2308         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2309
2310         BT_INIT_PARAMS();
2311         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2312
2313         memset(&param, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2314
2315         memcpy(&param.svc.uuid, service_handle->uuid, 16);
2316         param.svc.instance_id = service_handle->instance_id;
2317
2318         memcpy(&param.characteristic.uuid, char_handle->uuid, 16);
2319         param.characteristic.instance_id = char_handle->instance_id;
2320
2321         _bt_convert_addr_string_to_type(param.device_address.addr, address);
2322
2323         g_array_append_vals(in_param1, &param, sizeof(bluetooth_gatt_client_char_prop_info_t));
2324         g_array_append_vals(in_param2, data, sizeof(bluetooth_gatt_att_data_t));
2325         g_array_append_vals(in_param3, &write_type, sizeof(bluetooth_gatt_write_type_e));
2326
2327         result = _bt_send_request_async(BT_BLUEZ_SERVICE,
2328                         BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE,
2329                         in_param1, in_param2, in_param3, in_param4,
2330                         user_info->cb, user_info->user_data);
2331
2332         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2333
2334         return result;
2335 }
2336
2337 BT_EXPORT_API int bluetooth_gatt_client_write_descriptor_value(
2338                 const char *address,
2339                 bt_gatt_handle_property_t *service_handle,
2340                 bt_gatt_handle_property_t *char_handle,
2341                 bt_gatt_handle_property_t *descriptor_handle,
2342                 bluetooth_gatt_att_data_t *data,
2343                 bluetooth_gatt_write_type_e  write_type)
2344 {
2345         int result = BLUETOOTH_ERROR_NONE;
2346         bt_user_info_t *user_info;
2347         bluetooth_gatt_client_desc_prop_info_t param;
2348         BT_DBG("+");
2349
2350         BT_CHECK_PARAMETER(address, return);
2351         BT_CHECK_PARAMETER(service_handle, return);
2352         BT_CHECK_PARAMETER(char_handle, return);
2353         BT_CHECK_PARAMETER(descriptor_handle, return);
2354         BT_CHECK_PARAMETER(data, return);
2355
2356         /* Async Function, result expected in callback from bt-service */
2357         user_info = _bt_get_user_data(BT_GATT_CLIENT);
2358         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2359
2360         BT_INIT_PARAMS();
2361         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2362
2363         memset(&param, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2364
2365         memcpy(&param.svc.uuid, service_handle->uuid, 16);
2366         param.svc.instance_id = service_handle->instance_id;
2367
2368         memcpy(&param.characteristic.uuid, char_handle->uuid, 16);
2369         param.characteristic.instance_id = char_handle->instance_id;
2370
2371         memcpy(&param.descriptor.uuid, descriptor_handle->uuid, 16);
2372         param.descriptor.instance_id = descriptor_handle->instance_id;
2373
2374         _bt_convert_addr_string_to_type(param.device_address.addr, address);
2375
2376         g_array_append_vals(in_param1, &param, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2377         g_array_append_vals(in_param2, data, sizeof(bluetooth_gatt_att_data_t));
2378         g_array_append_vals(in_param3, &write_type, sizeof(bluetooth_gatt_write_type_e));
2379
2380         result = _bt_send_request_async(BT_BLUEZ_SERVICE,
2381                         BT_GATT_WRITE_DESCRIPTOR_VALUE,
2382                         in_param1, in_param2, in_param3, in_param4,
2383                         user_info->cb, user_info->user_data);
2384
2385         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2386
2387         return result;
2388 }
2389
2390 BT_EXPORT_API int bluetooth_gatt_client_set_service_change_watcher(
2391                 const bluetooth_device_address_t *address, gboolean enable)
2392 {
2393         GSList *l;
2394         bluetooth_device_address_t *addr = NULL;
2395         char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
2396         int result = BLUETOOTH_ERROR_NONE;
2397
2398         BT_INFO("+");
2399
2400         BT_INIT_PARAMS();
2401         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2402
2403         g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
2404         g_array_append_vals(in_param2, &enable, sizeof(gboolean));
2405
2406
2407         _bt_convert_addr_string_to_secure_string(secure_address, (const char *)address->addr);
2408         BT_INFO("Set watcher for %s with %d", secure_address, enable);
2409
2410         if (enable == TRUE) {
2411                 if (_bluetooth_gatt_check_service_change_watcher_address(address)
2412                                 == TRUE) {
2413                         BT_INFO("The watcher is already set");
2414                         return BLUETOOTH_ERROR_NONE;
2415                 }
2416
2417                 if (service_monitor_list == NULL) {
2418                         //_bt_register_manager_subscribe_signal(TRUE);
2419
2420                         result = _bt_send_request(BT_BLUEZ_SERVICE,
2421                                         BT_GATT_WATCH_SERVICE_CHANGED_INDICATION,
2422                                         in_param1, in_param2, in_param3, in_param4, &out_param);
2423                 }
2424
2425                 if (result == BLUETOOTH_ERROR_NONE) {
2426                         addr = g_malloc0(sizeof(bluetooth_device_address_t));
2427                         memcpy(addr, address, sizeof(bluetooth_device_address_t));
2428
2429                         service_monitor_list =
2430                                 g_slist_append(service_monitor_list, addr);
2431                 }
2432         } else {
2433                 for (l = service_monitor_list; l != NULL; l = l->next) {
2434                         addr = l->data;
2435
2436                         if (!memcmp(address, addr,
2437                                                 sizeof(bluetooth_device_address_t))) {
2438                                 service_monitor_list =
2439                                         g_slist_remove(service_monitor_list, addr);
2440                                 g_free(addr);
2441                                 break;
2442                         }
2443                 }
2444
2445                 if (service_monitor_list == NULL) {
2446                         //_bt_register_manager_subscribe_signal(FALSE);
2447                         result = _bt_send_request(BT_BLUEZ_SERVICE,
2448                                         BT_GATT_WATCH_SERVICE_CHANGED_INDICATION,
2449                                         in_param1, in_param2, in_param3, in_param4, &out_param);
2450
2451                 }
2452         }
2453
2454         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2455         return result;
2456 }
2457
2458 BT_EXPORT_API int bluetooth_gatt_client_deinit(
2459                 int client_id)
2460 {
2461         int result;
2462         int *count;
2463         bt_event_info_t *event_info;
2464
2465         BT_CHECK_ENABLED(return);
2466
2467         BT_INFO("GATT Client Deinit Client instance ID [%d]", client_id);
2468
2469         BT_INIT_PARAMS();
2470         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2471
2472         g_array_append_vals(in_param1, &client_id, sizeof(int));
2473
2474         /* Unregistration MUST NOT FAIL */
2475         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_UNREGISTER,
2476                         in_param1, in_param2, in_param3, in_param4, &out_param);
2477
2478         if (result != BLUETOOTH_ERROR_NONE)
2479                 BT_INFO("GATT Client Unregistration failed result [%d]", result);
2480         else
2481                 BT_INFO("GATT Client Unregistration successful");
2482
2483         /* Unregister event handler if this is the only instance */
2484         event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
2485
2486         if (event_info) {
2487                 count = (int*)event_info->user_data;
2488
2489                 BT_INFO("Total num of GATT client instances [%d]", *count);
2490
2491                 if (*count == 1) {
2492                         BT_INFO("Currently only one GATT client instance, so remove it and unregister GATT client events");
2493                         _bt_unregister_event(BT_GATT_CLIENT_EVENT);
2494                         _bt_set_user_data(BT_GATT_CLIENT, NULL, NULL);
2495                 } else
2496                         *count -= 1;
2497         } else
2498                 BT_ERR("Impossible that client is created, but no event handler is registered!!!");
2499
2500         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2501         return result;
2502 }
2503
2504 #endif