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