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