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