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