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