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