Coverity Fixes in BTAPI and BTHAL
[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_DBG("+");
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         if (!g_strcmp0(permission, "broadcast"))
565                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
566         else if (!g_strcmp0(permission, "read"))
567                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
568         else if (!g_strcmp0(permission, "write-without-response"))
569                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
570         else if (!g_strcmp0(permission, "write"))
571                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
572         else if (!g_strcmp0(permission, "notify"))
573                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
574         else if (!g_strcmp0(permission, "indicate"))
575                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
576         else if (!g_strcmp0(permission, "authenticated-signed-writes"))
577                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
578         else if (!g_strcmp0(permission, "reliable-write"))
579                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
580         else if (!g_strcmp0(permission, "writable-auxiliaries"))
581                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
582         else if (!g_strcmp0(permission, "encrypt-read"))
583                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
584         else if (!g_strcmp0(permission, "encrypt-write"))
585                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
586         else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
587                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
588         else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
589                 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
590
591         return ret;
592 }
593
594 static void __convert_permission_flag_to_str(unsigned int permission)
595 {
596         char perm[200] = { 0, };
597
598         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST)
599                 g_strlcat(perm, "broadcast ", sizeof(perm));
600         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ)
601                 g_strlcat(perm, "read ", sizeof(perm));
602         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE)
603                 g_strlcat(perm, "write-without-response ", sizeof(perm));
604         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE)
605                 g_strlcat(perm, "write ", sizeof(perm));
606         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY)
607                 g_strlcat(perm, "notify ", sizeof(perm));
608         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE)
609                 g_strlcat(perm, "indicate ", sizeof(perm));
610         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE)
611                 g_strlcat(perm, "authenticated-signed-writes ", sizeof(perm));
612         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE)
613                 g_strlcat(perm, "reliable-write ", sizeof(perm));
614         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES)
615                 g_strlcat(perm, "writable-auxiliaries ", sizeof(perm));
616         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ)
617                 g_strlcat(perm, "encrypt-read ", sizeof(perm));
618         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE)
619                 g_strlcat(perm, "encrypt-write ", sizeof(perm));
620         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ)
621                 g_strlcat(perm, "encrypt-authenticated-read ", sizeof(perm));
622         if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE)
623                 g_strlcat(perm, "encrypt-authenticated-write ", sizeof(perm));
624
625         BT_INFO("permission [0x%04x] : %s\n", permission, perm);
626         return;
627 }
628
629 BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
630                 const char *char_handle, bt_gatt_char_property_t *characteristic)
631 {
632         GDBusProxy *properties_proxy = NULL;
633         GError *error = NULL;
634         GVariant *value = NULL;
635         GVariant *result = NULL;
636         GByteArray *gb_array = NULL;
637         GPtrArray *gp_array  = NULL ;
638         GDBusConnection *g_conn;
639         guint8 char_value;
640         const gchar *key;
641         gchar* permission;
642         char *char_desc_handle = NULL;
643         gsize len;
644         GVariantIter *property_iter;
645         GVariantIter *char_value_iter;
646         GVariantIter *char_perm_iter;
647         GVariantIter *char_desc_iter;
648
649         BT_CHECK_PARAMETER(char_handle, return);
650         BT_CHECK_PARAMETER(characteristic, return);
651
652         BT_CHECK_ENABLED(return);
653
654         g_conn = _bt_gdbus_get_system_gconn();
655         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
656
657         properties_proxy = g_dbus_proxy_new_sync(g_conn,
658                         G_DBUS_PROXY_FLAGS_NONE, NULL,
659                         BT_BLUEZ_NAME,
660                         char_handle,
661                         BT_PROPERTIES_INTERFACE,
662                         NULL, &error);
663
664         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
665
666         result = g_dbus_proxy_call_sync(properties_proxy,
667                                 "GetAll",
668                                         g_variant_new("(s)", GATT_CHAR_INTERFACE),
669                                 G_DBUS_CALL_FLAGS_NONE,
670                                 -1,
671                                 NULL,
672                                 &error);
673
674         if (!result) {
675                 if (error != NULL) {
676                         BT_ERR("Fail to get properties (Error: %s)", error->message);
677                         g_clear_error(&error);
678                 } else
679                         BT_ERR("Fail to get properties");
680                 g_object_unref(properties_proxy);
681                 return BLUETOOTH_ERROR_INTERNAL;
682         }
683
684         g_variant_get(result, "(a{sv})", &property_iter);
685
686         memset(characteristic, 0, sizeof(bt_gatt_char_property_t));
687         characteristic->handle = g_strdup(char_handle);
688
689         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
690                 if (!g_strcmp0(key, "UUID")) {
691                         char *name = NULL;
692                         characteristic->uuid = g_variant_dup_string(value, &len);
693                         bluetooth_get_uuid_name(characteristic->uuid, &name);
694                         BT_INFO("%s %s [%s]", char_handle + 37, characteristic->uuid, name);
695                         g_free(name);
696                 } else if (!g_strcmp0(key, "Value")) {
697                         gb_array = g_byte_array_new();
698                         g_variant_get(value, "ay", &char_value_iter);
699                         while (g_variant_iter_loop(char_value_iter, "y",  &char_value)) {
700                         //      BT_DBG("value of char = %d",char_value);
701                                 g_byte_array_append(gb_array, &char_value, 1);
702                         }
703                         g_variant_iter_free(char_value_iter);
704
705                         if (gb_array->len != 0) {
706                                 characteristic->val = g_malloc0(gb_array->len *
707                                                                 sizeof(unsigned char));
708                                 memcpy(characteristic->val, gb_array->data, gb_array->len);
709                         }
710                         characteristic->val_len = gb_array->len;
711                         g_byte_array_free(gb_array, TRUE);
712                 } else if (!g_strcmp0(key, "Flags")) {
713                         g_variant_get(value, "as", &char_perm_iter);
714                         characteristic->permission = 0x00;
715
716                         while (g_variant_iter_loop(char_perm_iter, "s", &permission))
717                                 characteristic->permission |= __get_permission_flag(permission);
718                         __convert_permission_flag_to_str(characteristic->permission);
719
720                         g_variant_iter_free(char_perm_iter);
721                 } else if (!g_strcmp0(key, "Descriptors")) {
722                         g_variant_get(value, "ao", &char_desc_iter);
723                         gp_array = g_ptr_array_new();
724                         while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle))
725                                 g_ptr_array_add(gp_array, (gpointer)char_desc_handle);
726
727                         g_variant_iter_free(char_desc_iter);
728                         if (gp_array->len != 0) {
729                                 characteristic->char_desc_handle.count = gp_array->len;
730                                 characteristic->char_desc_handle.handle =
731                                                 __get_string_array_from_gptr_array(gp_array);
732                         }
733                         g_ptr_array_free(gp_array, TRUE);
734                 }
735         }
736
737         g_variant_iter_free(property_iter);
738         g_variant_unref(result);
739         g_object_unref(properties_proxy);
740
741         return BLUETOOTH_ERROR_NONE;
742 }
743
744 void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy,
745                         GAsyncResult *res, gpointer user_data)
746 {
747         GVariant *value;
748         GVariantIter *char_iter;
749         char *char_handle;
750         GError *error = NULL;
751         bt_user_info_t *user_info;
752         int ret = BLUETOOTH_ERROR_INTERNAL;
753         bt_gatt_char_property_t characteristic;
754
755         user_info = _bt_get_user_data(BT_COMMON);
756
757         value = g_dbus_proxy_call_finish(proxy, res, &error);
758
759         if (value == NULL) {
760                 if (error != NULL) {
761                         BT_ERR("Get service characteristics failed\n errCode[%x],"
762                                         "message[%s]\n", error->code, error->message);
763                         g_clear_error(&error);
764                 } else {
765                         BT_ERR("Get service characteristics failed\n");
766                 }
767                 if (user_info) {
768                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
769                                 BLUETOOTH_ERROR_INTERNAL, NULL,
770                                 user_info->cb, user_info->user_data);
771                 }
772                 g_object_unref(proxy);
773                 g_free(user_data);
774                 return;
775         }
776
777         g_variant_get(value, "(ao)", &char_iter);
778
779         while (g_variant_iter_loop(char_iter, "&o",  &char_handle)) {
780                 if (!char_handle)
781                         continue;
782                 ret = bluetooth_gatt_get_characteristics_property(char_handle,
783                                 &characteristic);
784
785                 if (ret != BLUETOOTH_ERROR_NONE) {
786                         BT_ERR("Get characteristic property failed(0x%08x)", ret);
787                 } else {
788                         if (g_strstr_len(characteristic.uuid, -1, user_data)) {
789                                 ret = BLUETOOTH_ERROR_NONE;
790                                 break;
791                         }
792                 }
793                 bluetooth_gatt_free_char_property(&characteristic);
794         }
795
796         if (user_info) {
797                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret,
798                                 &characteristic, user_info->cb, user_info->user_data);
799         }
800
801         bluetooth_gatt_free_char_property(&characteristic);
802         g_variant_iter_free(char_iter);
803         g_variant_unref(value);
804         g_free(user_data);
805 }
806
807 BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
808                                                 const char *char_uuid)
809 {
810         GDBusProxy *properties_proxy = NULL;
811         GDBusConnection *g_conn;
812         GError *error = NULL;
813         char *uuid;
814
815         BT_CHECK_PARAMETER(service_handle, return);
816         BT_CHECK_PARAMETER(char_uuid, return);
817         BT_CHECK_ENABLED(return);
818
819         g_conn = _bt_gdbus_get_system_gconn();
820         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
821
822         properties_proxy = g_dbus_proxy_new_sync(g_conn,
823                         G_DBUS_PROXY_FLAGS_NONE, NULL,
824                         BT_BLUEZ_NAME,
825                         service_handle,
826                         BT_PROPERTIES_INTERFACE,
827                         NULL, &error);
828
829         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
830
831         uuid = g_strdup(char_uuid);
832         g_dbus_proxy_call(properties_proxy,
833                         "Get",
834                         g_variant_new("(ss)",
835                                 GATT_SERV_INTERFACE, "Characteristics"),
836                         G_DBUS_CALL_FLAGS_NONE,
837                         -1,
838                         NULL,
839                         (GAsyncReadyCallback)bluetooth_gatt_get_char_from_uuid_cb,
840                         (gpointer)uuid);
841
842         return BLUETOOTH_ERROR_NONE;
843 }
844
845 BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
846                 const char *descriptor_handle, bt_gatt_char_descriptor_property_t *descriptor)
847 {
848         GDBusProxy *properties_proxy = NULL;
849         GError *error = NULL;
850         GDBusConnection *g_conn;
851         GVariant *result = NULL;
852         GVariantIter *property_iter;
853         const gchar *key;
854         guint8 char_value;
855         gsize len;
856         GVariant *value = NULL;
857         GByteArray *gb_array = NULL;
858         GVariantIter *desc_value_iter;
859
860         BT_CHECK_PARAMETER(descriptor_handle, return);
861         BT_CHECK_PARAMETER(descriptor, return);
862
863         BT_CHECK_ENABLED(return);
864
865         g_conn = _bt_gdbus_get_system_gconn();
866         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
867
868         properties_proxy = g_dbus_proxy_new_sync(g_conn,
869                         G_DBUS_PROXY_FLAGS_NONE, NULL,
870                         BT_BLUEZ_NAME,
871                         descriptor_handle,
872                         BT_PROPERTIES_INTERFACE,
873                         NULL, &error);
874
875         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
876
877         result = g_dbus_proxy_call_sync(properties_proxy,
878                                 "GetAll",
879                                         g_variant_new("(s)", GATT_DESC_INTERFACE),
880                                 G_DBUS_CALL_FLAGS_NONE,
881                                 -1,
882                                 NULL,
883                                 &error);
884
885         if (!result) {
886                 if (error != NULL) {
887                         BT_ERR("Fail to get properties (Error: %s)", error->message);
888                         g_clear_error(&error);
889                 } else
890                         BT_ERR("Fail to get properties");
891                 g_object_unref(properties_proxy);
892                 return BLUETOOTH_ERROR_INTERNAL;
893         }
894
895         g_variant_get(result, "(a{sv})", &property_iter);
896
897         memset(descriptor, 0, sizeof(bt_gatt_char_descriptor_property_t));
898         descriptor->handle = g_strdup(descriptor_handle);
899
900         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
901                 if (!g_strcmp0(key, "UUID")) {
902                         char *name = NULL;
903                         descriptor->uuid = g_variant_dup_string(value, &len);
904                         bluetooth_get_uuid_name(descriptor->uuid, &name);
905                         BT_INFO("Descriptor : %s [%s]", descriptor->uuid, name);
906                         g_free(name);
907                 } else if (!g_strcmp0(key, "Value")) {
908                         gb_array = g_byte_array_new();
909                         g_variant_get(value, "ay", &desc_value_iter);
910                         while (g_variant_iter_loop(desc_value_iter, "y",  &char_value)) {
911                                 BT_DBG("value of descriptor = %d", char_value);
912                                 g_byte_array_append(gb_array, &char_value, 1);
913                         }
914                         g_variant_iter_free(desc_value_iter);
915
916                         if (gb_array->len != 0) {
917                                 descriptor->val = g_malloc0(gb_array->len *
918                                                                 sizeof(unsigned char));
919                                 memcpy(descriptor->val, gb_array->data, gb_array->len);
920                         }
921                         descriptor->val_len = gb_array->len;
922                         g_byte_array_free(gb_array, TRUE);
923                 }
924         }
925
926         g_variant_iter_free(property_iter);
927         g_variant_unref(result);
928         g_object_unref(properties_proxy);
929
930         return BLUETOOTH_ERROR_NONE;
931 }
932
933 static int __bluetooth_get_att_error_code(GError *error, char *handle)
934 {
935         int att_ecode = 0;
936         int len;
937         char *str = NULL;
938
939         BT_ERR("Error : %s [%s]", error->message, handle + 15);
940         str = g_strrstr(error->message, "ATT error: 0x");
941         if (str) {
942                 len = strlen(str);
943                 att_ecode =  g_ascii_xdigit_value(str[len - 2]) << 4;
944                 att_ecode += g_ascii_xdigit_value(str[len - 1]);
945         } else
946                 return BLUETOOTH_ATT_ERROR_INTERNAL;
947
948         switch (att_ecode) {
949         case BLUETOOTH_ATT_ERROR_READ_NOT_PERMITTED:
950                 BT_ERR("Read not permitted");
951                 break;
952         case BLUETOOTH_ATT_ERROR_WRITE_NOT_PERMITTED:
953                 BT_ERR("Write not permitted");
954                 break;
955         case BLUETOOTH_ATT_ERROR_AUTHENTICATION:
956         case BLUETOOTH_ATT_ERROR_INSUFFICIENT_ENCRYPTION:
957         case BLUETOOTH_ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE:
958                 BT_ERR("Not paired");
959                 break;
960         case BLUETOOTH_ATT_ERROR_INVALID_OFFSET:
961                 BT_ERR("Invalid offset");
962                 break;
963         case BLUETOOTH_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN:
964                 BT_ERR("Invalid Length");
965                 break;
966         case BLUETOOTH_ATT_ERROR_AUTHORIZATION:
967                 BT_ERR("Operation not Authorized");
968                 break;
969         default:
970                 BT_ERR("default ecode");
971                 break;
972         }
973
974         if (att_ecode >= 0x80 && att_ecode <= 0x9F)
975                 BT_ERR("Application error");
976
977         return att_ecode;
978 }
979
980 static void __bluetooth_internal_read_cb(GObject *source_object,
981                                          GAsyncResult *res, gpointer user_data)
982 {
983         GError *error = NULL;
984         GDBusConnection *system_gconn = NULL;
985         GVariant *value;
986         bt_user_info_t *user_info;
987         GVariantIter *iter;
988         GByteArray *gp_byte_array = NULL;
989         guint8 g_byte;
990         int att_ecode = 0;
991         bt_gatt_resp_data_t *resp_data = user_data;
992
993         BT_DBG("+");
994
995         system_gconn = _bt_gdbus_get_system_gconn();
996         value = g_dbus_connection_call_finish(system_gconn, res, &error);
997
998         user_info = _bt_get_user_data(BT_COMMON);
999         if (!user_info) {
1000                 if (error) {
1001                         BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
1002                         g_clear_error(&error);
1003                         g_free(resp_data);
1004                         return;
1005                 }
1006                 g_free(resp_data);
1007                 g_variant_unref(value);
1008                 return;
1009         }
1010
1011         if (error) {
1012                 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
1013                 g_clear_error(&error);
1014
1015                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
1016                                     att_ecode, resp_data,
1017                                     user_info->cb, user_info->user_data);
1018                 g_free(resp_data);
1019                 return;
1020         }
1021
1022         gp_byte_array = g_byte_array_new();
1023         g_variant_get(value, "(ay)", &iter);
1024
1025         while (g_variant_iter_loop(iter, "y", &g_byte))
1026                 g_byte_array_append(gp_byte_array, &g_byte, 1);
1027
1028         if (gp_byte_array->len != 0) {
1029                 resp_data->len = gp_byte_array->len;
1030                 resp_data->value = gp_byte_array->data;
1031         }
1032
1033         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
1034                             BLUETOOTH_ATT_ERROR_NONE, resp_data,
1035                             user_info->cb, user_info->user_data);
1036         g_free(resp_data);
1037
1038         g_byte_array_free(gp_byte_array, TRUE);
1039         g_variant_iter_free(iter);
1040         g_variant_unref(value);
1041
1042         BT_DBG("-");
1043 }
1044
1045 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *chr,
1046                                                            gpointer user_data)
1047 {
1048         GDBusConnection *conn;
1049         bt_gatt_resp_data_t *resp_data;
1050         GVariantBuilder *builder = NULL;
1051         guint16 offset = 0;
1052
1053         BT_CHECK_PARAMETER(chr, return);
1054         BT_CHECK_ENABLED(return);
1055
1056         conn = _bt_gdbus_get_system_gconn();
1057         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1058
1059         resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1060         resp_data->user_data = user_data;
1061         resp_data->handle = (char *)chr;
1062
1063         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1064
1065         /*offset*/
1066         g_variant_builder_add(builder, "{sv}", "offset",
1067                 g_variant_new("q", offset));
1068
1069         /* Device Object path*/
1070 //      g_variant_builder_add(builder, "{sv}", "device",
1071 //      g_variant_new_object("o", NULL));
1072
1073         g_dbus_connection_call(conn, BT_BLUEZ_NAME, chr, GATT_CHAR_INTERFACE,
1074                         "ReadValue", g_variant_new("(a{sv})", builder),
1075                         G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1076                         (GAsyncReadyCallback)__bluetooth_internal_read_cb,
1077                         (gpointer)resp_data);
1078         g_variant_builder_unref(builder);
1079
1080         return BLUETOOTH_ERROR_NONE;
1081 }
1082
1083 static void __bluetooth_internal_write_cb(GObject *source_object,
1084                                           GAsyncResult *res, gpointer user_data)
1085 {
1086         GError *error = NULL;
1087         GDBusConnection *system_gconn = NULL;
1088         bt_user_info_t *user_info;
1089         GVariant *value;
1090         int att_ecode = 0;
1091         bt_gatt_resp_data_t *resp_data = user_data;
1092
1093         system_gconn = _bt_gdbus_get_system_gconn();
1094         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1095
1096         user_info = _bt_get_user_data(BT_COMMON);
1097         if (!user_info) {
1098                 if (error) {
1099                         BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
1100                         g_clear_error(&error);
1101                         g_free(resp_data);
1102                         return;
1103                 }
1104                 g_free(resp_data);
1105                 g_variant_unref(value);
1106                 return;
1107         }
1108
1109         if (error) {
1110                 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
1111                 g_clear_error(&error);
1112
1113                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
1114                                 att_ecode, resp_data,
1115                                 user_info->cb, user_info->user_data);
1116                 g_free(resp_data);
1117                 return;
1118         }
1119
1120         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
1121                         BLUETOOTH_ATT_ERROR_NONE, resp_data,
1122                         user_info->cb, user_info->user_data);
1123         g_free(resp_data);
1124
1125         g_variant_unref(value);
1126         return;
1127 }
1128
1129 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
1130                 const char *char_handle, const guint8 *value, int length)
1131 {
1132         GVariant *val, *options;
1133         GVariantBuilder *builder1;
1134         GVariantBuilder *builder2;
1135         GError *error = NULL;
1136         GDBusConnection *conn;
1137         int i = 0;
1138         guint16 offset = 0;
1139
1140         BT_DBG("+");
1141         BT_CHECK_PARAMETER(char_handle, return);
1142         BT_CHECK_PARAMETER(value, return);
1143         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1144         BT_CHECK_ENABLED(return);
1145
1146         conn = _bt_gdbus_get_system_gconn();
1147         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1148
1149         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1150         for (i = 0; i < length; i++)
1151                 g_variant_builder_add(builder1, "y", value[i]);
1152
1153         val = g_variant_new("ay", builder1);
1154
1155         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1156         /*offset*/
1157         g_variant_builder_add(builder2, "{sv}", "offset",
1158                                 g_variant_new_uint16(offset));
1159
1160         /* Device Object path*/
1161 //      g_variant_builder_add(builder2, "{sv}", "device",
1162 //      g_variant_new_object("o", NULL));
1163
1164         options = g_variant_new("a{sv}", builder2);
1165
1166         g_dbus_connection_call(conn,
1167                                 BT_BLUEZ_NAME,
1168                                 char_handle,
1169                                 GATT_CHAR_INTERFACE,
1170                                 "WriteValue",
1171                                 g_variant_new("(@ay@a{sv})",
1172                                 val, options),
1173                                 NULL,
1174                                 G_DBUS_CALL_FLAGS_NONE,
1175                                 -1, NULL,
1176                                 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1177                                 NULL);
1178
1179
1180         if (error) {
1181                 BT_ERR("Set value Failed: %s", error->message);
1182                 g_clear_error(&error);
1183                 g_variant_builder_unref(builder1);
1184                 return BLUETOOTH_ERROR_INTERNAL;
1185         }
1186         g_variant_builder_unref(builder1);
1187         g_variant_builder_unref(builder2);
1188
1189         BT_DBG("-");
1190         return BLUETOOTH_ERROR_NONE;
1191 }
1192
1193 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
1194                         const char *chr, const guint8 *value, int length,
1195                         guint8 write_type, gpointer user_data)
1196 {
1197         GVariant *val, *options;
1198         GVariantBuilder *builder1;
1199         GVariantBuilder *builder2;
1200         GDBusConnection *conn;
1201         guint16 offset = 0;
1202         int i = 0;
1203         int ret = BLUETOOTH_ERROR_NONE;
1204         bt_gatt_resp_data_t *resp_data;
1205
1206         BT_CHECK_PARAMETER(chr, return);
1207         BT_CHECK_PARAMETER(value, return);
1208         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1209         BT_CHECK_ENABLED_INTERNAL(return);
1210
1211         conn = _bt_gdbus_get_system_gconn();
1212         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1213
1214         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1215
1216         for (i = 0; i < length; i++)
1217                 g_variant_builder_add(builder1, "y", value[i]);
1218
1219         val = g_variant_new("ay", builder1);
1220
1221         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1222         /*offset*/
1223         g_variant_builder_add(builder2, "{sv}", "offset",
1224                         g_variant_new_uint16(offset));
1225
1226         /* Device Object path*/
1227 //      g_variant_builder_add(builder2, "{sv}", "device",
1228 //      g_variant_new_object("o", NULL));
1229
1230         options = g_variant_new("a{sv}", builder2);
1231
1232         resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1233         resp_data->user_data = user_data;
1234         resp_data->handle = (char *)chr;
1235
1236         g_dbus_connection_call(conn, BT_BLUEZ_NAME, chr, GATT_CHAR_INTERFACE,
1237                         "WriteValuebyType",
1238                         g_variant_new("(y@ay@a{sv})", write_type, val, options),
1239                         NULL,
1240                         G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1241                         (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1242                         (gpointer)resp_data);
1243
1244         g_variant_builder_unref(builder1);
1245         g_variant_builder_unref(builder2);
1246
1247         return ret;
1248 }
1249
1250 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
1251                         const char *char_handle, const guint8 *value, int length)
1252 {
1253         GVariant *val, *options;
1254         GDBusConnection *conn;
1255         GVariantBuilder *builder1;
1256         GVariantBuilder *builder2;
1257         guint offset = 0;
1258         int i;
1259
1260         BT_DBG("+");
1261         BT_CHECK_PARAMETER(char_handle, return);
1262         BT_CHECK_PARAMETER(value, return);
1263         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1264         BT_CHECK_ENABLED(return);
1265
1266         conn = _bt_gdbus_get_system_gconn();
1267         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1268
1269         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1270
1271         for (i = 0; i < length; i++) {
1272                 g_variant_builder_add(builder1, "y", value[i]);
1273                 BT_DBG("value [] = %d", value[i]);
1274         }
1275
1276         val = g_variant_new("ay", builder1);
1277
1278         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1279         /*offset*/
1280         g_variant_builder_add(builder2, "{sv}", "offset",
1281                                 g_variant_new_uint16(offset));
1282
1283         /* Device Object path*/
1284 //      g_variant_builder_add(builder2, "{sv}", "device",
1285 //      g_variant_new_object("o", NULL));
1286
1287         options = g_variant_new("a{sv}", builder2);
1288
1289         g_dbus_connection_call(conn,
1290                                 BT_BLUEZ_NAME,
1291                                 char_handle,
1292                                 GATT_CHAR_INTERFACE,
1293                                 "WriteValue",
1294                                 g_variant_new("(@ay@a{sv})",
1295                                 val, options),
1296                                 NULL,
1297                                 G_DBUS_CALL_FLAGS_NONE,
1298                                 -1, NULL,
1299                                 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1300                                 NULL);
1301
1302         g_variant_builder_unref(builder1);
1303         g_variant_builder_unref(builder2);
1304
1305         BT_DBG("-");
1306         return BLUETOOTH_ERROR_NONE;
1307 }
1308
1309 static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
1310                         bt_gatt_char_property_t *characteristic)
1311 {
1312         BT_DBG("+");
1313         GDBusProxy *properties_proxy = NULL;
1314         GError *error = NULL;
1315         GVariant *value = NULL;
1316         GVariant *result = NULL;
1317         GDBusConnection *g_conn;
1318         int i, ret = BLUETOOTH_ERROR_NONE;
1319         const char *uuid = NULL;
1320         gsize len = 0;
1321         GVariantIter *desc_value_iter, *property_iter;
1322         const gchar *key;
1323         char_descriptor_type_t desc_type = TYPE_NONE;
1324
1325         g_conn = _bt_gdbus_get_system_gconn();
1326         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1327
1328         properties_proxy = g_dbus_proxy_new_sync(g_conn,
1329                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1330                         BT_BLUEZ_NAME,
1331                         char_handle,
1332                         BT_PROPERTIES_INTERFACE,
1333                         NULL, &error);
1334
1335         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1336
1337         result = g_dbus_proxy_call_sync(properties_proxy,
1338                                 "GetAll",
1339                                 g_variant_new("(s)", GATT_DESC_INTERFACE),
1340                                 G_DBUS_CALL_FLAGS_NONE,
1341                                 -1,
1342                                 NULL,
1343                                 &error);
1344
1345         if (!result) {
1346                 if (error != NULL) {
1347                         BT_ERR("Fail to get properties (Error: %s)", error->message);
1348                         g_clear_error(&error);
1349                 } else
1350                         BT_ERR("Fail to get properties");
1351                 g_object_unref(properties_proxy);
1352                 return BLUETOOTH_ERROR_INTERNAL;
1353         }
1354         g_variant_get(result, "(a{sv})", &property_iter);
1355         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1356                 if (!g_strcmp0(key, "UUID")) {
1357                         uuid = g_variant_get_string(value, &len);
1358                         if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
1359                                 BT_DBG("GATT_USER_DESC_UUID");
1360                                 desc_type = USER_DESC;
1361                         } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) {
1362                                 BT_DBG("GATT_CHAR_FORMAT");
1363                                 desc_type = CHAR_FORMAT;
1364                         } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) {
1365                                 BT_DBG("GATT_CHAR_CLIENT_CONF");
1366                                 desc_type = CLIENT_CONF;
1367                         } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) {
1368                                 BT_DBG("GATT_CHAR_SERVER_CONF");
1369                                 desc_type = SERVER_CONF;
1370                         } else {
1371                                 BT_DBG("descriptor uuid = %s", uuid);
1372                         }
1373                 } else if (!g_strcmp0(key, "Value")) {
1374                         switch (desc_type) {
1375                         case CHAR_FORMAT:
1376                                 BT_DBG("Format descriptor");
1377                                 g_variant_get(value, "(yyqyq)",
1378                                                 &(characteristic->format.format),
1379                                                 &(characteristic->format.exponent),
1380                                                 &(characteristic->format.unit),
1381                                                 &(characteristic->format.name_space),
1382                                                 &(characteristic->format.description));
1383                                 break;
1384                         case USER_DESC:
1385                                 BT_DBG("User descriptor");
1386                                 g_variant_get(value, "ay", &desc_value_iter);
1387                                 len = g_variant_get_size((GVariant *)desc_value_iter);
1388
1389                                 if (len > 0)
1390                                         characteristic->description = (char *)g_malloc0(len + 1);
1391
1392                                 for (i = 0; i < len; i++) {
1393                                         g_variant_iter_loop(desc_value_iter, "y",
1394                                                 &characteristic->description[i]);
1395                                         BT_DBG("description = %s", characteristic->description);
1396                                 }
1397                                 g_variant_iter_free(desc_value_iter);
1398                                 break;
1399                         case CLIENT_CONF:
1400                                 BT_DBG(" CLIENT_CONF");
1401                                 break;
1402                         case SERVER_CONF:
1403                                 BT_DBG(" SERVER_CONF");
1404                                 break;
1405                         default:
1406                                 break;
1407                         }
1408                 }
1409         }
1410
1411         g_variant_iter_free(property_iter);
1412         g_variant_unref(result);
1413         g_object_unref(properties_proxy);
1414
1415         BT_DBG("-");
1416         return ret;
1417 }
1418
1419
1420 static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
1421                         GAsyncResult *res, gpointer user_data)
1422 {
1423         BT_DBG("+");
1424         GVariant *value;
1425         GVariant        *char_value;
1426         GVariantIter *char_iter;
1427         char *char_handle;
1428         GError *error = NULL;
1429         bt_user_info_t *user_info;
1430         bt_gatt_char_property_t characteristic = {0, };
1431         int ret = BLUETOOTH_ERROR_INTERNAL;
1432
1433         user_info = _bt_get_user_data(BT_COMMON);
1434
1435         value = g_dbus_proxy_call_finish(proxy, res, &error);
1436         characteristic.handle = user_data;
1437
1438         if (value == NULL) {
1439                 if (error != NULL) {
1440                         BT_ERR("Get characteristic descriptor failed\n errCode[%x],"
1441                                         "message[%s]\n", error->code, error->message);
1442                         g_clear_error(&error);
1443                 } else {
1444                         BT_ERR("Get characteristic descriptor failed\n");
1445                 }
1446                 if (user_info) {
1447                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1448                                 BLUETOOTH_ERROR_INTERNAL, NULL,
1449                                 user_info->cb, user_info->user_data);
1450                 }
1451                 g_free(characteristic.handle);
1452                 g_object_unref(proxy);
1453                 return;
1454         }
1455
1456         g_variant_get(value, "(v)", &char_value);
1457         g_variant_get(char_value, "ao", &char_iter);
1458
1459         while (g_variant_iter_loop(char_iter, "&o",  &char_handle)) {
1460                 BT_DBG("object path of descriptor = %s", char_handle);
1461                 if (char_handle) {
1462                         ret = __bluetooth_gatt_descriptor_iter(char_handle,
1463                                                 &characteristic);
1464                         BT_DBG("Descriptor read status [%d]", ret);
1465                 }
1466         }
1467
1468         if (user_info) {
1469                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1470                                 ret, &characteristic, user_info->cb, user_info->user_data);
1471         }
1472         bluetooth_gatt_free_char_property(&characteristic);
1473
1474         g_variant_iter_free(char_iter);
1475         g_variant_unref(value);
1476         BT_DBG("-");
1477 }
1478
1479 BT_EXPORT_API int bluetooth_gatt_discover_characteristic_descriptor(
1480                         const char *characteristic_handle)
1481 {
1482         GDBusProxy *properties_proxy = NULL;
1483         GDBusConnection *g_conn;
1484         char *handle;
1485         GError *error = NULL;
1486
1487         BT_CHECK_PARAMETER(characteristic_handle, return);
1488         BT_CHECK_ENABLED(return);
1489
1490         g_conn = _bt_gdbus_get_system_gconn();
1491         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1492
1493         properties_proxy = g_dbus_proxy_new_sync(g_conn,
1494                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1495                         BT_BLUEZ_NAME,
1496                         characteristic_handle,
1497                         BT_PROPERTIES_INTERFACE,
1498                         NULL, &error);
1499
1500         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1501
1502         handle = g_strdup(characteristic_handle);
1503         g_dbus_proxy_call(properties_proxy,
1504                         "Get",
1505                         g_variant_new("(ss)",
1506                                 GATT_CHAR_INTERFACE, "Descriptors"),
1507                         G_DBUS_CALL_FLAGS_NONE,
1508                         -1, NULL,
1509                         (GAsyncReadyCallback)bluetooth_gatt_get_char_desc_cb,
1510                         (gpointer)handle);
1511
1512         return BLUETOOTH_ERROR_NONE;
1513 }
1514
1515 static void __bluetooth_internal_read_desc_cb(GObject *source_object,
1516                         GAsyncResult *res,
1517                         gpointer user_data)
1518 {
1519         GError *error = NULL;
1520         GDBusConnection *system_gconn = NULL;
1521         GVariant *value;
1522         bt_user_info_t *user_info;
1523         GByteArray *gp_byte_array = NULL;
1524         GVariantIter *iter;
1525         guint8 g_byte;
1526         int att_ecode = 0;
1527         bt_gatt_resp_data_t *resp_data = user_data;
1528
1529         BT_DBG("+");
1530
1531         system_gconn = _bt_gdbus_get_system_gconn();
1532         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1533
1534         user_info = _bt_get_user_data(BT_COMMON);
1535         if (!user_info) {
1536                 if (error) {
1537                         BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
1538                         g_clear_error(&error);
1539                         g_free(resp_data);
1540                         return;
1541                 }
1542                 g_free(resp_data);
1543                 g_variant_unref(value);
1544                 return;
1545         }
1546
1547         if (error) {
1548                 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
1549                 g_clear_error(&error);
1550
1551                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1552                                 att_ecode, resp_data,
1553                                 user_info->cb, user_info->user_data);
1554                 g_free(resp_data);
1555                 return;
1556         }
1557
1558         gp_byte_array = g_byte_array_new();
1559         g_variant_get(value, "(ay)", &iter);
1560
1561         while (g_variant_iter_loop(iter, "y", &g_byte))
1562                 g_byte_array_append(gp_byte_array, &g_byte, 1);
1563
1564         if (gp_byte_array->len != 0) {
1565                 resp_data->len = gp_byte_array->len;
1566                 resp_data->value = gp_byte_array->data;
1567         }
1568
1569         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1570                         BLUETOOTH_ATT_ERROR_NONE, resp_data,
1571                         user_info->cb, user_info->user_data);
1572         g_free(resp_data);
1573
1574
1575         g_byte_array_free(gp_byte_array, TRUE);
1576         g_variant_iter_free(iter);
1577         g_variant_unref(value);
1578
1579         BT_DBG("-");
1580 }
1581
1582 BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *desc,
1583                                                        gpointer user_data)
1584 {
1585         GDBusConnection *conn;
1586         GVariantBuilder *builder;
1587         guint offset = 0;
1588         bt_gatt_resp_data_t *resp_data;
1589
1590         BT_DBG("+");
1591
1592         BT_CHECK_PARAMETER(desc, return);
1593         BT_CHECK_ENABLED(return);
1594
1595         conn = _bt_gdbus_get_system_gconn();
1596         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1597
1598         resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1599         resp_data->user_data = user_data;
1600         resp_data->handle = (char *)desc;
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                 if (error) {
1641                         BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
1642                         g_clear_error(&error);
1643                         g_free(resp_data);
1644                         return;
1645                 }
1646                 g_free(resp_data);
1647                 g_variant_unref(value);
1648                 return;
1649         }
1650
1651         if (error) {
1652                 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
1653                 g_clear_error(&error);
1654
1655                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1656                                 att_ecode, resp_data,
1657                                 user_info->cb, user_info->user_data);
1658                 g_free(resp_data);
1659                 return;
1660         }
1661
1662         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1663                                 BLUETOOTH_ATT_ERROR_NONE, resp_data,
1664                         user_info->cb, user_info->user_data);
1665         g_free(resp_data);
1666
1667         g_variant_unref(value);
1668         BT_DBG("-");
1669 }
1670
1671 BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(const char *desc,
1672                         const guint8 *value, int length, gpointer user_data)
1673 {
1674         GVariant *val, *options;
1675         GDBusConnection *conn;
1676         GVariantBuilder *builder1;
1677         GVariantBuilder *builder2;
1678         guint offset = 0;
1679         int i;
1680         bt_gatt_resp_data_t *resp_data;
1681
1682         BT_DBG("+");
1683
1684         BT_CHECK_PARAMETER(desc, return);
1685         BT_CHECK_PARAMETER(value, return);
1686         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1687         BT_CHECK_ENABLED(return);
1688
1689         conn = _bt_gdbus_get_system_gconn();
1690         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1691
1692         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1693
1694         for (i = 0; i < length; i++)
1695                 g_variant_builder_add(builder1, "y", value[i]);
1696
1697         val = g_variant_new("ay", builder1);
1698
1699         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1700         /*offset*/
1701         g_variant_builder_add(builder2, "{sv}", "offset",
1702                                 g_variant_new_uint16(offset));
1703
1704         /* Device Object path*/
1705 //      g_variant_builder_add(builder2, "{sv}", "device",
1706 //      g_variant_new_object("o", NULL));
1707
1708         options = g_variant_new("a{sv}", builder2);
1709
1710         resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1711         resp_data->user_data = user_data;
1712         resp_data->handle = (char *)desc;
1713
1714         g_dbus_connection_call(conn, BT_BLUEZ_NAME, desc, GATT_DESC_INTERFACE,
1715                         "WriteValue", g_variant_new("(@ay@a{sv})",
1716                         val, options), NULL,
1717                         G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1718                         (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
1719                         (gpointer)resp_data);
1720
1721         g_variant_builder_unref(builder1);
1722         g_variant_builder_unref(builder2);
1723
1724         BT_DBG("-");
1725         return BLUETOOTH_ERROR_NONE;
1726 }
1727
1728 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle, const char *svc_name)
1729 {
1730         GDBusConnection *conn;
1731         GError *error = NULL;
1732         int ret = BLUETOOTH_ERROR_NONE;
1733
1734         BT_CHECK_PARAMETER(char_handle, return);
1735         BT_CHECK_ENABLED(return);
1736
1737         BT_INFO_C("### Enable CCCD : %s [%s]", char_handle + 15, svc_name);
1738
1739         conn = _bt_gdbus_get_system_gconn();
1740         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1741
1742         g_dbus_connection_call_sync(conn,
1743                         BT_BLUEZ_NAME,
1744                         char_handle,
1745                         GATT_CHAR_INTERFACE,
1746                         "StartNotify",
1747                         NULL,
1748                         NULL,
1749                         G_DBUS_CALL_FLAGS_NONE,
1750                         GATT_DEFAULT_TIMEOUT, NULL, &error);
1751
1752         if (error) {
1753                 g_dbus_error_strip_remote_error(error);
1754                 BT_ERR_C("### Watch Failed: %s", error->message);
1755                 if (g_strrstr(error->message, "Already notifying"))
1756                         ret = BLUETOOTH_ERROR_NONE;
1757                 else if (g_strrstr(error->message, "In Progress"))
1758                         ret = BLUETOOTH_ERROR_IN_PROGRESS;
1759                 else if (g_strrstr(error->message, "Operation is not supported"))
1760                         ret = BLUETOOTH_ERROR_NOT_SUPPORT;
1761 /*failed because of either Insufficient Authorization or Write Not Permitted */
1762                 else if (g_strrstr(error->message, "Write not permitted") ||
1763                                 g_strrstr(error->message, "Operation Not Authorized"))
1764                         ret = BLUETOOTH_ERROR_PERMISSION_DEINED;
1765 /* failed because of either Insufficient Authentication,
1766         Insufficient Encryption Key Size, or Insufficient Encryption. */
1767                 else if (g_strrstr(error->message, "Not paired"))
1768                         ret = BLUETOOTH_ERROR_NOT_PAIRED;
1769                 else
1770                         ret = BLUETOOTH_ERROR_INTERNAL;
1771
1772                 g_clear_error(&error);
1773         }
1774
1775         return ret;
1776 }
1777
1778 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle)
1779 {
1780         GDBusConnection *conn;
1781         GError *error = NULL;
1782         int ret = BLUETOOTH_ERROR_NONE;
1783         BT_CHECK_PARAMETER(char_handle, return);
1784
1785         BT_CHECK_ENABLED(return);
1786
1787         BT_INFO("Disable CCCD : %s", char_handle);
1788
1789         conn = _bt_gdbus_get_system_gconn();
1790         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1791
1792         g_dbus_connection_call_sync(conn,
1793                         BT_BLUEZ_NAME,
1794                         char_handle,
1795                         GATT_CHAR_INTERFACE,
1796                         "StopNotify",
1797                         NULL,
1798                         NULL,
1799                         G_DBUS_CALL_FLAGS_NONE,
1800                         GATT_DEFAULT_TIMEOUT, NULL, &error);
1801
1802         if (error) {
1803                 BT_ERR("Watch Failed: %s", error->message);
1804                 g_clear_error(&error);
1805                 ret =  BLUETOOTH_ERROR_INTERNAL;
1806         }
1807
1808         return ret;
1809 }
1810
1811 #ifdef TIZEN_GATT_CLIENT
1812 void __bt_uuid_hex_to_string(unsigned char *uuid, char *str)
1813 {
1814         uint32_t uuid0, uuid4;
1815         uint16_t uuid1, uuid2, uuid3, uuid5;
1816
1817         memcpy(&uuid0, &(uuid[0]), 4);
1818         memcpy(&uuid1, &(uuid[4]), 2);
1819         memcpy(&uuid2, &(uuid[6]), 2);
1820         memcpy(&uuid3, &(uuid[8]), 2);
1821         memcpy(&uuid4, &(uuid[10]), 4);
1822         memcpy(&uuid5, &(uuid[14]), 2);
1823
1824         snprintf((char *)str, BLUETOOTH_UUID_STRING_MAX, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
1825                         ntohl(uuid0), ntohs(uuid1),
1826                         ntohs(uuid2), ntohs(uuid3),
1827                         ntohl(uuid4), ntohs(uuid5));
1828         return;
1829 }
1830
1831
1832 static void __bt_fill_service_handle_informations(bt_services_browse_info_t *props,
1833                 bt_gatt_handle_info_t *svcs)
1834 {
1835         int count;
1836         BT_INFO("Total services found [%d]", props->count);
1837
1838         if (props->count == 0)
1839                 return;
1840
1841         svcs->count = props->count;
1842
1843         for (count = 0; count < props->count; count++) {
1844                 BT_INFO("UUID[%d] = [%s] instance_id [%d] Is Primary [%d]",
1845                                 count, props->uuids[count], props->inst_id[count], props->primary[count]);
1846                 g_strlcpy(svcs->uuids[count], props->uuids[count],
1847                                 BLUETOOTH_UUID_STRING_MAX);
1848                 svcs->inst_id[count] = props->inst_id[count];
1849         }
1850 }
1851
1852 static void __bt_fill_char_handle_informations(bt_char_browse_info_t *props,
1853                 bt_gatt_service_property_t *service)
1854 {
1855         int count;
1856         char uuid_string[BLUETOOTH_UUID_STRING_MAX];
1857         BT_INFO("Total number of characteristics found [%d]",
1858                         props->count);
1859
1860         service->char_handle.count = props->count;
1861
1862         /* Before filling all char handles, fill the service's UUID and instance ID */
1863         __bt_uuid_hex_to_string(props->svc_uuid, uuid_string);
1864         service->uuid = g_strdup(uuid_string);
1865         service->primary = TRUE;
1866
1867         /* Now fill all the char handles [UUID and Instance ID's]*/
1868         for (count = 0; count < props->count; count++) {
1869                 BT_INFO("UUID[%d] = [%s] instance_id [%d] properties [%d]",
1870                                 count, props->uuids[count], props->inst_id[count], props->props[count]);
1871
1872                 g_strlcpy(service->char_handle.uuids[count],
1873                                 props->uuids[count],
1874                                 BLUETOOTH_UUID_STRING_MAX);
1875
1876                 service->char_handle.inst_id[count] = props->inst_id[count];
1877         }
1878 }
1879
1880 static void __bt_fill_desc_handle_informations(bt_descriptor_browse_info_t *props,
1881                 bt_gatt_char_property_t *charc)
1882 {
1883         int count;
1884         char uuid_string[BLUETOOTH_UUID_STRING_MAX];
1885         BT_INFO("Total descriptor count found [%d]", props->count);
1886
1887         charc->char_desc_handle.count = props->count;
1888
1889         /* Before filling all desc handles, fill the charac's UUID and instance ID */
1890         __bt_uuid_hex_to_string(props->char_uuid, uuid_string);
1891         charc->uuid = g_strdup(uuid_string);
1892
1893         /* Now fill all the descriptor handles [UUID and Instance ID's]*/
1894         for (count = 0; count < props->count; count++) {
1895                 BT_INFO("UUID[%d] = [%s] instance_id [%d]",
1896                                 count, props->uuids[count], props->inst_id[count]);
1897
1898                 g_strlcpy(charc->char_desc_handle.uuids[count],
1899                                 props->uuids[count],
1900                                 BLUETOOTH_UUID_STRING_MAX);
1901
1902                 charc->char_desc_handle.inst_id[count] = props->inst_id[count];
1903         }
1904         charc->permission = props->char_props_map;
1905         BT_INFO("Characteritic property map val [%d]", charc->permission);
1906 }
1907
1908
1909 BT_EXPORT_API int bluetooth_gatt_client_init(
1910                 int *client_id,
1911                 const bluetooth_device_address_t *address,
1912                 gatt_client_cb_func_ptr callback_ptr)
1913 {
1914         int ret = BLUETOOTH_ERROR_NONE;
1915         bt_event_info_t *event_info;
1916         int *count;
1917
1918         BT_CHECK_PARAMETER(client_id, return);
1919         BT_CHECK_PARAMETER(callback_ptr, return);
1920         BT_CHECK_ENABLED(return);
1921
1922         BT_INFO("+");
1923
1924         BT_INIT_PARAMS();
1925         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1926
1927         g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
1928
1929         ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_REGISTER,
1930                         in_param1, in_param2, in_param3, in_param4, &out_param);
1931
1932         /* App ID -1 is invalid */
1933         if (ret == BLUETOOTH_ERROR_NONE) {
1934
1935                 *client_id = g_array_index(out_param, int, 0);
1936
1937                 BT_INFO("GATT Client Registered successfully: Client instance ID [%d]", *client_id);
1938
1939                 event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
1940
1941                 if (event_info) {
1942                         count = (int*)event_info->user_data;
1943
1944                         BT_INFO("Total num of GATT client instances [%d]", *count);
1945
1946                         /* Increement the count */
1947                         *count += 1;
1948                 } else {
1949                         BT_INFO("No GATT Client instances found in this application: Set User data");
1950                         count = g_malloc0(sizeof(int));
1951                         *count = 1;
1952
1953                         /* Register event handler for GATT */
1954                         _bt_register_event(BT_GATT_CLIENT_EVENT,
1955                                         (void *)callback_ptr,
1956                                         (void *)count);
1957                         _bt_set_user_data(BT_GATT_CLIENT, (void *)callback_ptr, NULL);
1958                 }
1959         } else
1960                 BT_ERR("GATT Client Registration failed!! ret [%d]", ret);
1961
1962         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1963         return ret;
1964 }
1965
1966
1967
1968 /* GATT Client*/
1969 BT_EXPORT_API int bluetooth_gatt_client_get_primary_services(
1970                 const bluetooth_device_address_t *address, /* Remote GATT Server */
1971                 bt_gatt_handle_info_t *prim_svc) /* UUID & instance_id */
1972 {
1973
1974         int result = BLUETOOTH_ERROR_NONE;
1975         bt_services_browse_info_t service_props;
1976
1977         BT_DBG("+");
1978
1979         BT_CHECK_PARAMETER(address, return);
1980         BT_CHECK_PARAMETER(prim_svc, return);
1981         BT_CHECK_ENABLED(return);
1982
1983         BT_INIT_PARAMS();
1984         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1985         g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
1986
1987         result = _bt_send_request(BT_BLUEZ_SERVICE,
1988                         BT_GATT_GET_PRIMARY_SERVICES,
1989                         in_param1, in_param2, in_param3, in_param4, &out_param);
1990
1991         if (BLUETOOTH_ERROR_NONE != result)
1992                 goto done;
1993
1994         memset(&service_props, 0x00, sizeof(bt_services_browse_info_t));
1995
1996         service_props = g_array_index(
1997                         out_param, bt_services_browse_info_t, 0);
1998
1999         __bt_fill_service_handle_informations(
2000                         &service_props, prim_svc);
2001
2002 done:
2003         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2004         BT_DBG("result = %d", result);
2005         return result;
2006 }
2007
2008 BT_EXPORT_API int bluetooth_gatt_client_get_service_property(
2009                 const char *address,
2010                 bt_gatt_handle_property_t *service_handle,
2011                 bt_gatt_service_property_t *service)
2012 {
2013         int result = BLUETOOTH_ERROR_NONE;
2014         bluetooth_gatt_client_svc_prop_info_t svc_prop;
2015         bt_char_browse_info_t char_handles_info;
2016         BT_INFO("Remote Address [%s]", address);
2017
2018         BT_CHECK_PARAMETER(address, return);
2019         BT_CHECK_PARAMETER(service_handle, return);
2020         BT_CHECK_PARAMETER(service, return);
2021         BT_CHECK_ENABLED(return);
2022
2023         /* Call to bt-service (sync) and send address and service_handle info */
2024         BT_INIT_PARAMS();
2025         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2026
2027         memset(&svc_prop, 0x00, sizeof(bluetooth_gatt_client_svc_prop_info_t));
2028         /* All characteristics handles are discovered */
2029         memset(&char_handles_info, 0x00, sizeof(bt_char_browse_info_t));
2030
2031         svc_prop.svc.instance_id = service_handle->instance_id;
2032         memcpy(&svc_prop.svc.uuid, &service_handle->uuid, 16);
2033
2034         _bt_convert_addr_string_to_type(svc_prop.device_address.addr, address);
2035
2036         g_array_append_vals(in_param1, &svc_prop, sizeof(bluetooth_gatt_client_svc_prop_info_t));
2037
2038         result = _bt_send_request(BT_BLUEZ_SERVICE,
2039                         BT_GATT_GET_SERVICE_PROPERTIES,
2040                         in_param1, in_param2, in_param3, in_param4, &out_param);
2041
2042         if (BLUETOOTH_ERROR_NONE != result)
2043                 goto done;
2044
2045         char_handles_info = g_array_index(
2046                         out_param, bt_char_browse_info_t, 0);
2047         __bt_fill_char_handle_informations(&char_handles_info,
2048                         service);
2049         /* TODO Get all Included Services */
2050
2051 done:
2052         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2053         BT_INFO("result = %d", result);
2054         return result;
2055 }
2056
2057 BT_EXPORT_API int bluetooth_gatt_client_get_characteristics_property(
2058                 const char *address,
2059                 bt_gatt_handle_property_t *service_handle,
2060                 bt_gatt_handle_property_t *char_handle,
2061                 bt_gatt_char_property_t *char_property)
2062 {
2063         int result = BLUETOOTH_ERROR_NONE;
2064         bt_descriptor_browse_info_t desc_handles_info;
2065         bluetooth_gatt_client_char_prop_info_t char_prop;
2066         BT_INFO("Get Properties of characteristics from remote device [%s]", address);
2067
2068         BT_CHECK_PARAMETER(address, return);
2069         BT_CHECK_PARAMETER(service_handle, return);
2070         BT_CHECK_PARAMETER(char_handle, return);
2071         BT_CHECK_PARAMETER(char_property, return);
2072         BT_CHECK_ENABLED(return);
2073
2074
2075         /* Call to bt-service (sync) and send address service_handle info & char handle info  */
2076         BT_INIT_PARAMS();
2077         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2078
2079         memset(&char_prop, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2080         char_prop.svc.instance_id = service_handle->instance_id;
2081         memcpy(&char_prop.svc.uuid, &service_handle->uuid, 16);
2082
2083         char_prop.characteristic.instance_id = char_handle->instance_id;
2084         memcpy(&char_prop.characteristic.uuid, &char_handle->uuid, 16);
2085
2086         _bt_convert_addr_string_to_type(char_prop.device_address.addr, address);
2087
2088         g_array_append_vals(in_param1, &char_prop, sizeof(bluetooth_gatt_client_char_prop_info_t));
2089
2090         result = _bt_send_request(BT_BLUEZ_SERVICE,
2091                         BT_GATT_GET_CHARACTERISTIC_PROPERTIES,
2092                         in_param1, in_param2, in_param3, in_param4, &out_param);
2093
2094         BT_INFO("result = [%d]", result);
2095         if (BLUETOOTH_ERROR_NONE != result)
2096                 goto done;
2097
2098         /* All descriptors handles are discovered */
2099         memset(&desc_handles_info, 0x00, sizeof(bt_descriptor_browse_info_t));
2100
2101         desc_handles_info = g_array_index(
2102                         out_param, bt_descriptor_browse_info_t, 0);
2103
2104         __bt_fill_desc_handle_informations(&desc_handles_info,
2105                         char_property);
2106
2107 done:
2108         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2109         BT_INFO("result = %d", result);
2110         return result;
2111         /* Call to bt-service (sync) and send address, service_handle & char_handle infos */
2112
2113         /* After result is fetched, extract descriptor handles (UUID's & instance_id's) */
2114
2115         /* Fill the info in *char_prop */
2116
2117         /*No: Before returning, call bluetooth_gatt_client_read_characteristic_value as
2118                 an asyn function and leave every thing else in the callback */
2119 }
2120
2121 BT_EXPORT_API int bluetooth_gatt_client_get_char_descriptor_property(
2122                 const char *address,
2123                 bt_gatt_handle_property_t *service_handle,
2124                 bt_gatt_handle_property_t *char_handle,
2125                 bt_gatt_handle_property_t *descriptor_handle,
2126                 bt_gatt_char_descriptor_property_t *desc_prop)
2127 {
2128         char uuid_string[BLUETOOTH_UUID_STRING_MAX];
2129         BT_DBG("Remote Address [%s]", address);
2130
2131         BT_CHECK_PARAMETER(address, return);
2132         BT_CHECK_PARAMETER(service_handle, return);
2133         BT_CHECK_PARAMETER(char_handle, return);
2134         BT_CHECK_PARAMETER(descriptor_handle, return);
2135         BT_CHECK_PARAMETER(desc_prop, return);
2136         /* No Need to Call to bt-service (sync) and send address, service_handle,
2137                 char_handle & descriptor handle infos */
2138         /* After result is fetched, extract descriptior handles (UUID's & instance_id's) */
2139         /* Fill the info in *desc_prop */
2140         __bt_uuid_hex_to_string(descriptor_handle->uuid, uuid_string);
2141
2142         /* Before filling all desc handles, fill the charac's UUID and instance ID */
2143         desc_prop->uuid = g_strdup(uuid_string);
2144
2145         return BLUETOOTH_ERROR_NONE;
2146         /* No: Before returning, call bluetooth_gatt_client_read_descriptor_value
2147                 as an asyn function and leave every thing else in the callback */
2148 }
2149
2150 BT_EXPORT_API int bluetooth_gatt_client_watch_characteristics(
2151                         const char *address,
2152                         bt_gatt_handle_property_t *service_handle,
2153                         bt_gatt_handle_property_t *char_handle,
2154                         int client_id,
2155                         gboolean is_notify)
2156 {
2157         int result = BLUETOOTH_ERROR_NONE;
2158         bluetooth_gatt_client_char_prop_info_t param;
2159         BT_DBG("+");
2160
2161         BT_CHECK_PARAMETER(address, return);
2162         BT_CHECK_PARAMETER(service_handle, return);
2163         BT_CHECK_PARAMETER(char_handle, return);
2164
2165         /* ASync Function, result expected in callback from bt-service */
2166
2167         BT_INIT_PARAMS();
2168         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2169
2170         BT_INFO("Address [%s]", address);
2171         memset(&param, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2172
2173         memcpy(&param.svc.uuid, service_handle->uuid, 16);
2174         param.svc.instance_id = service_handle->instance_id;
2175
2176         memcpy(&param.characteristic.uuid, char_handle->uuid, 16);
2177         param.characteristic.instance_id = char_handle->instance_id;
2178
2179         _bt_convert_addr_string_to_type(param.device_address.addr, address);
2180
2181         g_array_append_vals(in_param1, &param, sizeof(bluetooth_gatt_client_char_prop_info_t));
2182         g_array_append_vals(in_param2, &client_id, sizeof(int));
2183         g_array_append_vals(in_param3, &is_notify, sizeof(gboolean));
2184
2185         result = _bt_send_request(BT_BLUEZ_SERVICE,
2186                         BT_GATT_WATCH_CHARACTERISTIC,
2187                         in_param1, in_param2, in_param3, in_param4, &out_param);
2188
2189         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2190
2191         BT_INFO("Result [%d]", result);
2192         return result;
2193 }
2194
2195 BT_EXPORT_API int bluetooth_gatt_client_read_characteristic_value(
2196                 const char *address,
2197                 bt_gatt_handle_property_t *service_handle,
2198                 bt_gatt_handle_property_t *char_handle)
2199 {
2200         int result = BLUETOOTH_ERROR_NONE;
2201         bt_user_info_t *user_info;
2202         bluetooth_gatt_client_char_prop_info_t param;
2203         BT_DBG("+");
2204
2205         BT_CHECK_PARAMETER(address, return);
2206         BT_CHECK_PARAMETER(service_handle, return);
2207         BT_CHECK_PARAMETER(char_handle, return);
2208
2209         user_info = _bt_get_user_data(BT_GATT_CLIENT);
2210         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2211
2212         BT_INIT_PARAMS();
2213         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2214
2215         /* Async Function, result expected in callback from bt-service */
2216         /* Call to bt-service (sync) and send address service_handle info & char handle info  */
2217         memset(&param, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2218
2219         memcpy(&param.svc.uuid, service_handle->uuid, 16);
2220         param.svc.instance_id = service_handle->instance_id;
2221
2222         memcpy(&param.characteristic.uuid, char_handle->uuid, 16);
2223         param.characteristic.instance_id = char_handle->instance_id;
2224
2225         _bt_convert_addr_string_to_type(param.device_address.addr, address);
2226
2227         g_array_append_vals(in_param1, &param,
2228                         sizeof(bluetooth_gatt_client_char_prop_info_t));
2229
2230
2231         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_GATT_READ_CHARACTERISTIC,
2232                         in_param1, in_param2, in_param3, in_param4,
2233                         user_info->cb, user_info->user_data);
2234
2235
2236         BT_INFO("result = [%d]", result);
2237         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2238         return result;
2239 }
2240
2241 BT_EXPORT_API int bluetooth_gatt_client_read_descriptor_value(
2242                 const char *address,
2243                 bt_gatt_handle_property_t *service_handle,
2244                 bt_gatt_handle_property_t *char_handle,
2245                 bt_gatt_handle_property_t *descriptor_handle)
2246 {
2247         int result = BLUETOOTH_ERROR_NONE;
2248         bt_user_info_t *user_info;
2249         bluetooth_gatt_client_desc_prop_info_t param;
2250         BT_DBG("+");
2251
2252         BT_CHECK_PARAMETER(address, return);
2253         BT_CHECK_PARAMETER(service_handle, return);
2254         BT_CHECK_PARAMETER(char_handle, return);
2255         BT_CHECK_PARAMETER(descriptor_handle, return);
2256
2257         user_info = _bt_get_user_data(BT_GATT_CLIENT);
2258         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2259
2260         BT_INIT_PARAMS();
2261         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2262
2263         /* Async Function, result expected in callback from bt-service */
2264         memset(&param, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2265
2266         memcpy(&param.svc.uuid, service_handle->uuid, 16);
2267         param.svc.instance_id = service_handle->instance_id;
2268
2269         memcpy(&param.characteristic.uuid, char_handle->uuid, 16);
2270         param.characteristic.instance_id = char_handle->instance_id;
2271
2272         memcpy(&param.descriptor.uuid, descriptor_handle->uuid, 16);
2273         param.descriptor.instance_id = descriptor_handle->instance_id;
2274
2275         _bt_convert_addr_string_to_type(param.device_address.addr, address);
2276
2277         g_array_append_vals(in_param1, &param,
2278                         sizeof(bluetooth_gatt_client_desc_prop_info_t));
2279
2280
2281         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_GATT_READ_DESCRIPTOR_VALUE,
2282                         in_param1, in_param2, in_param3, in_param4,
2283                         user_info->cb, user_info->user_data);
2284
2285         BT_INFO("result = [%d]", result);
2286         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2287         return result;
2288 }
2289
2290 BT_EXPORT_API int bluetooth_gatt_client_write_characteristic_value_by_type(
2291                 const char *address,
2292                 bt_gatt_handle_property_t *service_handle,
2293                 bt_gatt_handle_property_t *char_handle,
2294                 bluetooth_gatt_att_data_t *data,
2295                 bluetooth_gatt_write_type_e  write_type)
2296 {
2297         int result = BLUETOOTH_ERROR_NONE;
2298         bt_user_info_t *user_info;
2299         bluetooth_gatt_client_char_prop_info_t param;
2300         BT_DBG("+");
2301
2302         BT_CHECK_PARAMETER(address, return);
2303         BT_CHECK_PARAMETER(service_handle, return);
2304         BT_CHECK_PARAMETER(char_handle, return);
2305         BT_CHECK_PARAMETER(data, return);
2306
2307         /* ASync Function, result expected in callback from bt-service */
2308         user_info = _bt_get_user_data(BT_GATT_CLIENT);
2309         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2310
2311         BT_INIT_PARAMS();
2312         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2313
2314         memset(&param, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2315
2316         memcpy(&param.svc.uuid, service_handle->uuid, 16);
2317         param.svc.instance_id = service_handle->instance_id;
2318
2319         memcpy(&param.characteristic.uuid, char_handle->uuid, 16);
2320         param.characteristic.instance_id = char_handle->instance_id;
2321
2322         _bt_convert_addr_string_to_type(param.device_address.addr, address);
2323
2324         g_array_append_vals(in_param1, &param, sizeof(bluetooth_gatt_client_char_prop_info_t));
2325         g_array_append_vals(in_param2, data, sizeof(bluetooth_gatt_att_data_t));
2326         g_array_append_vals(in_param3, &write_type, sizeof(bluetooth_gatt_write_type_e));
2327
2328         result = _bt_send_request_async(BT_BLUEZ_SERVICE,
2329                         BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE,
2330                         in_param1, in_param2, in_param3, in_param4,
2331                         user_info->cb, user_info->user_data);
2332
2333         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2334
2335         return result;
2336 }
2337
2338 BT_EXPORT_API int bluetooth_gatt_client_write_descriptor_value(
2339                 const char *address,
2340                 bt_gatt_handle_property_t *service_handle,
2341                 bt_gatt_handle_property_t *char_handle,
2342                 bt_gatt_handle_property_t *descriptor_handle,
2343                 bluetooth_gatt_att_data_t *data,
2344                 bluetooth_gatt_write_type_e  write_type)
2345 {
2346         int result = BLUETOOTH_ERROR_NONE;
2347         bt_user_info_t *user_info;
2348         bluetooth_gatt_client_desc_prop_info_t param;
2349         BT_DBG("+");
2350
2351         BT_CHECK_PARAMETER(address, return);
2352         BT_CHECK_PARAMETER(service_handle, return);
2353         BT_CHECK_PARAMETER(char_handle, return);
2354         BT_CHECK_PARAMETER(descriptor_handle, return);
2355         BT_CHECK_PARAMETER(data, return);
2356
2357         /* Async Function, result expected in callback from bt-service */
2358         user_info = _bt_get_user_data(BT_GATT_CLIENT);
2359         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2360
2361         BT_INIT_PARAMS();
2362         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2363
2364         memset(&param, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2365
2366         memcpy(&param.svc.uuid, service_handle->uuid, 16);
2367         param.svc.instance_id = service_handle->instance_id;
2368
2369         memcpy(&param.characteristic.uuid, char_handle->uuid, 16);
2370         param.characteristic.instance_id = char_handle->instance_id;
2371
2372         memcpy(&param.descriptor.uuid, descriptor_handle->uuid, 16);
2373         param.descriptor.instance_id = descriptor_handle->instance_id;
2374
2375         _bt_convert_addr_string_to_type(param.device_address.addr, address);
2376
2377         g_array_append_vals(in_param1, &param, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2378         g_array_append_vals(in_param2, data, sizeof(bluetooth_gatt_att_data_t));
2379         g_array_append_vals(in_param3, &write_type, sizeof(bluetooth_gatt_write_type_e));
2380
2381         result = _bt_send_request_async(BT_BLUEZ_SERVICE,
2382                         BT_GATT_WRITE_DESCRIPTOR_VALUE,
2383                         in_param1, in_param2, in_param3, in_param4,
2384                         user_info->cb, user_info->user_data);
2385
2386         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2387
2388         return result;
2389 }
2390
2391 BT_EXPORT_API int bluetooth_gatt_client_set_service_change_watcher(
2392                 const bluetooth_device_address_t *address, gboolean enable)
2393 {
2394         GSList *l;
2395         bluetooth_device_address_t *addr = NULL;
2396         char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
2397         int result = BLUETOOTH_ERROR_NONE;
2398
2399         BT_INFO("+");
2400
2401         BT_INIT_PARAMS();
2402         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2403
2404         g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
2405         g_array_append_vals(in_param2, &enable, sizeof(gboolean));
2406
2407
2408         _bt_convert_addr_string_to_secure_string(secure_address, (const char *)address->addr);
2409         BT_INFO("Set watcher for %s with %d", secure_address, enable);
2410
2411         if (enable == TRUE) {
2412                 if (_bluetooth_gatt_check_service_change_watcher_address(address)
2413                                 == TRUE) {
2414                         BT_INFO("The watcher is already set");
2415                         goto done;
2416                 }
2417
2418                 if (service_monitor_list == NULL) {
2419                         //_bt_register_manager_subscribe_signal(TRUE);
2420
2421                         result = _bt_send_request(BT_BLUEZ_SERVICE,
2422                                         BT_GATT_WATCH_SERVICE_CHANGED_INDICATION,
2423                                         in_param1, in_param2, in_param3, in_param4, &out_param);
2424                 }
2425
2426                 if (result == BLUETOOTH_ERROR_NONE) {
2427                         addr = g_malloc0(sizeof(bluetooth_device_address_t));
2428                         memcpy(addr, address, sizeof(bluetooth_device_address_t));
2429
2430                         service_monitor_list =
2431                                 g_slist_append(service_monitor_list, addr);
2432                 }
2433         } else {
2434                 for (l = service_monitor_list; l != NULL; l = l->next) {
2435                         addr = l->data;
2436
2437                         if (!memcmp(address, addr,
2438                                                 sizeof(bluetooth_device_address_t))) {
2439                                 service_monitor_list =
2440                                         g_slist_remove(service_monitor_list, addr);
2441                                 g_free(addr);
2442                                 break;
2443                         }
2444                 }
2445
2446                 if (service_monitor_list == NULL) {
2447                         //_bt_register_manager_subscribe_signal(FALSE);
2448                         result = _bt_send_request(BT_BLUEZ_SERVICE,
2449                                         BT_GATT_WATCH_SERVICE_CHANGED_INDICATION,
2450                                         in_param1, in_param2, in_param3, in_param4, &out_param);
2451
2452                 }
2453         }
2454
2455 done:
2456         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2457         return result;
2458 }
2459
2460 BT_EXPORT_API int bluetooth_gatt_client_deinit(
2461                 int client_id)
2462 {
2463         int result;
2464         int *count;
2465         bt_event_info_t *event_info;
2466
2467         BT_CHECK_ENABLED(return);
2468
2469         BT_INFO("GATT Client Deinit Client instance ID [%d]", client_id);
2470
2471         BT_INIT_PARAMS();
2472         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2473
2474         g_array_append_vals(in_param1, &client_id, sizeof(int));
2475
2476         /* Unregistration MUST NOT FAIL */
2477         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_UNREGISTER,
2478                         in_param1, in_param2, in_param3, in_param4, &out_param);
2479
2480         if (result != BLUETOOTH_ERROR_NONE)
2481                 BT_INFO("GATT Client Unregistration failed result [%d]", result);
2482         else
2483                 BT_INFO("GATT Client Unregistration successful");
2484
2485         /* Unregister event handler if this is the only instance */
2486         event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
2487
2488         if (event_info) {
2489                 count = (int*)event_info->user_data;
2490
2491                 BT_INFO("Total num of GATT client instances [%d]", *count);
2492
2493                 if (*count == 1) {
2494                         BT_INFO("Currently only one GATT client instance, so remove it and unregister GATT client events");
2495                         _bt_unregister_event(BT_GATT_CLIENT_EVENT);
2496                         _bt_set_user_data(BT_GATT_CLIENT, NULL, NULL);
2497                 } else
2498                         *count -= 1;
2499         } else
2500                 BT_ERR("Impossible that client is created, but no event handler is registered!!!");
2501
2502         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2503         return result;
2504 }
2505
2506 #endif