BT 5.0: Add APIs to support set/read PHYs
[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_common_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_common_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_common_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_common_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_common_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_common_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_common_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_common_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         GDBusConnection *conn;
1114         int i = 0;
1115         guint16 offset = 0;
1116
1117         BT_DBG("+");
1118         BT_CHECK_PARAMETER(char_handle, return);
1119         BT_CHECK_PARAMETER(value, return);
1120         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1121         BT_CHECK_ENABLED(return);
1122
1123         conn = _bt_get_system_common_conn();
1124         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1125
1126         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1127         for (i = 0; i < length; i++)
1128                 g_variant_builder_add(builder1, "y", value[i]);
1129
1130         val = g_variant_new("ay", builder1);
1131
1132         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1133         /*offset*/
1134         g_variant_builder_add(builder2, "{sv}", "offset",
1135                                 g_variant_new_uint16(offset));
1136
1137         /* Device Object path*/
1138 //      g_variant_builder_add(builder2, "{sv}", "device",
1139 //      g_variant_new_object("o", NULL));
1140
1141         options = g_variant_new("a{sv}", builder2);
1142
1143         g_dbus_connection_call(conn,
1144                                 BT_BLUEZ_NAME,
1145                                 char_handle,
1146                                 GATT_CHAR_INTERFACE,
1147                                 "WriteValue",
1148                                 g_variant_new("(@ay@a{sv})",
1149                                 val, options),
1150                                 NULL,
1151                                 G_DBUS_CALL_FLAGS_NONE,
1152                                 -1, NULL,
1153                                 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1154                                 NULL);
1155
1156         g_variant_builder_unref(builder1);
1157         g_variant_builder_unref(builder2);
1158
1159         BT_DBG("-");
1160         return BLUETOOTH_ERROR_NONE;
1161 }
1162
1163 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
1164                         const char *chr, const guint8 *value, int length,
1165                         guint8 write_type, gpointer user_data)
1166 {
1167         GVariant *val, *options;
1168         GVariantBuilder *builder1;
1169         GVariantBuilder *builder2;
1170         GDBusConnection *conn;
1171         guint16 offset = 0;
1172         int i = 0;
1173         int ret = BLUETOOTH_ERROR_NONE;
1174         bt_gatt_resp_data_t *resp_data;
1175
1176         BT_CHECK_PARAMETER(chr, return);
1177         BT_CHECK_PARAMETER(value, return);
1178         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1179         BT_CHECK_ENABLED_INTERNAL(return);
1180
1181         conn = _bt_get_system_common_conn();
1182         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1183
1184         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1185
1186         for (i = 0; i < length; i++)
1187                 g_variant_builder_add(builder1, "y", value[i]);
1188
1189         val = g_variant_new("ay", builder1);
1190
1191         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1192         /*offset*/
1193         g_variant_builder_add(builder2, "{sv}", "offset",
1194                         g_variant_new_uint16(offset));
1195
1196         /* Device Object path*/
1197 //      g_variant_builder_add(builder2, "{sv}", "device",
1198 //      g_variant_new_object("o", NULL));
1199
1200         options = g_variant_new("a{sv}", builder2);
1201
1202         resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1203         resp_data->user_data = user_data;
1204         resp_data->handle = (char *)chr;
1205
1206         g_dbus_connection_call(conn, BT_BLUEZ_NAME, chr, GATT_CHAR_INTERFACE,
1207                         "WriteValuebyType",
1208                         g_variant_new("(y@ay@a{sv})", write_type, val, options),
1209                         NULL,
1210                         G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1211                         (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1212                         (gpointer)resp_data);
1213
1214         g_variant_builder_unref(builder1);
1215         g_variant_builder_unref(builder2);
1216
1217         return ret;
1218 }
1219
1220 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
1221                         const char *char_handle, const guint8 *value, int length)
1222 {
1223         GVariant *val, *options;
1224         GDBusConnection *conn;
1225         GVariantBuilder *builder1;
1226         GVariantBuilder *builder2;
1227         guint offset = 0;
1228         int i;
1229
1230         BT_DBG("+");
1231         BT_CHECK_PARAMETER(char_handle, return);
1232         BT_CHECK_PARAMETER(value, return);
1233         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1234         BT_CHECK_ENABLED(return);
1235
1236         conn = _bt_get_system_common_conn();
1237         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1238
1239         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1240
1241         for (i = 0; i < length; i++) {
1242                 g_variant_builder_add(builder1, "y", value[i]);
1243                 BT_DBG("value [] = %d", value[i]);
1244         }
1245
1246         val = g_variant_new("ay", builder1);
1247
1248         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1249         /*offset*/
1250         g_variant_builder_add(builder2, "{sv}", "offset",
1251                                 g_variant_new_uint16(offset));
1252
1253         /* Device Object path*/
1254 //      g_variant_builder_add(builder2, "{sv}", "device",
1255 //      g_variant_new_object("o", NULL));
1256
1257         options = g_variant_new("a{sv}", builder2);
1258
1259         g_dbus_connection_call(conn,
1260                                 BT_BLUEZ_NAME,
1261                                 char_handle,
1262                                 GATT_CHAR_INTERFACE,
1263                                 "WriteValue",
1264                                 g_variant_new("(@ay@a{sv})",
1265                                 val, options),
1266                                 NULL,
1267                                 G_DBUS_CALL_FLAGS_NONE,
1268                                 -1, NULL,
1269                                 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1270                                 NULL);
1271
1272         g_variant_builder_unref(builder1);
1273         g_variant_builder_unref(builder2);
1274
1275         BT_DBG("-");
1276         return BLUETOOTH_ERROR_NONE;
1277 }
1278
1279 static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
1280                         bt_gatt_char_property_t *characteristic)
1281 {
1282         BT_DBG("+");
1283         GDBusProxy *properties_proxy = NULL;
1284         GError *error = NULL;
1285         GVariant *value = NULL;
1286         GVariant *result = NULL;
1287         GDBusConnection *g_conn;
1288         int i, ret = BLUETOOTH_ERROR_NONE;
1289         const char *uuid = NULL;
1290         gsize len = 0;
1291         GVariantIter *desc_value_iter, *property_iter;
1292         const gchar *key;
1293         char_descriptor_type_t desc_type = TYPE_NONE;
1294
1295         g_conn = _bt_get_system_common_conn();
1296         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1297
1298         properties_proxy = g_dbus_proxy_new_sync(g_conn,
1299                         G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1300                         BT_BLUEZ_NAME,
1301                         char_handle,
1302                         BT_PROPERTIES_INTERFACE,
1303                         NULL, &error);
1304
1305         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1306
1307         result = g_dbus_proxy_call_sync(properties_proxy,
1308                                 "GetAll",
1309                                 g_variant_new("(s)", GATT_DESC_INTERFACE),
1310                                 G_DBUS_CALL_FLAGS_NONE,
1311                                 -1,
1312                                 NULL,
1313                                 &error);
1314
1315         if (!result) {
1316                 if (error != NULL) {
1317                         BT_ERR("Fail to get properties (Error: %s)", error->message);
1318                         g_clear_error(&error);
1319                 } else
1320                         BT_ERR("Fail to get properties");
1321                 g_object_unref(properties_proxy);
1322                 return BLUETOOTH_ERROR_INTERNAL;
1323         }
1324         g_variant_get(result, "(a{sv})", &property_iter);
1325         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1326                 if (!g_strcmp0(key, "UUID")) {
1327                         uuid = g_variant_get_string(value, &len);
1328                         if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
1329                                 BT_DBG("GATT_USER_DESC_UUID");
1330                                 desc_type = USER_DESC;
1331                         } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) {
1332                                 BT_DBG("GATT_CHAR_FORMAT");
1333                                 desc_type = CHAR_FORMAT;
1334                         } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) {
1335                                 BT_DBG("GATT_CHAR_CLIENT_CONF");
1336                                 desc_type = CLIENT_CONF;
1337                         } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) {
1338                                 BT_DBG("GATT_CHAR_SERVER_CONF");
1339                                 desc_type = SERVER_CONF;
1340                         } else {
1341                                 BT_DBG("descriptor uuid = %s", uuid);
1342                         }
1343                 } else if (!g_strcmp0(key, "Value")) {
1344                         switch (desc_type) {
1345                         case CHAR_FORMAT:
1346                                 BT_DBG("Format descriptor");
1347                                 g_variant_get(value, "(yyqyq)",
1348                                                 &(characteristic->format.format),
1349                                                 &(characteristic->format.exponent),
1350                                                 &(characteristic->format.unit),
1351                                                 &(characteristic->format.name_space),
1352                                                 &(characteristic->format.description));
1353                                 break;
1354                         case USER_DESC:
1355                                 BT_DBG("User descriptor");
1356                                 g_variant_get(value, "ay", &desc_value_iter);
1357                                 len = g_variant_get_size((GVariant *)desc_value_iter);
1358
1359                                 if (len > 0)
1360                                         characteristic->description = (char *)g_malloc0(len + 1);
1361
1362                                 for (i = 0; i < len; i++) {
1363                                         g_variant_iter_loop(desc_value_iter, "y",
1364                                                 &characteristic->description[i]);
1365                                         BT_DBG("description = %s", characteristic->description);
1366                                 }
1367                                 g_variant_iter_free(desc_value_iter);
1368                                 break;
1369                         case CLIENT_CONF:
1370                                 BT_DBG(" CLIENT_CONF");
1371                                 break;
1372                         case SERVER_CONF:
1373                                 BT_DBG(" SERVER_CONF");
1374                                 break;
1375                         default:
1376                                 break;
1377                         }
1378                 }
1379         }
1380
1381         g_variant_iter_free(property_iter);
1382         g_variant_unref(result);
1383         g_object_unref(properties_proxy);
1384
1385         BT_DBG("-");
1386         return ret;
1387 }
1388
1389
1390 static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
1391                         GAsyncResult *res, gpointer user_data)
1392 {
1393         BT_DBG("+");
1394         GVariant *value;
1395         GVariant        *char_value;
1396         GVariantIter *char_iter;
1397         char *char_handle;
1398         GError *error = NULL;
1399         bt_user_info_t *user_info;
1400         bt_gatt_char_property_t characteristic = {0, };
1401         int ret = BLUETOOTH_ERROR_INTERNAL;
1402
1403         user_info = _bt_get_user_data(BT_COMMON);
1404
1405         value = g_dbus_proxy_call_finish(proxy, res, &error);
1406         characteristic.handle = user_data;
1407
1408         if (value == NULL) {
1409                 if (error != NULL) {
1410                         BT_ERR("Get characteristic descriptor failed\n errCode[%x],"
1411                                         "message[%s]\n", error->code, error->message);
1412                         g_clear_error(&error);
1413                 } else {
1414                         BT_ERR("Get characteristic descriptor failed\n");
1415                 }
1416                 if (user_info) {
1417                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1418                                 BLUETOOTH_ERROR_INTERNAL, NULL,
1419                                 user_info->cb, user_info->user_data);
1420                 }
1421                 g_free(characteristic.handle);
1422                 g_object_unref(proxy);
1423                 return;
1424         }
1425
1426         g_variant_get(value, "(v)", &char_value);
1427         g_variant_get(char_value, "ao", &char_iter);
1428
1429         while (g_variant_iter_loop(char_iter, "&o",  &char_handle)) {
1430                 BT_DBG("object path of descriptor = %s", char_handle);
1431                 if (char_handle) {
1432                         ret = __bluetooth_gatt_descriptor_iter(char_handle,
1433                                                 &characteristic);
1434                         BT_DBG("Descriptor read status [%d]", ret);
1435                 }
1436         }
1437
1438         if (user_info) {
1439                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1440                                 ret, &characteristic, user_info->cb, user_info->user_data);
1441         }
1442         bluetooth_gatt_free_char_property(&characteristic);
1443
1444         g_variant_iter_free(char_iter);
1445         g_variant_unref(value);
1446         g_variant_unref(char_value);
1447         BT_DBG("-");
1448 }
1449
1450 BT_EXPORT_API int bltooth_gatt_discover_characteristic_descriptor(
1451                         const char *characteristic_handle)
1452 {
1453         GDBusProxy *properties_proxy = NULL;
1454         GDBusConnection *g_conn;
1455         char *handle;
1456         GError *error = NULL;
1457
1458         BT_CHECK_PARAMETER(characteristic_handle, return);
1459         BT_CHECK_ENABLED(return);
1460
1461         g_conn = _bt_get_system_common_conn();
1462         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1463
1464         properties_proxy = g_dbus_proxy_new_sync(g_conn,
1465                         G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1466                         BT_BLUEZ_NAME,
1467                         characteristic_handle,
1468                         BT_PROPERTIES_INTERFACE,
1469                         NULL, &error);
1470
1471         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1472
1473         handle = g_strdup(characteristic_handle);
1474         g_dbus_proxy_call(properties_proxy,
1475                         "Get",
1476                         g_variant_new("(ss)",
1477                                 GATT_CHAR_INTERFACE, "Descriptors"),
1478                         G_DBUS_CALL_FLAGS_NONE,
1479                         -1, NULL,
1480                         (GAsyncReadyCallback)bluetooth_gatt_get_char_desc_cb,
1481                         (gpointer)handle);
1482
1483         return BLUETOOTH_ERROR_NONE;
1484 }
1485
1486 static void __bluetooth_internal_read_desc_cb(GObject *source_object,
1487                         GAsyncResult *res,
1488                         gpointer user_data)
1489 {
1490         GError *error = NULL;
1491         GDBusConnection *system_gconn = NULL;
1492         GVariant *value;
1493         bt_user_info_t *user_info;
1494         GByteArray *gp_byte_array = NULL;
1495         GVariantIter *iter;
1496         guint8 g_byte;
1497         int att_ecode = 0;
1498         bt_gatt_resp_data_t *resp_data = user_data;
1499
1500         BT_DBG("+");
1501
1502         system_gconn = _bt_get_system_common_conn();
1503         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1504
1505         user_info = _bt_get_user_data(BT_COMMON);
1506         if (!user_info) {
1507                 if (error) {
1508                         BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
1509                         g_clear_error(&error);
1510                         g_free(resp_data);
1511                         return;
1512                 }
1513                 g_free(resp_data);
1514                 g_variant_unref(value);
1515                 return;
1516         }
1517
1518         if (error) {
1519                 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
1520                 g_clear_error(&error);
1521
1522                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1523                                 att_ecode, resp_data,
1524                                 user_info->cb, user_info->user_data);
1525                 g_free(resp_data);
1526                 return;
1527         }
1528
1529         gp_byte_array = g_byte_array_new();
1530         g_variant_get(value, "(ay)", &iter);
1531
1532         while (g_variant_iter_loop(iter, "y", &g_byte))
1533                 g_byte_array_append(gp_byte_array, &g_byte, 1);
1534
1535         if (gp_byte_array->len != 0) {
1536                 resp_data->len = gp_byte_array->len;
1537                 resp_data->value = gp_byte_array->data;
1538         }
1539
1540         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1541                         BLUETOOTH_ATT_ERROR_NONE, resp_data,
1542                         user_info->cb, user_info->user_data);
1543         g_free(resp_data);
1544
1545
1546         g_byte_array_free(gp_byte_array, TRUE);
1547         g_variant_iter_free(iter);
1548         g_variant_unref(value);
1549
1550         BT_DBG("-");
1551 }
1552
1553 BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *desc,
1554                                                        gpointer user_data)
1555 {
1556         GDBusConnection *conn;
1557         GVariantBuilder *builder;
1558         guint offset = 0;
1559         bt_gatt_resp_data_t *resp_data;
1560
1561         BT_DBG("+");
1562
1563         BT_CHECK_PARAMETER(desc, return);
1564         BT_CHECK_ENABLED(return);
1565
1566         conn = _bt_get_system_common_conn();
1567         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1568
1569         resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1570         resp_data->user_data = user_data;
1571         resp_data->handle = (char *)desc;
1572
1573         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1574
1575         /*offset*/
1576         g_variant_builder_add(builder, "{sv}", "offset",
1577                                 g_variant_new("q", offset));
1578         /* Device Object path*/
1579 //  g_variant_builder_add(builder, "{sv}", "device",
1580 //  g_variant_new("o", serv_info->serv_path));
1581
1582         g_dbus_connection_call(conn, BT_BLUEZ_NAME, desc, GATT_DESC_INTERFACE,
1583                         "ReadValue", g_variant_new("(a{sv})", builder),
1584                         G_VARIANT_TYPE("(ay)"),
1585                         G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1586                         (GAsyncReadyCallback)__bluetooth_internal_read_desc_cb,
1587                         (gpointer)resp_data);
1588         g_variant_builder_unref(builder);
1589
1590         BT_DBG("-");
1591         return BLUETOOTH_ERROR_NONE;
1592 }
1593
1594 static void __bluetooth_internal_write_desc_cb(GObject *source_object,
1595                                         GAsyncResult *res, gpointer user_data)
1596 {
1597         GError *error = NULL;
1598         bt_user_info_t *user_info;
1599         GDBusConnection *system_gconn = NULL;
1600         GVariant *value;
1601         int att_ecode = BLUETOOTH_ATT_ERROR_NONE;
1602         bt_gatt_resp_data_t *resp_data = user_data;
1603
1604         BT_DBG("+");
1605
1606         system_gconn = _bt_get_system_common_conn();
1607         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1608
1609         user_info = _bt_get_user_data(BT_COMMON);
1610         if (!user_info) {
1611                 if (error) {
1612                         BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
1613                         g_clear_error(&error);
1614                         g_free(resp_data);
1615                         return;
1616                 }
1617                 g_free(resp_data);
1618                 g_variant_unref(value);
1619                 return;
1620         }
1621
1622         if (error) {
1623                 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
1624                 g_clear_error(&error);
1625
1626                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1627                                 att_ecode, resp_data,
1628                                 user_info->cb, user_info->user_data);
1629                 g_free(resp_data);
1630                 return;
1631         }
1632
1633         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1634                                 BLUETOOTH_ATT_ERROR_NONE, resp_data,
1635                         user_info->cb, user_info->user_data);
1636         g_free(resp_data);
1637
1638         g_variant_unref(value);
1639         BT_DBG("-");
1640 }
1641
1642 BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(const char *desc,
1643                         const guint8 *value, int length, gpointer user_data)
1644 {
1645         GVariant *val, *options;
1646         GDBusConnection *conn;
1647         GVariantBuilder *builder1;
1648         GVariantBuilder *builder2;
1649         guint offset = 0;
1650         int i;
1651         bt_gatt_resp_data_t *resp_data;
1652
1653         BT_DBG("+");
1654
1655         BT_CHECK_PARAMETER(desc, return);
1656         BT_CHECK_PARAMETER(value, return);
1657         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1658         BT_CHECK_ENABLED(return);
1659
1660         conn = _bt_get_system_common_conn();
1661         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1662
1663         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1664
1665         for (i = 0; i < length; i++)
1666                 g_variant_builder_add(builder1, "y", value[i]);
1667
1668         val = g_variant_new("ay", builder1);
1669
1670         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1671         /*offset*/
1672         g_variant_builder_add(builder2, "{sv}", "offset",
1673                                 g_variant_new_uint16(offset));
1674
1675         /* Device Object path*/
1676 //      g_variant_builder_add(builder2, "{sv}", "device",
1677 //      g_variant_new_object("o", NULL));
1678
1679         options = g_variant_new("a{sv}", builder2);
1680
1681         resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1682         resp_data->user_data = user_data;
1683         resp_data->handle = (char *)desc;
1684
1685         g_dbus_connection_call(conn, BT_BLUEZ_NAME, desc, GATT_DESC_INTERFACE,
1686                         "WriteValue", g_variant_new("(@ay@a{sv})",
1687                         val, options), NULL,
1688                         G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1689                         (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
1690                         (gpointer)resp_data);
1691
1692         g_variant_builder_unref(builder1);
1693         g_variant_builder_unref(builder2);
1694
1695         BT_DBG("-");
1696         return BLUETOOTH_ERROR_NONE;
1697 }
1698
1699 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle, const char *svc_name)
1700 {
1701         GDBusConnection *conn;
1702         GError *error = NULL;
1703         int ret = BLUETOOTH_ERROR_NONE;
1704
1705         BT_CHECK_PARAMETER(char_handle, return);
1706         BT_CHECK_ENABLED(return);
1707
1708         BT_INFO_C("### Enable CCCD : %s [%s]", char_handle + 15, svc_name);
1709
1710         conn = _bt_get_system_common_conn();
1711         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1712
1713         g_dbus_connection_call_sync(conn,
1714                         BT_BLUEZ_NAME,
1715                         char_handle,
1716                         GATT_CHAR_INTERFACE,
1717                         "StartNotify",
1718                         NULL,
1719                         NULL,
1720                         G_DBUS_CALL_FLAGS_NONE,
1721                         GATT_DEFAULT_TIMEOUT, NULL, &error);
1722
1723         if (error) {
1724                 g_dbus_error_strip_remote_error(error);
1725                 BT_ERR_C("### Watch Failed: %s", error->message);
1726                 if (g_strrstr(error->message, "Already notifying"))
1727                         ret = BLUETOOTH_ERROR_NONE;
1728                 else if (g_strrstr(error->message, "In Progress"))
1729                         ret = BLUETOOTH_ERROR_IN_PROGRESS;
1730                 else if (g_strrstr(error->message, "Operation is not supported"))
1731                         ret = BLUETOOTH_ERROR_NOT_SUPPORT;
1732 /*failed because of either Insufficient Authorization or Write Not Permitted */
1733                 else if (g_strrstr(error->message, "Write not permitted") ||
1734                                 g_strrstr(error->message, "Operation Not Authorized"))
1735                         ret = BLUETOOTH_ERROR_PERMISSION_DEINED;
1736 /* failed because of either Insufficient Authentication,
1737         Insufficient Encryption Key Size, or Insufficient Encryption. */
1738                 else if (g_strrstr(error->message, "Not paired"))
1739                         ret = BLUETOOTH_ERROR_NOT_PAIRED;
1740                 else
1741                         ret = BLUETOOTH_ERROR_INTERNAL;
1742
1743                 g_clear_error(&error);
1744         }
1745
1746         return ret;
1747 }
1748
1749 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle)
1750 {
1751         GDBusConnection *conn;
1752         GError *error = NULL;
1753         int ret = BLUETOOTH_ERROR_NONE;
1754         BT_CHECK_PARAMETER(char_handle, return);
1755
1756         BT_CHECK_ENABLED(return);
1757
1758         BT_INFO("Disable CCCD : %s", char_handle);
1759
1760         conn = _bt_get_system_common_conn();
1761         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1762
1763         g_dbus_connection_call_sync(conn,
1764                         BT_BLUEZ_NAME,
1765                         char_handle,
1766                         GATT_CHAR_INTERFACE,
1767                         "StopNotify",
1768                         NULL,
1769                         NULL,
1770                         G_DBUS_CALL_FLAGS_NONE,
1771                         GATT_DEFAULT_TIMEOUT, NULL, &error);
1772
1773         if (error) {
1774                 BT_ERR("Watch Failed: %s", error->message);
1775                 g_clear_error(&error);
1776                 ret =  BLUETOOTH_ERROR_INTERNAL;
1777         }
1778
1779         return ret;
1780 }
1781
1782 void __bt_uuid_hex_to_string(unsigned char *uuid, char *str)
1783 {
1784         uint32_t uuid0, uuid4;
1785         uint16_t uuid1, uuid2, uuid3, uuid5;
1786
1787         memcpy(&uuid0, &(uuid[0]), 4);
1788         memcpy(&uuid1, &(uuid[4]), 2);
1789         memcpy(&uuid2, &(uuid[6]), 2);
1790         memcpy(&uuid3, &(uuid[8]), 2);
1791         memcpy(&uuid4, &(uuid[10]), 4);
1792         memcpy(&uuid5, &(uuid[14]), 2);
1793
1794         snprintf((char *)str, BLUETOOTH_UUID_STRING_MAX, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
1795                         ntohl(uuid0), ntohs(uuid1),
1796                         ntohs(uuid2), ntohs(uuid3),
1797                         ntohl(uuid4), ntohs(uuid5));
1798         return;
1799 }
1800
1801
1802 static void __bt_fill_service_handle_informations(bt_services_browse_info_t *props,
1803                 bt_gatt_handle_info_t *svcs)
1804 {
1805         int count;
1806
1807         if (props->count == 0)
1808                 return;
1809
1810         svcs->count = props->count;
1811
1812         for (count = 0; count < props->count; count++) {
1813                 BT_DBG("[%d] %s  instance_id [%d] Is Primary [%d]",
1814                                 count, props->uuids[count], props->inst_id[count], props->primary[count]);
1815                 g_strlcpy(svcs->uuids[count], props->uuids[count],
1816                                 BLUETOOTH_UUID_STRING_MAX);
1817                 svcs->inst_id[count] = props->inst_id[count];
1818         }
1819 }
1820
1821 static void __bt_fill_char_handle_informations(bt_char_browse_info_t *props, bt_gatt_service_property_t *service)
1822 {
1823         int count;
1824         char uuid_string[BLUETOOTH_UUID_STRING_MAX];
1825
1826         service->char_handle.count = props->count;
1827
1828         /* Before filling all char handles, fill the service's UUID and instance ID */
1829         __bt_uuid_hex_to_string(props->svc_uuid, uuid_string);
1830         service->uuid = g_strdup(uuid_string);
1831         service->primary = TRUE;
1832
1833         /* Now fill all the char handles [UUID and Instance ID's]*/
1834         for (count = 0; count < props->count; count++) {
1835                 BT_DBG("[%d] %s  instance_id [%d] properties [%d]",
1836                                 count, props->uuids[count], props->inst_id[count], props->props[count]);
1837
1838                 g_strlcpy(service->char_handle.uuids[count],
1839                                 props->uuids[count],
1840                                 BLUETOOTH_UUID_STRING_MAX);
1841
1842                 service->char_handle.inst_id[count] = props->inst_id[count];
1843         }
1844 }
1845
1846 static void __bt_fill_desc_handle_informations(bt_descriptor_browse_info_t *props,
1847                 bt_gatt_char_property_t *charc)
1848 {
1849         int count;
1850         char uuid_string[BLUETOOTH_UUID_STRING_MAX];
1851
1852         charc->char_desc_handle.count = props->count;
1853
1854         /* Before filling all desc handles, fill the charac's UUID and instance ID */
1855         __bt_uuid_hex_to_string(props->char_uuid, uuid_string);
1856         charc->uuid = g_strdup(uuid_string);
1857
1858         /* Now fill all the descriptor handles [UUID and Instance ID's]*/
1859         for (count = 0; count < props->count; count++) {
1860                 BT_DBG("[%d] %s  instance_id [%d]",
1861                                 count, props->uuids[count], props->inst_id[count]);
1862
1863                 g_strlcpy(charc->char_desc_handle.uuids[count],
1864                                 props->uuids[count],
1865                                 BLUETOOTH_UUID_STRING_MAX);
1866
1867                 charc->char_desc_handle.inst_id[count] = props->inst_id[count];
1868         }
1869         charc->permission = props->char_props_map;
1870         __convert_permission_flag_to_str(charc->permission);
1871 }
1872
1873
1874 BT_EXPORT_API int bluetooth_gatt_client_init(
1875                 int *client_id,
1876                 const bluetooth_device_address_t *address,
1877                 gatt_client_cb_func_ptr callback_ptr)
1878 {
1879         int ret = BLUETOOTH_ERROR_NONE;
1880         bt_event_info_t *event_info;
1881         int *count;
1882
1883         BT_CHECK_PARAMETER(client_id, return);
1884         BT_CHECK_PARAMETER(callback_ptr, return);
1885         BT_CHECK_ENABLED(return);
1886
1887         BT_INIT_PARAMS();
1888         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1889
1890         g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
1891
1892         ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_REGISTER,
1893                         in_param1, in_param2, in_param3, in_param4, &out_param);
1894
1895         /* App ID -1 is invalid */
1896         if (ret == BLUETOOTH_ERROR_NONE) {
1897
1898                 *client_id = g_array_index(out_param, int, 0);
1899
1900                 BT_INFO("GATT Client Registered successfully: Client instance ID [%d]", *client_id);
1901
1902                 event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
1903
1904                 if (event_info) {
1905                         count = (int*)event_info->user_data;
1906
1907                         BT_INFO("Total num of GATT client instances [%d]", *count);
1908
1909                         /* Increement the count */
1910                         *count += 1;
1911                 } else {
1912                         BT_INFO("No GATT Client instances found in this application: Set User data");
1913                         count = g_malloc0(sizeof(int));
1914                         *count = 1;
1915
1916                         /* Register event handler for GATT */
1917                         _bt_register_event(BT_GATT_CLIENT_EVENT,
1918                                         (void *)callback_ptr,
1919                                         (void *)count);
1920                         _bt_set_user_data(BT_GATT_CLIENT, (void *)callback_ptr, NULL);
1921                 }
1922         } else
1923                 BT_ERR("GATT Client Registration failed!! ret [%d]", ret);
1924
1925         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1926         return ret;
1927 }
1928
1929
1930
1931 /* GATT Client*/
1932 BT_EXPORT_API int bluetooth_gatt_client_get_primary_services(
1933                 const bluetooth_device_address_t *address, /* Remote GATT Server */
1934                 bt_gatt_handle_info_t *prim_svc) /* UUID & instance_id */
1935 {
1936
1937         int result = BLUETOOTH_ERROR_NONE;
1938         bt_services_browse_info_t service_props;
1939
1940         BT_CHECK_PARAMETER(address, return);
1941         BT_CHECK_PARAMETER(prim_svc, return);
1942         BT_CHECK_ENABLED(return);
1943
1944         BT_INIT_PARAMS();
1945         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1946         g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
1947
1948         result = _bt_send_request(BT_BLUEZ_SERVICE,
1949                         BT_GATT_GET_PRIMARY_SERVICES,
1950                         in_param1, in_param2, in_param3, in_param4, &out_param);
1951
1952         if (BLUETOOTH_ERROR_NONE != result)
1953                 goto done;
1954
1955         memset(&service_props, 0x00, sizeof(bt_services_browse_info_t));
1956
1957         service_props = g_array_index(
1958                         out_param, bt_services_browse_info_t, 0);
1959
1960         __bt_fill_service_handle_informations(
1961                         &service_props, prim_svc);
1962
1963 done:
1964         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1965         return result;
1966 }
1967
1968 BT_EXPORT_API int bluetooth_gatt_client_get_service_property(
1969                 const char *address,
1970                 bt_gatt_handle_property_t *service_handle,
1971                 bt_gatt_service_property_t *service)
1972 {
1973         int result = BLUETOOTH_ERROR_NONE;
1974         bluetooth_gatt_client_svc_prop_info_t svc_prop;
1975         bt_char_browse_info_t char_handles_info;
1976
1977         BT_CHECK_PARAMETER(address, return);
1978         BT_CHECK_PARAMETER(service_handle, return);
1979         BT_CHECK_PARAMETER(service, return);
1980         BT_CHECK_ENABLED(return);
1981
1982         /* Call to bt-service (sync) and send address and service_handle info */
1983         BT_INIT_PARAMS();
1984         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1985
1986         memset(&svc_prop, 0x00, sizeof(bluetooth_gatt_client_svc_prop_info_t));
1987         /* All characteristics handles are discovered */
1988         memset(&char_handles_info, 0x00, sizeof(bt_char_browse_info_t));
1989
1990         svc_prop.svc.instance_id = service_handle->instance_id;
1991         memcpy(&svc_prop.svc.uuid, &service_handle->uuid, 16);
1992
1993         _bt_convert_addr_string_to_type(svc_prop.device_address.addr, address);
1994
1995         g_array_append_vals(in_param1, &svc_prop, sizeof(bluetooth_gatt_client_svc_prop_info_t));
1996
1997         result = _bt_send_request(BT_BLUEZ_SERVICE,
1998                         BT_GATT_GET_SERVICE_PROPERTIES,
1999                         in_param1, in_param2, in_param3, in_param4, &out_param);
2000
2001         if (BLUETOOTH_ERROR_NONE != result)
2002                 goto done;
2003
2004         char_handles_info = g_array_index(
2005                         out_param, bt_char_browse_info_t, 0);
2006         __bt_fill_char_handle_informations(&char_handles_info,
2007                         service);
2008         /* TODO Get all Included Services */
2009
2010 done:
2011         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2012         return result;
2013 }
2014
2015 BT_EXPORT_API int bluetooth_gatt_client_get_characteristics_property(
2016                 const char *address,
2017                 bt_gatt_handle_property_t *service_handle,
2018                 bt_gatt_handle_property_t *char_handle,
2019                 bt_gatt_char_property_t *char_property)
2020 {
2021         int result = BLUETOOTH_ERROR_NONE;
2022         bt_descriptor_browse_info_t desc_handles_info;
2023         bluetooth_gatt_client_char_prop_info_t char_prop;
2024
2025         BT_CHECK_PARAMETER(address, return);
2026         BT_CHECK_PARAMETER(service_handle, return);
2027         BT_CHECK_PARAMETER(char_handle, return);
2028         BT_CHECK_PARAMETER(char_property, return);
2029         BT_CHECK_ENABLED(return);
2030
2031
2032         /* Call to bt-service (sync) and send address service_handle info & char handle info  */
2033         BT_INIT_PARAMS();
2034         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2035
2036         memset(&char_prop, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2037         char_prop.svc.instance_id = service_handle->instance_id;
2038         memcpy(&char_prop.svc.uuid, &service_handle->uuid, 16);
2039
2040         char_prop.characteristic.instance_id = char_handle->instance_id;
2041         memcpy(&char_prop.characteristic.uuid, &char_handle->uuid, 16);
2042
2043         _bt_convert_addr_string_to_type(char_prop.device_address.addr, address);
2044
2045         g_array_append_vals(in_param1, &char_prop, sizeof(bluetooth_gatt_client_char_prop_info_t));
2046
2047         result = _bt_send_request(BT_BLUEZ_SERVICE,
2048                         BT_GATT_GET_CHARACTERISTIC_PROPERTIES,
2049                         in_param1, in_param2, in_param3, in_param4, &out_param);
2050
2051         if (BLUETOOTH_ERROR_NONE != result)
2052                 goto done;
2053
2054         /* All descriptors handles are discovered */
2055         memset(&desc_handles_info, 0x00, sizeof(bt_descriptor_browse_info_t));
2056
2057         desc_handles_info = g_array_index(
2058                         out_param, bt_descriptor_browse_info_t, 0);
2059
2060         __bt_fill_desc_handle_informations(&desc_handles_info,
2061                         char_property);
2062
2063 done:
2064         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2065         return result;
2066         /* Call to bt-service (sync) and send address, service_handle & char_handle infos */
2067
2068         /* After result is fetched, extract descriptor handles (UUID's & instance_id's) */
2069
2070         /* Fill the info in *char_prop */
2071
2072         /*No: Before returning, call bluetooth_gatt_client_read_characteristic_value as
2073                 an asyn function and leave every thing else in the callback */
2074 }
2075
2076 BT_EXPORT_API int bluetooth_gatt_client_get_char_descriptor_property(
2077                 const char *address,
2078                 bt_gatt_handle_property_t *service_handle,
2079                 bt_gatt_handle_property_t *char_handle,
2080                 bt_gatt_handle_property_t *descriptor_handle,
2081                 bt_gatt_char_descriptor_property_t *desc_prop)
2082 {
2083         char uuid_string[BLUETOOTH_UUID_STRING_MAX];
2084
2085         BT_CHECK_PARAMETER(address, return);
2086         BT_CHECK_PARAMETER(service_handle, return);
2087         BT_CHECK_PARAMETER(char_handle, return);
2088         BT_CHECK_PARAMETER(descriptor_handle, return);
2089         BT_CHECK_PARAMETER(desc_prop, return);
2090         /* No Need to Call to bt-service (sync) and send address, service_handle,
2091                 char_handle & descriptor handle infos */
2092         /* After result is fetched, extract descriptior handles (UUID's & instance_id's) */
2093         /* Fill the info in *desc_prop */
2094         __bt_uuid_hex_to_string(descriptor_handle->uuid, uuid_string);
2095
2096         /* Before filling all desc handles, fill the charac's UUID and instance ID */
2097         desc_prop->uuid = g_strdup(uuid_string);
2098
2099         return BLUETOOTH_ERROR_NONE;
2100         /* No: Before returning, call bluetooth_gatt_client_read_descriptor_value
2101                 as an asyn function and leave every thing else in the callback */
2102 }
2103
2104
2105 static gboolean  bluetooth_gatt_client_notify_channel_watch_cb(GIOChannel *gio,
2106                                         GIOCondition cond, gpointer data)
2107 {
2108         bt_gatt_characteristic_notify_info_t *chr_info = (bt_gatt_characteristic_notify_info_t *)data;
2109
2110         if (!chr_info) {
2111                 BT_ERR("chr_info is invalid");
2112                 return FALSE;
2113         }
2114
2115         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
2116                 BT_ERR("Error : GIOCondition %d, [%s]", cond, chr_info->UUID);
2117                 g_io_channel_shutdown(gio, TRUE, NULL);
2118                 g_io_channel_unref(gio);
2119
2120                 gatt_characteristic_notify_list = g_slist_remove(gatt_characteristic_notify_list, chr_info);
2121                 g_free(chr_info);
2122
2123                 return FALSE;
2124         }
2125
2126         if (cond & G_IO_IN) {
2127                 GIOStatus status = G_IO_STATUS_NORMAL;
2128                 GError *err = NULL;
2129                 char *buffer = NULL;
2130                 gsize len = 0;
2131                 bt_event_info_t *event_info;
2132
2133                 buffer = g_malloc0(chr_info->mtu + 1);
2134                 memset(buffer, 0, chr_info->mtu + 1);
2135
2136                 status = g_io_channel_read_chars(gio, buffer,
2137                                 chr_info->mtu, &len, &err);
2138                 if (status != G_IO_STATUS_NORMAL) {
2139                         BT_ERR("IO Channel read is failed with %d", status);
2140                         g_free(buffer);
2141                         if (err) {
2142                                 BT_ERR("IO Channel read error [%s]", err->message);
2143                                 if (status == G_IO_STATUS_ERROR) {
2144                                         BT_ERR("cond : %d", cond);
2145                                         g_error_free(err);
2146                                         g_io_channel_shutdown(gio, TRUE, NULL);
2147                                         g_io_channel_unref(gio);
2148
2149                                         gatt_characteristic_notify_list = g_slist_remove(gatt_characteristic_notify_list, chr_info);
2150                                         g_free(chr_info);
2151                                         return FALSE;
2152                                 }
2153                                 g_error_free(err);
2154                         }
2155                         return FALSE;
2156                 }
2157
2158                 if (len > 0 && len < chr_info->mtu) {
2159                         bt_gatt_char_property_t char_val;
2160 //                       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);
2161
2162                         memcpy(char_val.prop.uuid, chr_info->UUID, 16);
2163                         memcpy(char_val.value, buffer, len);
2164                         char_val.val_len = len;
2165                         memcpy(char_val.address, chr_info->address, 18);
2166
2167                         event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
2168                         if (event_info) {
2169                                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED,
2170                                                         BLUETOOTH_ERROR_NONE, &char_val,
2171                                                         event_info->cb, event_info->user_data);
2172                         } else {
2173                                 BT_ERR("event_info failed");
2174                         }
2175
2176                 } else
2177                         BT_ERR("Packet corrupted");
2178
2179                 g_free(buffer);
2180
2181                 return TRUE;
2182         }
2183
2184         return TRUE;
2185 }
2186
2187 #ifndef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
2188 static bt_gatt_characteristic_notify_info_t * bluetooth_gatt_client_get_characteristic_notify_info(unsigned  char *handle , int id)
2189 {
2190         GSList *l;
2191
2192         for (l = gatt_characteristic_notify_list; l != NULL; l = l->next) {
2193                 bt_gatt_characteristic_notify_info_t *info = l->data;
2194                 if (memcmp(info->UUID, handle, 16) == 0 && info->id == id)
2195                         return info;
2196         }
2197         return NULL;
2198 }
2199 #endif
2200
2201 static bt_gatt_characteristic_notify_info_t *  bluetooth_gatt_client_create_watch_io(int fd, int id, int mtu, char * address, unsigned char *uuid)
2202 {
2203         GIOChannel *channel;
2204         bt_gatt_characteristic_notify_info_t *chr_info;
2205
2206         chr_info = g_malloc0(sizeof(bt_gatt_characteristic_notify_info_t));
2207         chr_info->notify_fd = fd;
2208         chr_info->id = id;
2209         chr_info->mtu = mtu;
2210         g_strlcpy(chr_info->address, address, 18);
2211         memcpy(chr_info->UUID, uuid, 16);
2212
2213         channel = g_io_channel_unix_new(fd);
2214
2215         chr_info->io_channel = channel;
2216
2217         g_io_channel_set_encoding(channel, NULL, NULL);
2218         g_io_channel_set_buffered(channel, FALSE);
2219         g_io_channel_set_close_on_unref(channel, TRUE);
2220         g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
2221
2222         chr_info->watch_id = g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP),
2223                          bluetooth_gatt_client_notify_channel_watch_cb, chr_info);
2224
2225         return chr_info;
2226
2227 }
2228
2229 BT_EXPORT_API int bluetooth_gatt_client_watch_characteristics(
2230                         const char *address,
2231                         bt_gatt_handle_property_t *service_handle,
2232                         bt_gatt_handle_property_t *char_handle,
2233                         int client_id,
2234                         gboolean is_notify,
2235                         gboolean is_indicate)
2236 {
2237         int result = BLUETOOTH_ERROR_NONE;
2238         bluetooth_gatt_client_char_prop_info_t param;
2239         bt_gatt_characteristic_notify_info_t *chr_info;
2240
2241         BT_CHECK_PARAMETER(address, return);
2242         BT_CHECK_PARAMETER(service_handle, return);
2243         BT_CHECK_PARAMETER(char_handle, return);
2244
2245 #ifndef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
2246         chr_info = bluetooth_gatt_client_get_characteristic_notify_info(char_handle->uuid , char_handle->instance_id);
2247         if (chr_info && !is_notify) {
2248                 BT_INFO("Already CCCD enabled. fd %d", chr_info->notify_fd);
2249
2250                 if (chr_info->watch_id > 0)
2251                         g_source_remove(chr_info->watch_id);
2252
2253                 if (chr_info->io_channel) {
2254                         g_io_channel_shutdown(chr_info->io_channel, TRUE, NULL);
2255                         g_io_channel_unref(chr_info->io_channel);
2256                 }
2257
2258                 gatt_characteristic_notify_list = g_slist_remove(gatt_characteristic_notify_list, chr_info);
2259
2260                 g_free(chr_info);
2261
2262                 return result;
2263         }
2264 #endif
2265
2266         /* ASync Function, result expected in callback from bt-service */
2267
2268         BT_INIT_PARAMS();
2269         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2270
2271         memset(&param, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2272
2273         memcpy(&param.svc.uuid, service_handle->uuid, 16);
2274         param.svc.instance_id = service_handle->instance_id;
2275
2276         memcpy(&param.characteristic.uuid, char_handle->uuid, 16);
2277         param.characteristic.instance_id = char_handle->instance_id;
2278
2279         _bt_convert_addr_string_to_type(param.device_address.addr, address);
2280
2281         g_array_append_vals(in_param1, &param, sizeof(bluetooth_gatt_client_char_prop_info_t));
2282         g_array_append_vals(in_param2, &client_id, sizeof(int));
2283         g_array_append_vals(in_param3, &is_notify, sizeof(gboolean));
2284         g_array_append_vals(in_param4, &is_indicate, sizeof(gboolean));
2285
2286 #ifdef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
2287         result = _bt_send_request(BT_BLUEZ_SERVICE,
2288                         BT_GATT_WATCH_CHARACTERISTIC,
2289                         in_param1, in_param2, in_param3, in_param4, &out_param);
2290
2291         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2292
2293         BT_INFO("Result [%d]", result);
2294         return result;
2295 #endif
2296
2297         GUnixFDList *out_fd_list = NULL;
2298         char *svc_name = NULL;
2299         char  str_uuid[37];
2300
2301         _bt_convert_uuid_type_to_string(str_uuid, param.svc.uuid);
2302         bluetooth_get_uuid_name(str_uuid, &svc_name);
2303
2304         _bt_convert_uuid_type_to_string(str_uuid, param.characteristic.uuid);
2305
2306         BT_INFO_C("### Request subscription Notify : %s [%s]", str_uuid, svc_name);
2307         g_free(svc_name);
2308
2309         result  = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_WATCH_CHARACTERISTIC,
2310                                                         in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
2311         if (result != BLUETOOTH_ERROR_NONE) {
2312                 BT_ERR("Fail to get Nofify FD. result %d", result);
2313                 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2314                 return result;
2315         }
2316
2317         if (is_indicate == false) {
2318                 if (NULL == out_fd_list) {
2319                         BT_ERR("out_fd_list is NULL");
2320                         result = BLUETOOTH_ERROR_INTERNAL;
2321                 } else {
2322                         int *fd_list_array;
2323                         int len = 0;
2324                         int mtu;
2325                         int fd = -1;
2326
2327                         fd_list_array = g_unix_fd_list_steal_fds(out_fd_list, &len);
2328                         BT_DBG("Num fds in fd_list is : %d, fd_list[0]: %d", len, fd_list_array[0]);
2329                         fd = fd_list_array[0];
2330                         mtu =  g_array_index(out_param, int, 0);
2331
2332                         BT_INFO("Acquired characteristic Notify FD %d, mtu %d", fd, mtu);
2333                         chr_info = bluetooth_gatt_client_create_watch_io(fd, char_handle->instance_id, mtu, (char *)address, char_handle->uuid);
2334
2335                         gatt_characteristic_notify_list = g_slist_append(gatt_characteristic_notify_list, chr_info);
2336
2337                         g_free(fd_list_array);
2338                         g_object_unref(out_fd_list);
2339                 }
2340         }
2341
2342         /*result = _bt_send_request(BT_BLUEZ_SERVICE,
2343                         BT_GATT_WATCH_CHARACTERISTIC,
2344                         in_param1, in_param2, in_param3, in_param4, &out_param);*/
2345
2346         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2347
2348         return result;
2349 }
2350
2351 BT_EXPORT_API int bluetooth_gatt_client_read_characteristic_value(
2352                 const char *address,
2353                 bt_gatt_handle_property_t *service_handle,
2354                 bt_gatt_handle_property_t *char_handle)
2355 {
2356         int result = BLUETOOTH_ERROR_NONE;
2357         bt_user_info_t *user_info;
2358         bluetooth_gatt_client_char_prop_info_t param;
2359
2360         BT_CHECK_PARAMETER(address, return);
2361         BT_CHECK_PARAMETER(service_handle, return);
2362         BT_CHECK_PARAMETER(char_handle, return);
2363
2364         user_info = _bt_get_user_data(BT_GATT_CLIENT);
2365         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2366
2367         BT_INIT_PARAMS();
2368         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2369
2370         /* Async Function, result expected in callback from bt-service */
2371         /* Call to bt-service (sync) and send address service_handle info & char handle info  */
2372         memset(&param, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2373
2374         memcpy(&param.svc.uuid, service_handle->uuid, 16);
2375         param.svc.instance_id = service_handle->instance_id;
2376
2377         memcpy(&param.characteristic.uuid, char_handle->uuid, 16);
2378         param.characteristic.instance_id = char_handle->instance_id;
2379
2380         _bt_convert_addr_string_to_type(param.device_address.addr, address);
2381
2382         g_array_append_vals(in_param1, &param,
2383                         sizeof(bluetooth_gatt_client_char_prop_info_t));
2384
2385         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_GATT_READ_CHARACTERISTIC,
2386                         in_param1, in_param2, in_param3, in_param4,
2387                         user_info->cb, user_info->user_data);
2388
2389         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2390         return result;
2391 }
2392
2393 BT_EXPORT_API int bluetooth_gatt_client_read_descriptor_value(
2394                 const char *address,
2395                 bt_gatt_handle_property_t *service_handle,
2396                 bt_gatt_handle_property_t *char_handle,
2397                 bt_gatt_handle_property_t *descriptor_handle)
2398 {
2399         int result = BLUETOOTH_ERROR_NONE;
2400         bt_user_info_t *user_info;
2401         bluetooth_gatt_client_desc_prop_info_t param;
2402
2403         BT_CHECK_PARAMETER(address, return);
2404         BT_CHECK_PARAMETER(service_handle, return);
2405         BT_CHECK_PARAMETER(char_handle, return);
2406         BT_CHECK_PARAMETER(descriptor_handle, return);
2407
2408         user_info = _bt_get_user_data(BT_GATT_CLIENT);
2409         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2410
2411         BT_INIT_PARAMS();
2412         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2413
2414         /* Async Function, result expected in callback from bt-service */
2415         memset(&param, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2416
2417         memcpy(&param.svc.uuid, service_handle->uuid, 16);
2418         param.svc.instance_id = service_handle->instance_id;
2419
2420         memcpy(&param.characteristic.uuid, char_handle->uuid, 16);
2421         param.characteristic.instance_id = char_handle->instance_id;
2422
2423         memcpy(&param.descriptor.uuid, descriptor_handle->uuid, 16);
2424         param.descriptor.instance_id = descriptor_handle->instance_id;
2425
2426         _bt_convert_addr_string_to_type(param.device_address.addr, address);
2427
2428         g_array_append_vals(in_param1, &param,
2429                         sizeof(bluetooth_gatt_client_desc_prop_info_t));
2430
2431         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_GATT_READ_DESCRIPTOR_VALUE,
2432                         in_param1, in_param2, in_param3, in_param4,
2433                         user_info->cb, user_info->user_data);
2434
2435         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2436         return result;
2437 }
2438
2439
2440 static bt_gatt_characteristic_write_info_t *  bluetooth_gatt_client_get_characteristic_fd(unsigned  char *handle, int id)
2441 {
2442         GSList *l;
2443         char  str[37];
2444
2445         for (l = gatt_characteristic_write_list; l != NULL; l = l->next) {
2446                 bt_gatt_characteristic_write_info_t *info = l->data;
2447
2448                 if (memcmp(info->UUID, handle, 16) ==  0 &&  info->id == id)
2449                         return info;
2450         }
2451
2452         _bt_convert_uuid_type_to_string(str, handle);
2453         BT_ERR("Unable to get characteristic fd. [%s] id [ %d]", str, id);
2454         return NULL;
2455 }
2456
2457 static gboolean  bluetooth_gatt_client_write_channel_watch_cb(GIOChannel *gio,
2458                                         GIOCondition cond, gpointer data)
2459 {
2460         bt_gatt_characteristic_write_info_t *chr_info = (bt_gatt_characteristic_write_info_t *)data;
2461
2462         if (!chr_info)
2463                 return FALSE;
2464
2465         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
2466                 char  uuid_str[37];
2467                 _bt_convert_uuid_type_to_string(uuid_str, chr_info->UUID);
2468                 BT_ERR("Error : GIOCondition %d, [%s]", cond, uuid_str);
2469                 g_io_channel_shutdown(gio, TRUE, NULL);
2470                 g_io_channel_unref(gio);
2471
2472                 gatt_characteristic_write_list = g_slist_remove(gatt_characteristic_write_list, chr_info);
2473                 g_free(chr_info);
2474
2475                 return FALSE;
2476         }
2477
2478         return TRUE;
2479 }
2480
2481 static int  bluetooth_gatt_client_write_characteristics_value_to_fd(
2482                          int fd, const guint8 *value, int length, int mtu,
2483                         gpointer user_data)
2484 {
2485         int written;
2486         int att_result = BLUETOOTH_ERROR_NONE;
2487         BT_CHECK_PARAMETER(value, return);
2488         written = write(fd, value, length);
2489         if (written != length) {
2490                 att_result = BLUETOOTH_ERROR_INTERNAL;
2491                 BT_ERR("write data failed.  ret : %d ", written);
2492         }
2493
2494         return att_result;
2495 }
2496
2497 static void  bluetooth_gatt_client_create_write_io_channel(int fd, unsigned char * uuid, int id, int mtu)
2498 {
2499         bt_gatt_characteristic_write_info_t *chr_info;
2500         GIOChannel *channel;
2501
2502         chr_info = g_malloc0(sizeof(bt_gatt_characteristic_write_info_t));
2503         chr_info->write_fd = fd;
2504         chr_info->id = id;
2505         chr_info->mtu = mtu;
2506
2507         memcpy(chr_info->UUID, uuid, 16);
2508         channel = g_io_channel_unix_new(fd);
2509         g_io_channel_set_encoding(channel, NULL, NULL);
2510         g_io_channel_set_buffered(channel, FALSE);
2511         g_io_channel_set_close_on_unref(channel, TRUE);
2512         g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
2513         g_io_add_watch(channel, (G_IO_ERR | G_IO_HUP | G_IO_NVAL),
2514                          bluetooth_gatt_client_write_channel_watch_cb, chr_info);
2515
2516         gatt_characteristic_write_list = g_slist_append(gatt_characteristic_write_list, chr_info);
2517
2518 }
2519
2520 BT_EXPORT_API int bluetooth_gatt_client_write_characteristic_value_by_type(
2521                 const char *address,
2522                 bt_gatt_handle_property_t *service_handle,
2523                 bt_gatt_handle_property_t *char_handle,
2524                 bluetooth_gatt_att_data_t *data,
2525                 bluetooth_gatt_write_type_e  write_type)
2526 {
2527         int result = BLUETOOTH_ERROR_NONE;
2528         bt_user_info_t *user_info;
2529         bluetooth_gatt_client_char_prop_info_t param;
2530
2531         BT_CHECK_PARAMETER(address, return);
2532         BT_CHECK_PARAMETER(service_handle, return);
2533         BT_CHECK_PARAMETER(char_handle, return);
2534         BT_CHECK_PARAMETER(data, return);
2535
2536         /* ASync Function, result expected in callback from bt-service */
2537         user_info = _bt_get_user_data(BT_GATT_CLIENT);
2538         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2539
2540         BT_INIT_PARAMS();
2541         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2542
2543         memset(&param, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2544
2545         memcpy(&param.svc.uuid, service_handle->uuid, 16);
2546         param.svc.instance_id = service_handle->instance_id;
2547
2548         memcpy(&param.characteristic.uuid, char_handle->uuid, 16);
2549         param.characteristic.instance_id = char_handle->instance_id;
2550
2551         _bt_convert_addr_string_to_type(param.device_address.addr, address);
2552
2553         g_array_append_vals(in_param1, &param, sizeof(bluetooth_gatt_client_char_prop_info_t));
2554         g_array_append_vals(in_param2, data, sizeof(bluetooth_gatt_att_data_t));
2555         g_array_append_vals(in_param3, &write_type, sizeof(bluetooth_gatt_write_type_e));
2556
2557 #ifdef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
2558         goto done;
2559 #endif
2560
2561         if (write_type == BLUETOOTH_GATT_TYPE_WRITE_NO_RESPONSE) {
2562                 int fd = -1;
2563                 int mtu = 0;
2564                 bt_gatt_characteristic_write_info_t *info;
2565                 info =  bluetooth_gatt_client_get_characteristic_fd(char_handle->uuid, service_handle->instance_id);
2566
2567                 if (info) {
2568                         fd = info->write_fd;
2569                         mtu = info->mtu;
2570                 }
2571
2572                 if (fd < 0) {
2573
2574                         GUnixFDList *out_fd_list = NULL;
2575
2576                         result  = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_ACQUIRE_WRITE,
2577                                         in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
2578
2579                         mtu =  g_array_index(out_param, int, 0);
2580
2581                         if (result != BLUETOOTH_ERROR_NONE) {
2582                                 BT_ERR("Fail to get Write FD. result %d", result);
2583                                 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2584                                 return result;
2585                         } else if (NULL == out_fd_list) {
2586                                 BT_ERR("out_fd_list is NULL");
2587                                 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2588                                 return BLUETOOTH_ERROR_INTERNAL;
2589                         } else {
2590                                 int *fd_list_array;
2591                                 int len = 0;
2592
2593                                 fd_list_array = g_unix_fd_list_steal_fds(out_fd_list, &len);
2594                                 fd = fd_list_array[0];
2595
2596                                 g_free(fd_list_array);
2597                                 g_object_unref(out_fd_list);
2598                         }
2599                         BT_INFO("Acquired characteristic Write FD %d, mtu %d", fd, mtu);
2600
2601                         if (fd > -1) {
2602                                 bluetooth_gatt_client_create_write_io_channel(fd, char_handle->uuid, service_handle->instance_id, mtu);
2603
2604                                 result =  bluetooth_gatt_client_write_characteristics_value_to_fd(fd, data->data, data->length, mtu, NULL);
2605
2606                         } else {
2607                                 BT_ERR("characteristic info  FD is invalid");
2608                                 goto done;
2609                         }
2610
2611                 } else {
2612                         result =  bluetooth_gatt_client_write_characteristics_value_to_fd(fd, data->data, data->length, mtu, NULL);
2613                 }
2614
2615         } else {
2616 done:
2617                 result = _bt_send_request_async(BT_BLUEZ_SERVICE,
2618                         BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE,
2619                         in_param1, in_param2, in_param3, in_param4,
2620                         user_info->cb, user_info->user_data);
2621         }
2622
2623         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2624
2625         return result;
2626 }
2627
2628 BT_EXPORT_API int bluetooth_gatt_client_write_descriptor_value(
2629                 const char *address,
2630                 bt_gatt_handle_property_t *service_handle,
2631                 bt_gatt_handle_property_t *char_handle,
2632                 bt_gatt_handle_property_t *descriptor_handle,
2633                 bluetooth_gatt_att_data_t *data,
2634                 bluetooth_gatt_write_type_e  write_type)
2635 {
2636         int result = BLUETOOTH_ERROR_NONE;
2637         bt_user_info_t *user_info;
2638         bluetooth_gatt_client_desc_prop_info_t param;
2639
2640         BT_CHECK_PARAMETER(address, return);
2641         BT_CHECK_PARAMETER(service_handle, return);
2642         BT_CHECK_PARAMETER(char_handle, return);
2643         BT_CHECK_PARAMETER(descriptor_handle, return);
2644         BT_CHECK_PARAMETER(data, return);
2645
2646         /* Async Function, result expected in callback from bt-service */
2647         user_info = _bt_get_user_data(BT_GATT_CLIENT);
2648         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2649
2650         BT_INIT_PARAMS();
2651         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2652
2653         memset(&param, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2654
2655         memcpy(&param.svc.uuid, service_handle->uuid, 16);
2656         param.svc.instance_id = service_handle->instance_id;
2657
2658         memcpy(&param.characteristic.uuid, char_handle->uuid, 16);
2659         param.characteristic.instance_id = char_handle->instance_id;
2660
2661         memcpy(&param.descriptor.uuid, descriptor_handle->uuid, 16);
2662         param.descriptor.instance_id = descriptor_handle->instance_id;
2663
2664         _bt_convert_addr_string_to_type(param.device_address.addr, address);
2665
2666         g_array_append_vals(in_param1, &param, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2667         g_array_append_vals(in_param2, data, sizeof(bluetooth_gatt_att_data_t));
2668         g_array_append_vals(in_param3, &write_type, sizeof(bluetooth_gatt_write_type_e));
2669
2670         result = _bt_send_request_async(BT_BLUEZ_SERVICE,
2671                         BT_GATT_WRITE_DESCRIPTOR_VALUE,
2672                         in_param1, in_param2, in_param3, in_param4,
2673                         user_info->cb, user_info->user_data);
2674
2675         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2676
2677         return result;
2678 }
2679
2680 BT_EXPORT_API int bluetooth_gatt_client_set_service_change_watcher(
2681                 const bluetooth_device_address_t *address, gboolean enable)
2682 {
2683         GSList *l;
2684         bluetooth_device_address_t *addr = NULL;
2685         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
2686         char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
2687         int result = BLUETOOTH_ERROR_NONE;
2688
2689         BT_INIT_PARAMS();
2690         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2691
2692         g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
2693         g_array_append_vals(in_param2, &enable, sizeof(gboolean));
2694
2695         _bt_convert_addr_type_to_string(device_address, (unsigned char *)address->addr);
2696         _bt_convert_addr_string_to_secure_string(secure_address, device_address);
2697         BT_INFO("%s watcher for [%s]", enable ? "Set":"Unset", secure_address);
2698
2699         if (enable == TRUE) {
2700                 if (_bluetooth_gatt_check_service_change_watcher_address(address)
2701                                 == TRUE) {
2702                         BT_INFO("The watcher is already set");
2703                         goto done;
2704                 }
2705
2706                 if (service_monitor_list == NULL) {
2707                         //_bt_register_manager_subscribe_signal(TRUE);
2708
2709                         result = _bt_send_request(BT_BLUEZ_SERVICE,
2710                                         BT_GATT_WATCH_SERVICE_CHANGED_INDICATION,
2711                                         in_param1, in_param2, in_param3, in_param4, &out_param);
2712                 }
2713
2714                 if (result == BLUETOOTH_ERROR_NONE) {
2715                         addr = g_malloc0(sizeof(bluetooth_device_address_t));
2716                         memcpy(addr, address, sizeof(bluetooth_device_address_t));
2717
2718                         service_monitor_list =
2719                                 g_slist_append(service_monitor_list, addr);
2720                 }
2721         } else {
2722                 for (l = service_monitor_list; l != NULL; l = l->next) {
2723                         addr = l->data;
2724
2725                         if (!memcmp(address, addr,
2726                                                 sizeof(bluetooth_device_address_t))) {
2727                                 service_monitor_list =
2728                                         g_slist_remove(service_monitor_list, addr);
2729                                 g_free(addr);
2730                                 break;
2731                         }
2732                 }
2733
2734                 if (service_monitor_list == NULL) {
2735                         //_bt_register_manager_subscribe_signal(FALSE);
2736                         result = _bt_send_request(BT_BLUEZ_SERVICE,
2737                                         BT_GATT_WATCH_SERVICE_CHANGED_INDICATION,
2738                                         in_param1, in_param2, in_param3, in_param4, &out_param);
2739
2740                 }
2741         }
2742
2743 done:
2744         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2745         return result;
2746 }
2747
2748 BT_EXPORT_API int bluetooth_gatt_client_deinit(
2749                 int client_id)
2750 {
2751         int result;
2752         int *count;
2753         bt_event_info_t *event_info;
2754
2755         BT_CHECK_ENABLED(return);
2756
2757         BT_INFO("GATT Client Deinit Client instance ID [%d]", client_id);
2758
2759         BT_INIT_PARAMS();
2760         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2761
2762         g_array_append_vals(in_param1, &client_id, sizeof(int));
2763
2764         /* Unregistration MUST NOT FAIL */
2765         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_UNREGISTER,
2766                         in_param1, in_param2, in_param3, in_param4, &out_param);
2767
2768         if (result != BLUETOOTH_ERROR_NONE)
2769                 BT_ERR("GATT Client Unregistration failed result [%d]", result);
2770
2771         /* Unregister event handler if this is the only instance */
2772         event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
2773
2774         if (event_info) {
2775                 count = (int*)event_info->user_data;
2776
2777                 BT_DBG("Total num of GATT client instances [%d]", *count);
2778
2779                 if (*count == 1) {
2780                         BT_DBG("Currently only one GATT client instance, so remove it and unregister GATT client events");
2781                         _bt_unregister_event(BT_GATT_CLIENT_EVENT);
2782                         _bt_set_user_data(BT_GATT_CLIENT, NULL, NULL);
2783                 } else
2784                         *count -= 1;
2785         } else
2786                 BT_ERR("Impossible that client is created, but no event handler is registered!!!");
2787
2788         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2789         return result;
2790 }
2791
2792 BT_EXPORT_API int bluetooth_gatt_client_read_phy(const bluetooth_device_address_t *device_address)
2793 {
2794         int result;
2795
2796         BT_CHECK_PARAMETER(device_address, return);
2797         BT_CHECK_ENABLED(return);
2798
2799         BT_INIT_PARAMS();
2800         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2801
2802         g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t));
2803
2804         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_READ_PHY,
2805                 in_param1, in_param2, in_param3, in_param4, &out_param);
2806
2807         if (result != BLUETOOTH_ERROR_NONE)
2808                 BT_INFO("GATT Client Read PHY failed result [%d]", result);
2809         else
2810                 BT_INFO("GATT Client Read PHY successful");
2811
2812         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2813
2814         return result;
2815 }
2816
2817 BT_EXPORT_API int bluetooth_gatt_client_set_phy(const bluetooth_device_address_t *device_address,
2818                                 int tx_phy, int rx_phy, int phy_options)
2819 {
2820         int result;
2821
2822         BT_CHECK_PARAMETER(device_address, return);
2823         BT_CHECK_ENABLED(return);
2824
2825         BT_INFO("Set PHY: Tx[%d], Rx[%d], Phy_options[%d]", tx_phy, rx_phy, phy_options);
2826
2827         BT_INIT_PARAMS();
2828         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2829
2830         g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t));
2831         g_array_append_vals(in_param2, &tx_phy, sizeof(int));
2832         g_array_append_vals(in_param3, &rx_phy, sizeof(int));
2833         g_array_append_vals(in_param4, &phy_options, sizeof(int));
2834
2835         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_SET_PHY,
2836                 in_param1, in_param2, in_param3, in_param4, &out_param);
2837
2838         if (result != BLUETOOTH_ERROR_NONE)
2839                 BT_INFO("GATT Client Set PHY failed result [%d]", result);
2840         else
2841                 BT_INFO("GATT Client Set PHY successful");
2842
2843         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2844
2845         return result;
2846 }