[GATT Client] Delivery ATT error code to higher layer
[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
25 #include "bt-common.h"
26 #include "bt-event-handler.h"
27 #include "bt-gatt-client.h"
28 #include "bt-internal-types.h"
29 #include "bt-request-sender.h"
30
31 #define GATT_DEFAULT_TIMEOUT  (6 * 1000) // Dependent on supervision timeout 6 sec
32
33 typedef enum {
34         TYPE_NONE,
35         USER_DESC,
36         CLIENT_CONF,
37         SERVER_CONF,
38         CHAR_FORMAT
39 } char_descriptor_type_t;
40
41 static GSList *service_monitor_list = NULL;
42
43 BT_EXPORT_API int bluetooth_gatt_free_service_property(bt_gatt_service_property_t *svc_pty)
44 {
45         BT_CHECK_PARAMETER(svc_pty, return);
46
47         g_free(svc_pty->uuid);
48         g_free(svc_pty->handle);
49         g_strfreev(svc_pty->include_handles.handle);
50         g_strfreev(svc_pty->char_handle.handle);
51
52         memset(svc_pty, 0, sizeof(bt_gatt_service_property_t));
53
54         return BLUETOOTH_ERROR_NONE;
55 }
56
57 BT_EXPORT_API int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty)
58 {
59         BT_CHECK_PARAMETER(char_pty, return);
60
61         g_free(char_pty->uuid);
62         g_free(char_pty->name);
63         g_free(char_pty->description);
64         g_free(char_pty->val);
65         g_free(char_pty->handle);
66         g_strfreev(char_pty->char_desc_handle.handle);
67
68         memset(char_pty, 0, sizeof(bt_gatt_char_property_t));
69
70         return BLUETOOTH_ERROR_NONE;
71 }
72
73 BT_EXPORT_API int bluetooth_gatt_free_desc_property(bt_gatt_char_descriptor_property_t *desc_pty)
74 {
75         BT_CHECK_PARAMETER(desc_pty, return);
76
77         g_free(desc_pty->uuid);
78         g_free(desc_pty->val);
79         g_free(desc_pty->handle);
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         char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
112
113         _bt_convert_addr_type_to_string(device_address,
114                         (unsigned char *)device_addr->addr);
115
116         for (l = service_monitor_list; l != NULL; l = l->next) {
117                 char device_address2[BT_ADDRESS_STRING_SIZE] = { 0 };
118                 char secure_address2[BT_ADDRESS_STRING_SIZE] = { 0 };
119                 bluetooth_device_address_t *addr = l->data;
120
121                 _bt_convert_addr_type_to_string(device_address2,
122                                 (unsigned char *)addr->addr);
123                 _bt_convert_addr_string_to_secure_string(secure_address,
124                                 device_address);
125                 _bt_convert_addr_string_to_secure_string(secure_address2,
126                                 device_address2);
127                 BT_INFO("service_monitor_list [%s] - Input [%s]",
128                                 secure_address2, secure_address);
129
130                 if (!memcmp(device_addr, addr,
131                                 sizeof(bluetooth_device_address_t)))
132                         return TRUE;
133         }
134
135         return FALSE;
136 }
137
138 BT_EXPORT_API int bluetooth_gatt_set_service_change_watcher(
139                 const bluetooth_device_address_t *address, gboolean enable)
140 {
141         GSList *l;
142         bluetooth_device_address_t *addr = NULL;
143         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
144         char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
145
146         _bt_convert_addr_type_to_string(device_address,
147                         (unsigned char *)address->addr);
148         _bt_convert_addr_string_to_secure_string(secure_address,
149                         device_address);
150         BT_INFO("Set watcher for %s with %d", secure_address, enable);
151
152         if (enable == TRUE) {
153                 if (service_monitor_list == NULL)
154                         _bt_register_manager_subscribe_signal(TRUE);
155
156                 if (_bluetooth_gatt_check_service_change_watcher_address(address)
157                                 == TRUE) {
158                         BT_INFO("The watcher is already set");
159                         return BLUETOOTH_ERROR_NONE;
160                 }
161                 addr = g_malloc0(sizeof(bluetooth_device_address_t));
162                 memcpy(addr, address, sizeof(bluetooth_device_address_t));
163
164                 service_monitor_list =
165                         g_slist_append(service_monitor_list, addr);
166         } else {
167
168                 for (l = service_monitor_list; l != NULL; l = l->next) {
169                         addr = l->data;
170                         if (!memcmp(address, addr,
171                                         sizeof(bluetooth_device_address_t))) {
172                                 service_monitor_list =
173                                         g_slist_remove(service_monitor_list, addr);
174                                 g_free(addr);
175                                 break;
176                         }
177                 }
178
179                 if (service_monitor_list == NULL)
180                         _bt_register_manager_subscribe_signal(FALSE);
181         }
182
183         return BLUETOOTH_ERROR_NONE;
184 }
185
186 BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle,
187                                                 bt_gatt_service_property_t *service)
188 {
189         GDBusProxy *properties_proxy = NULL;
190         GError *error = NULL;
191         GVariant *result = NULL;
192         GDBusConnection *g_conn;
193         gsize len;
194         char *char_handle = NULL;
195         GPtrArray *gp_array  = NULL ;
196         GVariantIter *property_iter, *char_iter = NULL;
197         const gchar *key;
198         GVariant *value;
199
200         BT_CHECK_PARAMETER(service_handle, return);
201         BT_CHECK_PARAMETER(service, return);
202         BT_CHECK_ENABLED(return);
203
204         g_conn = _bt_gdbus_get_system_gconn();
205         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
206
207         properties_proxy = g_dbus_proxy_new_sync(g_conn,
208                         G_DBUS_PROXY_FLAGS_NONE, NULL,
209                         BT_BLUEZ_NAME,
210                         service_handle,
211                         BT_PROPERTIES_INTERFACE,
212                         NULL, &error);
213
214         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
215
216         result = g_dbus_proxy_call_sync(properties_proxy,
217                                 "GetAll",
218                                 g_variant_new("(s)", GATT_SERV_INTERFACE),
219                                 G_DBUS_CALL_FLAGS_NONE,
220                                 -1,
221                                 NULL,
222                                 &error);
223
224         if (!result) {
225                 if (error != NULL) {
226                         BT_ERR("Fail to get properties (Error: %s)", error->message);
227                         g_clear_error(&error);
228                 } else
229                         BT_ERR("Fail to get properties");
230                 g_object_unref(properties_proxy);
231                 return BLUETOOTH_ERROR_INTERNAL;
232         }
233
234         g_variant_get(result, "(a{sv})", &property_iter);
235
236         memset(service, 0, sizeof(bt_gatt_service_property_t));
237
238         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
239                 if (!g_strcmp0(key, "UUID")) {
240                         char *name = NULL;
241                         service->uuid = g_variant_dup_string(value, &len);
242                         _bt_get_uuid_specification_name(service->uuid, &name);
243                         BT_INFO("======> Service : %s [%s]", service->uuid, name);
244                         g_free(name);
245                 } else if (!g_strcmp0(key, "Primary")) {
246                         service->primary = g_variant_get_boolean(value);
247
248                 } else if (!g_strcmp0(key, "Includes")) {
249                         g_variant_get(value, "ao", &char_iter);
250                         gp_array = g_ptr_array_new();
251                         while (g_variant_iter_loop(char_iter, "&o", &char_handle))
252                                 g_ptr_array_add(gp_array, (gpointer)char_handle);
253
254                         if (gp_array->len != 0) {
255                                 service->include_handles.count = gp_array->len;
256                                 service->include_handles.handle =
257                                                 __get_string_array_from_gptr_array(gp_array);
258                         }
259                         g_ptr_array_free(gp_array, TRUE);
260                         g_variant_iter_free(char_iter);
261                 } else if (!g_strcmp0(key, "Characteristics")) {
262                         g_variant_get(value, "ao", &char_iter);
263                         gp_array = g_ptr_array_new();
264                         while (g_variant_iter_loop(char_iter, "&o", &char_handle))
265                                 g_ptr_array_add(gp_array, (gpointer)char_handle);
266
267                         if (gp_array->len != 0) {
268                                 service->char_handle.count = gp_array->len;
269                                 service->char_handle.handle =
270                                                 __get_string_array_from_gptr_array(gp_array);
271                         }
272                         BT_DBG("Characteristics count : %d", service->char_handle.count);
273                         g_ptr_array_free(gp_array, TRUE);
274                         g_variant_iter_free(char_iter);
275                 }
276         }
277
278         service->handle = g_strdup(service_handle);
279
280         g_variant_iter_free(property_iter);
281         g_variant_unref(result);
282         g_object_unref(properties_proxy);
283
284         return BLUETOOTH_ERROR_NONE;
285 }
286
287 BT_EXPORT_API int bluetooth_gatt_get_primary_services(
288                 const bluetooth_device_address_t *address,
289                 bt_gatt_handle_info_t *prim_svc)
290 {
291         GVariant *result = NULL;
292         GVariantIter *iter;
293         GVariantIter *svc_iter;
294         GVariantIter *interface_iter;
295         char *object_path = NULL;
296         char *interface_str = NULL;
297         const gchar *key = NULL;
298         GVariant *value = NULL;
299         GPtrArray *gp_array  = NULL;
300         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
301         char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
302         int ret = BLUETOOTH_ERROR_INTERNAL;
303
304         BT_INFO("+");
305         BT_CHECK_PARAMETER(address, return);
306         BT_CHECK_PARAMETER(prim_svc, return);
307         BT_CHECK_ENABLED(return);
308
309         result = _bt_get_managed_objects();
310         if (result == NULL)
311                 return ret;
312
313         _bt_convert_addr_type_to_string(device_address,
314                         (unsigned char *)address->addr);
315
316         gp_array = g_ptr_array_new();
317         g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
318
319         while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
320                         &interface_iter)) {
321                 if (object_path == NULL)
322                         continue;
323
324                 _bt_convert_device_path_to_address(object_path, temp_address);
325
326                 if (g_strcmp0(temp_address, device_address) != 0)
327                         continue;
328
329                 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
330                                 &interface_str, &svc_iter)) {
331                         if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
332                                 continue;
333
334                         BT_DBG("Object Path: %s", object_path);
335                         while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
336                                 if (g_strcmp0(key, "Primary") == 0) {
337                                         if (g_variant_get_boolean(value))
338                                                 g_ptr_array_add(gp_array, (gpointer)object_path);
339                                 }
340                         }
341                 }
342         }
343
344         if (gp_array->len == 0) {
345                 BT_ERR("gp_array is NULL");
346                 ret = BLUETOOTH_ERROR_NOT_FOUND;
347         } else {
348                 ret = BLUETOOTH_ERROR_NONE;
349                 prim_svc->count = gp_array->len;
350                 prim_svc->handle = __get_string_array_from_gptr_array(gp_array);
351         }
352
353         g_ptr_array_free(gp_array, TRUE);
354         g_variant_iter_free(iter);
355         g_variant_unref(result);
356         BT_DBG("-");
357         return ret;
358 }
359
360 BT_EXPORT_API int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address,
361                         const char *service_uuid,
362                         bt_gatt_service_property_t *service)
363 {
364         GVariant *result = NULL;
365         GVariantIter *iter;
366         GVariantIter *svc_iter;
367         GVariantIter *interface_iter;
368         char *object_path = NULL;
369         char *interface_str = NULL;
370         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
371         char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
372         int ret = BLUETOOTH_ERROR_INTERNAL;
373
374         BT_CHECK_PARAMETER(address, return);
375         BT_CHECK_PARAMETER(service_uuid, return);
376         BT_CHECK_PARAMETER(service, return);
377         BT_CHECK_ENABLED(return);
378
379         result = _bt_get_managed_objects();
380         if (result == NULL)
381                 return ret;
382
383         _bt_convert_addr_type_to_string(device_address,
384                                 (unsigned char *)address->addr);
385
386         g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
387
388         while (g_variant_iter_loop(iter, "{oa{sa{sv}}}", &object_path,
389                         &interface_iter)) {
390                 if (object_path == NULL)
391                         continue;
392
393                 _bt_convert_device_path_to_address(object_path,
394                                 temp_address);
395
396                 if (g_strcmp0(temp_address, device_address) != 0)
397                         continue;
398
399                 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
400                                 &interface_str, &svc_iter)) {
401                         if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
402                                 continue;
403
404                         BT_DBG("Object Path: %s", object_path);
405                         ret = bluetooth_gatt_get_service_property(object_path,
406                                         service);
407
408                         if (ret != BLUETOOTH_ERROR_NONE) {
409                                 BT_ERR("Get service property failed(0x%08x)", ret);
410                         } else {
411                                 if (service->primary == TRUE &&
412                                                 g_strstr_len(service->uuid, -1,
413                                                                 service_uuid)) {
414                                         ret = BLUETOOTH_ERROR_NONE;
415                                         goto done;
416                                 }
417                         }
418                         bluetooth_gatt_free_service_property(service);
419                 }
420         }
421
422 done:
423         g_variant_iter_free(iter);
424         g_variant_unref(result);
425
426         return ret;
427 }
428
429 static void __bluetooth_internal_get_char_cb(GDBusProxy *proxy,
430                 GAsyncResult *res, gpointer user_data)
431 {
432         GVariant *value;
433         GVariant *char_value;
434         GVariantIter *char_iter;
435         GPtrArray *gp_array = NULL;
436         bt_gatt_discovered_char_t svc_char = { 0, };
437         char *char_handle;
438         GError *error = NULL;
439         bt_user_info_t *user_info;
440
441         BT_DBG("+");
442
443         user_info = _bt_get_user_data(BT_COMMON);
444         svc_char.service_handle = user_data;
445
446         value = g_dbus_proxy_call_finish(proxy, res, &error);
447
448         if (value == NULL) {
449                 if (error != NULL) {
450                         BT_ERR("Get service characteristics failed\n errCode[%x],"
451                                         "message[%s]\n", error->code, error->message);
452                         g_clear_error(&error);
453                 } else {
454                         BT_ERR("Get service characteristics failed\n");
455                 }
456                 if (user_info) {
457                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
458                                 BLUETOOTH_ERROR_INTERNAL, NULL,
459                                 user_info->cb, user_info->user_data);
460                 }
461                 g_free(svc_char.service_handle);
462                 g_object_unref(proxy);
463                 return;
464         }
465
466         g_variant_get(value, "(v)", &char_value);
467         g_variant_get(char_value, "ao", &char_iter);
468
469         gp_array = g_ptr_array_new();
470         while (g_variant_iter_loop(char_iter, "&o",  &char_handle))
471                 g_ptr_array_add(gp_array, (gpointer)char_handle);
472
473         if (gp_array->len != 0) {
474                 svc_char.handle_info.count = gp_array->len;
475                 svc_char.handle_info.handle =
476                         __get_string_array_from_gptr_array(gp_array);
477         }
478         g_ptr_array_free(gp_array, TRUE);
479
480         if (user_info) {
481                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
482                         BLUETOOTH_ERROR_NONE, &svc_char,
483                         user_info->cb, user_info->user_data);
484         }
485
486         g_strfreev(svc_char.handle_info.handle);
487         g_free(svc_char.service_handle);
488         g_variant_iter_free(char_iter);
489         g_variant_unref(value);
490         g_object_unref(proxy);
491 }
492
493 BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(
494                         const char *service_handle)
495 {
496         GDBusProxy *properties_proxy = NULL;
497         GDBusConnection *g_conn;
498         GError *error = NULL;
499         char *handle;
500
501         BT_DBG("+");
502
503         BT_CHECK_PARAMETER(service_handle, return);
504         BT_CHECK_ENABLED(return);
505
506         g_conn = _bt_gdbus_get_system_gconn();
507         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
508
509         properties_proxy = g_dbus_proxy_new_sync(g_conn,
510                         G_DBUS_PROXY_FLAGS_NONE, NULL,
511                         BT_BLUEZ_NAME,
512                         service_handle,
513                         BT_PROPERTIES_INTERFACE,
514                         NULL, &error);
515
516         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
517
518         handle = g_strdup(service_handle);
519         g_dbus_proxy_call(properties_proxy,
520                         "Get",
521                         g_variant_new("(ss)",
522                                 GATT_SERV_INTERFACE, "Characteristics"),
523                         G_DBUS_CALL_FLAGS_NONE,
524                         -1,
525                         NULL,
526                         (GAsyncReadyCallback)__bluetooth_internal_get_char_cb,
527                         (gpointer)handle);
528
529         BT_DBG("-");
530         return BLUETOOTH_ERROR_NONE;
531 }
532
533
534 static int __get_permission_flag(char *permission)
535 {
536         int ret = 0;
537
538         retv_if(permission == NULL, ret);
539
540         BT_INFO("permission = %s", permission);
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 BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
573                 const char *char_handle, bt_gatt_char_property_t *characteristic)
574 {
575         GDBusProxy *properties_proxy = NULL;
576         GError *error = NULL;
577         GVariant *value = NULL;
578         GVariant *result = NULL;
579         GByteArray *gb_array = NULL;
580         GPtrArray *gp_array  = NULL ;
581         GDBusConnection *g_conn;
582         guint8 char_value;
583         const gchar *key;
584         gchar* permission;
585         char *char_desc_handle = NULL;
586         gsize len;
587         GVariantIter *property_iter;
588         GVariantIter *char_value_iter;
589         GVariantIter *char_perm_iter;
590         GVariantIter *char_desc_iter;
591
592         BT_CHECK_PARAMETER(char_handle, return);
593         BT_CHECK_PARAMETER(characteristic, return);
594
595         BT_CHECK_ENABLED(return);
596
597         g_conn = _bt_gdbus_get_system_gconn();
598         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
599
600         properties_proxy = g_dbus_proxy_new_sync(g_conn,
601                         G_DBUS_PROXY_FLAGS_NONE, NULL,
602                         BT_BLUEZ_NAME,
603                         char_handle,
604                         BT_PROPERTIES_INTERFACE,
605                         NULL, &error);
606
607         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
608
609         result = g_dbus_proxy_call_sync(properties_proxy,
610                                 "GetAll",
611                                         g_variant_new("(s)", GATT_CHAR_INTERFACE),
612                                 G_DBUS_CALL_FLAGS_NONE,
613                                 -1,
614                                 NULL,
615                                 &error);
616
617         if (!result) {
618                 if (error != NULL) {
619                         BT_ERR("Fail to get properties (Error: %s)", error->message);
620                         g_clear_error(&error);
621                 } else
622                         BT_ERR("Fail to get properties");
623                 g_object_unref(properties_proxy);
624                 return BLUETOOTH_ERROR_INTERNAL;
625         }
626
627         g_variant_get(result, "(a{sv})", &property_iter);
628
629         memset(characteristic, 0, sizeof(bt_gatt_char_property_t));
630         characteristic->handle = g_strdup(char_handle);
631
632         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
633                 if (!g_strcmp0(key, "UUID")) {
634                         char *name = NULL;
635                         characteristic->uuid = g_variant_dup_string(value, &len);
636                         _bt_get_uuid_specification_name(characteristic->uuid, &name);
637                         BT_INFO("Characteristic : %s [%s]", characteristic->uuid, name);
638                         g_free(name);
639                 } else if (!g_strcmp0(key, "Value")) {
640                         gb_array = g_byte_array_new();
641                         g_variant_get(value, "ay", &char_value_iter);
642                         while (g_variant_iter_loop(char_value_iter, "y",  &char_value)) {
643                         //      BT_DBG("value of char = %d",char_value);
644                                 g_byte_array_append(gb_array, &char_value, 1);
645                         }
646                         g_variant_iter_free(char_value_iter);
647
648                         if (gb_array->len != 0) {
649                                 characteristic->val = g_malloc0(gb_array->len *
650                                                                 sizeof(unsigned char));
651                                 memcpy(characteristic->val, gb_array->data, gb_array->len);
652                         }
653                         characteristic->val_len = gb_array->len;
654                         g_byte_array_free(gb_array, TRUE);
655                 } else if (!g_strcmp0(key, "Flags")) {
656                         g_variant_get(value, "as", &char_perm_iter);
657                         characteristic->permission = 0x00;
658
659                         while (g_variant_iter_loop(char_perm_iter, "s", &permission))
660                                 characteristic->permission |= __get_permission_flag(permission);
661
662                         g_variant_iter_free(char_perm_iter);
663                 } else if (!g_strcmp0(key, "Descriptors")) {
664                         g_variant_get(value, "ao", &char_desc_iter);
665                         gp_array = g_ptr_array_new();
666                         while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle))
667                                 g_ptr_array_add(gp_array, (gpointer)char_desc_handle);
668
669                         g_variant_iter_free(char_desc_iter);
670                         if (gp_array->len != 0) {
671                                 characteristic->char_desc_handle.count = gp_array->len;
672                                 characteristic->char_desc_handle.handle =
673                                                 __get_string_array_from_gptr_array(gp_array);
674                         }
675                         g_ptr_array_free(gp_array, TRUE);
676                 }
677         }
678
679         g_variant_iter_free(property_iter);
680         g_variant_unref(result);
681         g_object_unref(properties_proxy);
682
683         return BLUETOOTH_ERROR_NONE;
684 }
685
686 void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy,
687                         GAsyncResult *res, gpointer user_data)
688 {
689         GVariant *value;
690         GVariantIter *char_iter;
691         char *char_handle;
692         GError *error = NULL;
693         bt_user_info_t *user_info;
694         int ret = BLUETOOTH_ERROR_INTERNAL;
695         bt_gatt_char_property_t characteristic;
696
697         user_info = _bt_get_user_data(BT_COMMON);
698
699         value = g_dbus_proxy_call_finish(proxy, res, &error);
700
701         if (value == NULL) {
702                 if (error != NULL) {
703                         BT_ERR("Get service characteristics failed\n errCode[%x],"
704                                         "message[%s]\n", error->code, error->message);
705                         g_clear_error(&error);
706                 } else {
707                         BT_ERR("Get service characteristics failed\n");
708                 }
709                 if (user_info) {
710                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
711                                 BLUETOOTH_ERROR_INTERNAL, NULL,
712                                 user_info->cb, user_info->user_data);
713                 }
714                 g_object_unref(proxy);
715                 g_free(user_data);
716                 return;
717         }
718
719         g_variant_get(value, "(ao)", &char_iter);
720
721         while (g_variant_iter_loop(char_iter, "&o",  &char_handle)) {
722                 if (!char_handle)
723                         continue;
724                 ret = bluetooth_gatt_get_characteristics_property(char_handle,
725                                 &characteristic);
726
727                 if (ret != BLUETOOTH_ERROR_NONE) {
728                         BT_ERR("Get characteristic property failed(0x%08x)", ret);
729                 } else {
730                         if (g_strstr_len(characteristic.uuid, -1, user_data)) {
731                                 ret = BLUETOOTH_ERROR_NONE;
732                                 break;
733                         }
734                 }
735                 bluetooth_gatt_free_char_property(&characteristic);
736         }
737
738         if (user_info) {
739                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret,
740                                 &characteristic, user_info->cb, user_info->user_data);
741         }
742
743         bluetooth_gatt_free_char_property(&characteristic);
744         g_variant_iter_free(char_iter);
745         g_variant_unref(value);
746         g_free(user_data);
747 }
748
749 BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
750                                                 const char *char_uuid)
751 {
752         GDBusProxy *properties_proxy = NULL;
753         GDBusConnection *g_conn;
754         GError *error = NULL;
755         char *uuid;
756
757         BT_CHECK_PARAMETER(service_handle, return);
758         BT_CHECK_PARAMETER(char_uuid, return);
759         BT_CHECK_ENABLED(return);
760
761         g_conn = _bt_gdbus_get_system_gconn();
762         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
763
764         properties_proxy = g_dbus_proxy_new_sync(g_conn,
765                         G_DBUS_PROXY_FLAGS_NONE, NULL,
766                         BT_BLUEZ_NAME,
767                         service_handle,
768                         BT_PROPERTIES_INTERFACE,
769                         NULL, &error);
770
771         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
772
773         uuid = g_strdup(char_uuid);
774         g_dbus_proxy_call(properties_proxy,
775                         "Get",
776                         g_variant_new("(ss)",
777                                 GATT_SERV_INTERFACE, "Characteristics"),
778                         G_DBUS_CALL_FLAGS_NONE,
779                         -1,
780                         NULL,
781                         (GAsyncReadyCallback)bluetooth_gatt_get_char_from_uuid_cb,
782                         (gpointer)uuid);
783
784         return BLUETOOTH_ERROR_NONE;
785 }
786
787 BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
788                 const char *descriptor_handle, bt_gatt_char_descriptor_property_t *descriptor)
789 {
790         GDBusProxy *properties_proxy = NULL;
791         GError *error = NULL;
792         GDBusConnection *g_conn;
793         GVariant *result = NULL;
794         GVariantIter *property_iter;
795         const gchar *key;
796         guint8 char_value;
797         gsize len;
798         GVariant *value = NULL;
799         GByteArray *gb_array = NULL;
800         GVariantIter *desc_value_iter;
801
802         BT_CHECK_PARAMETER(descriptor_handle, return);
803         BT_CHECK_PARAMETER(descriptor, return);
804
805         BT_CHECK_ENABLED(return);
806
807         g_conn = _bt_gdbus_get_system_gconn();
808         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
809
810         properties_proxy = g_dbus_proxy_new_sync(g_conn,
811                         G_DBUS_PROXY_FLAGS_NONE, NULL,
812                         BT_BLUEZ_NAME,
813                         descriptor_handle,
814                         BT_PROPERTIES_INTERFACE,
815                         NULL, &error);
816
817         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
818
819         result = g_dbus_proxy_call_sync(properties_proxy,
820                                 "GetAll",
821                                         g_variant_new("(s)", GATT_DESC_INTERFACE),
822                                 G_DBUS_CALL_FLAGS_NONE,
823                                 -1,
824                                 NULL,
825                                 &error);
826
827         if (!result) {
828                 if (error != NULL) {
829                         BT_ERR("Fail to get properties (Error: %s)", error->message);
830                         g_clear_error(&error);
831                 } else
832                         BT_ERR("Fail to get properties");
833                 g_object_unref(properties_proxy);
834                 return BLUETOOTH_ERROR_INTERNAL;
835         }
836
837         g_variant_get(result, "(a{sv})", &property_iter);
838
839         memset(descriptor, 0, sizeof(bt_gatt_char_descriptor_property_t));
840         descriptor->handle = g_strdup(descriptor_handle);
841
842         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
843                 if (!g_strcmp0(key, "UUID")) {
844                         char *name = NULL;
845                         descriptor->uuid = g_variant_dup_string(value, &len);
846                         _bt_get_uuid_specification_name(descriptor->uuid, &name);
847                         BT_INFO("Descriptor : %s [%s]", descriptor->uuid, name);
848                         g_free(name);
849                 } else if (!g_strcmp0(key, "Value")) {
850                         gb_array = g_byte_array_new();
851                         g_variant_get(value, "ay", &desc_value_iter);
852                         while (g_variant_iter_loop(desc_value_iter, "y",  &char_value)) {
853                                 BT_DBG("value of descriptor = %d", char_value);
854                                 g_byte_array_append(gb_array, &char_value, 1);
855                         }
856                         g_variant_iter_free(desc_value_iter);
857
858                         if (gb_array->len != 0) {
859                                 descriptor->val = g_malloc0(gb_array->len *
860                                                                 sizeof(unsigned char));
861                                 memcpy(descriptor->val, gb_array->data, gb_array->len);
862                         }
863                         descriptor->val_len = gb_array->len;
864                         g_byte_array_free(gb_array, TRUE);
865                 }
866         }
867
868         g_variant_iter_free(property_iter);
869         g_variant_unref(result);
870         g_object_unref(properties_proxy);
871
872         return BLUETOOTH_ERROR_NONE;
873 }
874
875 static int __bluetooth_get_att_error_code(GError *error)
876 {
877         int att_ecode = 0;
878         int len;
879         char *str = NULL;
880
881         BT_ERR("Error : %s", error->message);
882         str = g_strrstr(error->message, "ATT error: 0x");
883         if (str) {
884                 len = strlen(str);
885                 att_ecode =  g_ascii_xdigit_value(str[len-2]) << 4;
886                 att_ecode += g_ascii_xdigit_value(str[len-1]);
887         } else
888                 return BLUETOOTH_ATT_ERROR_INTERNAL;
889
890         switch (att_ecode) {
891         case BLUETOOTH_ATT_ERROR_READ_NOT_PERMITTED:
892                 BT_ERR("Read not permitted");
893                 break;
894         case BLUETOOTH_ATT_ERROR_WRITE_NOT_PERMITTED:
895                 BT_ERR("Write not permitted");
896                 break;
897         case BLUETOOTH_ATT_ERROR_AUTHENTICATION:
898                 break;
899         case BLUETOOTH_ATT_ERROR_INSUFFICIENT_ENCRYPTION:
900         case BLUETOOTH_ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE:
901                 BT_ERR("Not paired");
902                 break;
903         case BLUETOOTH_ATT_ERROR_INVALID_OFFSET:
904                 BT_ERR("Invalid offset");
905                 break;
906         case BLUETOOTH_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN:
907                 BT_ERR("Invalid Length");
908                 break;
909         case BLUETOOTH_ATT_ERROR_AUTHORIZATION:
910                 BT_ERR("Operation not Authorized");
911                 break;
912         }
913
914         if (att_ecode >= 0x80 && att_ecode <= 0x9F)
915                 BT_ERR("Application error");
916
917         return att_ecode;
918 }
919
920 static void __bluetooth_internal_read_cb(GObject *source_object,
921                         GAsyncResult *res,
922                         gpointer user_data)
923 {
924         GError *error = NULL;
925         bt_user_info_t *user_info;
926         bt_gatt_char_value_t char_value =  { 0, };
927         GDBusConnection *system_gconn = NULL;
928         GVariant *value;
929         GByteArray *gp_byte_array = NULL;
930         GVariantIter *iter;
931         guint8 g_byte;
932         int att_ecode = 0;
933
934         BT_DBG("+");
935         user_info = _bt_get_user_data(BT_COMMON);
936
937         system_gconn = _bt_gdbus_get_system_gconn();
938         value = g_dbus_connection_call_finish(system_gconn, res, &error);
939         char_value.char_handle = user_data;
940
941         if (error) {
942                 att_ecode = __bluetooth_get_att_error_code(error);
943                 g_clear_error(&error);
944                 if (user_info) {
945                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
946                                 att_ecode, NULL,
947                                 user_info->cb, user_info->user_data);
948                 }
949                 g_free(char_value.char_handle);
950                 g_variant_unref(value);
951                 return;
952         }
953
954         g_variant_get(value, "(ay)", &iter);
955
956         gp_byte_array = g_byte_array_new();
957         while (g_variant_iter_loop(iter, "y", &g_byte))
958                 g_byte_array_append(gp_byte_array, &g_byte, 1);
959
960         if (gp_byte_array->len != 0) {
961                 char_value.val_len = gp_byte_array->len;
962                 char_value.char_value = gp_byte_array->data;
963         }
964
965         if (user_info) {
966                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
967                                 BLUETOOTH_ATT_ERROR_NONE, &char_value,
968                                 user_info->cb, user_info->user_data);
969         }
970
971         g_free(char_value.char_handle);
972         g_byte_array_free(gp_byte_array, TRUE);
973         g_variant_unref(value);
974         g_variant_iter_free(iter);
975
976         BT_DBG("-");
977 }
978
979 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *characteristic)
980 {
981         GDBusConnection *conn;
982         char *handle;
983         GVariantBuilder *builder = NULL;
984         guint16 offset = 0;
985
986         BT_CHECK_PARAMETER(characteristic, return);
987         BT_CHECK_ENABLED(return);
988
989         conn = _bt_gdbus_get_system_gconn();
990         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
991
992         handle = g_strdup(characteristic);
993
994         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
995
996         /*offset*/
997         g_variant_builder_add(builder, "{sv}", "offset",
998                 g_variant_new("q", offset));
999
1000         /* Device Object path*/
1001 //      g_variant_builder_add(builder, "{sv}", "device",
1002 //      g_variant_new_object("o", NULL));
1003
1004         g_dbus_connection_call(conn,
1005                         BT_BLUEZ_NAME,
1006                         characteristic,
1007                         GATT_CHAR_INTERFACE,
1008                         "ReadValue",
1009                         g_variant_new("(a{sv})", builder),
1010                         G_VARIANT_TYPE("(ay)"),
1011                         G_DBUS_CALL_FLAGS_NONE,
1012                         -1,
1013                         NULL,
1014                         (GAsyncReadyCallback)__bluetooth_internal_read_cb,
1015                         (gpointer)handle);
1016         g_variant_builder_unref(builder);
1017
1018         return BLUETOOTH_ERROR_NONE;
1019 }
1020
1021 static void __bluetooth_internal_write_cb(GObject *source_object,
1022                         GAsyncResult *res,
1023                         gpointer user_data)
1024 {
1025         GError *error = NULL;
1026         bt_user_info_t *user_info;
1027         GDBusConnection *system_gconn = NULL;
1028         GVariant *value;
1029         int att_ecode = BLUETOOTH_ATT_ERROR_NONE;
1030
1031         user_info = _bt_get_user_data(BT_COMMON);
1032
1033         system_gconn = _bt_gdbus_get_system_gconn();
1034         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1035
1036         if (error) {
1037                 att_ecode = __bluetooth_get_att_error_code(error);
1038                 g_clear_error(&error);
1039         }
1040
1041         if (user_info) {
1042                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
1043                                 att_ecode, NULL,
1044                                 user_info->cb, user_info->user_data);
1045         } else {
1046                 BT_ERR("user info is null");
1047         }
1048
1049         if (value)
1050                 g_variant_unref(value);
1051
1052         return;
1053 }
1054
1055 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
1056                 const char *char_handle, const guint8 *value, int length)
1057 {
1058         GVariant *val, *options;
1059         GVariantBuilder *builder1;
1060         GVariantBuilder *builder2;
1061         GError *error = NULL;
1062         GDBusConnection *conn;
1063         int i = 0;
1064         guint16 offset = 0;
1065
1066         BT_DBG("+");
1067         BT_CHECK_PARAMETER(char_handle, return);
1068         BT_CHECK_PARAMETER(value, return);
1069         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1070         BT_CHECK_ENABLED(return);
1071
1072         conn = _bt_gdbus_get_system_gconn();
1073         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1074
1075         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1076         for (i = 0; i < length; i++)
1077                 g_variant_builder_add(builder1, "y", value[i]);
1078
1079         val = g_variant_new("ay", builder1);
1080
1081         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1082         /*offset*/
1083         g_variant_builder_add(builder2, "{sv}", "offset",
1084                                 g_variant_new_uint16(offset));
1085
1086         /* Device Object path*/
1087 //      g_variant_builder_add(builder2, "{sv}", "device",
1088 //      g_variant_new_object("o", NULL));
1089
1090         options = g_variant_new("a{sv}", builder2);
1091
1092         g_dbus_connection_call(conn,
1093                                 BT_BLUEZ_NAME,
1094                                 char_handle,
1095                                 GATT_CHAR_INTERFACE,
1096                                 "WriteValue",
1097                                 g_variant_new("(@ay@a{sv})",
1098                                 val, options),
1099                                 NULL,
1100                                 G_DBUS_CALL_FLAGS_NONE,
1101                                 -1, NULL,
1102                                 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1103                                 NULL);
1104
1105
1106         if (error) {
1107                 BT_ERR("Set value Failed: %s", error->message);
1108                 g_clear_error(&error);
1109                 g_variant_builder_unref(builder1);
1110                 return BLUETOOTH_ERROR_INTERNAL;
1111         }
1112         g_variant_builder_unref(builder1);
1113         g_variant_builder_unref(builder2);
1114
1115         BT_DBG("-");
1116         return BLUETOOTH_ERROR_NONE;
1117 }
1118
1119 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
1120                 const char *char_handle, const guint8 *value, int length, guint8 write_type)
1121 {
1122         GVariant *val, *options;
1123         GVariantBuilder *builder1;
1124         GVariantBuilder *builder2;
1125         GDBusConnection *conn;
1126         guint16 offset = 0;
1127         int i = 0;
1128         int ret = BLUETOOTH_ERROR_NONE;
1129
1130         BT_CHECK_PARAMETER(char_handle, return);
1131         BT_CHECK_PARAMETER(value, return);
1132         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1133         BT_CHECK_ENABLED_INTERNAL(return);
1134
1135         conn = _bt_gdbus_get_system_gconn();
1136         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1137
1138         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1139
1140         for (i = 0; i < length; i++)
1141                 g_variant_builder_add(builder1, "y", value[i]);
1142
1143         val = g_variant_new("ay", builder1);
1144
1145         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1146         /*offset*/
1147         g_variant_builder_add(builder2, "{sv}", "offset",
1148                         g_variant_new_uint16(offset));
1149
1150         /* Device Object path*/
1151 //      g_variant_builder_add(builder2, "{sv}", "device",
1152 //      g_variant_new_object("o", NULL));
1153
1154         options = g_variant_new("a{sv}", builder2);
1155
1156         g_dbus_connection_call(conn,
1157                         BT_BLUEZ_NAME,
1158                         char_handle,
1159                         GATT_CHAR_INTERFACE,
1160                         "WriteValuebyType",
1161                         g_variant_new("(y@ay@a{sv})",
1162                         write_type, val, options),
1163                         NULL,
1164                         G_DBUS_CALL_FLAGS_NONE,
1165                         -1, NULL,
1166                         (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1167                         NULL);
1168
1169         g_variant_builder_unref(builder1);
1170         g_variant_builder_unref(builder2);
1171         return ret;
1172 }
1173
1174 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
1175                         const char *char_handle, const guint8 *value, int length)
1176 {
1177         GVariant *val, *options;
1178         GDBusConnection *conn;
1179         GVariantBuilder *builder1;
1180         GVariantBuilder *builder2;
1181         guint offset = 0;
1182         int i;
1183
1184         BT_DBG("+");
1185         BT_CHECK_PARAMETER(char_handle, return);
1186         BT_CHECK_PARAMETER(value, return);
1187         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1188         BT_CHECK_ENABLED(return);
1189
1190         conn = _bt_gdbus_get_system_gconn();
1191         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1192
1193         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1194
1195         for (i = 0; i < length; i++) {
1196                 g_variant_builder_add(builder1, "y", value[i]);
1197                 BT_DBG("value [] = %d", value[i]);
1198         }
1199
1200         val = g_variant_new("ay", builder1);
1201
1202         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1203         /*offset*/
1204         g_variant_builder_add(builder2, "{sv}", "offset",
1205                                 g_variant_new_uint16(offset));
1206
1207         /* Device Object path*/
1208 //      g_variant_builder_add(builder2, "{sv}", "device",
1209 //      g_variant_new_object("o", NULL));
1210
1211         options = g_variant_new("a{sv}", builder2);
1212
1213         g_dbus_connection_call(conn,
1214                                 BT_BLUEZ_NAME,
1215                                 char_handle,
1216                                 GATT_CHAR_INTERFACE,
1217                                 "WriteValue",
1218                                 g_variant_new("(@ay@a{sv})",
1219                                 val, options),
1220                                 NULL,
1221                                 G_DBUS_CALL_FLAGS_NONE,
1222                                 -1, NULL,
1223                                 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1224                                 NULL);
1225
1226         g_variant_builder_unref(builder1);
1227         g_variant_builder_unref(builder2);
1228
1229         BT_DBG("-");
1230         return BLUETOOTH_ERROR_NONE;
1231 }
1232
1233 static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
1234                         bt_gatt_char_property_t *characteristic)
1235 {
1236         BT_DBG("+");
1237         GDBusProxy *properties_proxy = NULL;
1238         GError *error = NULL;
1239         GVariant *value = NULL;
1240         GVariant *result = NULL;
1241         GDBusConnection *g_conn;
1242         int i, ret = BLUETOOTH_ERROR_NONE;
1243         const char *uuid = NULL;
1244         gsize len = 0;
1245         GVariantIter *desc_value_iter, *property_iter;
1246         const gchar *key;
1247         char_descriptor_type_t desc_type = TYPE_NONE;
1248
1249         g_conn = _bt_gdbus_get_system_gconn();
1250         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1251
1252         properties_proxy = g_dbus_proxy_new_sync(g_conn,
1253                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1254                         BT_BLUEZ_NAME,
1255                         char_handle,
1256                         BT_PROPERTIES_INTERFACE,
1257                         NULL, &error);
1258
1259         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1260
1261         result = g_dbus_proxy_call_sync(properties_proxy,
1262                                 "GetAll",
1263                                 g_variant_new("(s)", GATT_DESC_INTERFACE),
1264                                 G_DBUS_CALL_FLAGS_NONE,
1265                                 -1,
1266                                 NULL,
1267                                 &error);
1268
1269         if (!result) {
1270                 if (error != NULL) {
1271                         BT_ERR("Fail to get properties (Error: %s)", error->message);
1272                         g_clear_error(&error);
1273                 } else
1274                         BT_ERR("Fail to get properties");
1275                 g_object_unref(properties_proxy);
1276                 return BLUETOOTH_ERROR_INTERNAL;
1277         }
1278         g_variant_get(result, "(a{sv})", &property_iter);
1279         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1280                 if (!g_strcmp0(key, "UUID")) {
1281                         uuid = g_variant_get_string(value, &len);
1282                         if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
1283                                 BT_DBG("GATT_USER_DESC_UUID");
1284                                 desc_type = USER_DESC;
1285                         } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) {
1286                                 BT_DBG("GATT_CHAR_FORMAT");
1287                                 desc_type = CHAR_FORMAT;
1288                         } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) {
1289                                 BT_DBG("GATT_CHAR_CLIENT_CONF");
1290                                 desc_type = CLIENT_CONF;
1291                         } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) {
1292                                 BT_DBG("GATT_CHAR_SERVER_CONF");
1293                                 desc_type = SERVER_CONF;
1294                         } else {
1295                                 BT_DBG("descriptor uuid = %s", uuid);
1296                         }
1297                 } else if (!g_strcmp0(key, "Value")) {
1298                         switch (desc_type) {
1299                         case CHAR_FORMAT:
1300                                 BT_DBG("Format descriptor");
1301                                 g_variant_get(value, "(yyqyq)",
1302                                                 &(characteristic->format.format),
1303                                                 &(characteristic->format.exponent),
1304                                                 &(characteristic->format.unit),
1305                                                 &(characteristic->format.name_space),
1306                                                 &(characteristic->format.description));
1307                                 break;
1308                         case USER_DESC:
1309                                 BT_DBG("User descriptor");
1310                                 g_variant_get(value, "ay", &desc_value_iter);
1311                                 len = g_variant_get_size((GVariant *)desc_value_iter);
1312
1313                                 if (len > 0)
1314                                         characteristic->description = (char *)g_malloc0(len + 1);
1315
1316                                 for (i = 0; i < len; i++) {
1317                                         g_variant_iter_loop(desc_value_iter, "y",
1318                                                 &characteristic->description[i]);
1319                                         BT_DBG("description = %s", characteristic->description);
1320                                 }
1321                                 g_variant_iter_free(desc_value_iter);
1322                                 break;
1323                         case CLIENT_CONF:
1324                                 BT_DBG(" CLIENT_CONF");
1325                                 break;
1326                         case SERVER_CONF:
1327                                 BT_DBG(" SERVER_CONF");
1328                                 break;
1329                         default:
1330                                 break;
1331                         }
1332                 }
1333         }
1334
1335         g_variant_iter_free(property_iter);
1336         g_variant_unref(result);
1337         g_object_unref(properties_proxy);
1338
1339         BT_DBG("-");
1340         return ret;
1341 }
1342
1343
1344 static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
1345                         GAsyncResult *res, gpointer user_data)
1346 {
1347         BT_DBG("+");
1348         GVariant *value;
1349         GVariant        *char_value;
1350         GVariantIter *char_iter;
1351         char *char_handle;
1352         GError *error = NULL;
1353         bt_user_info_t *user_info;
1354         bt_gatt_char_property_t characteristic = {0, };
1355         int ret = BLUETOOTH_ERROR_INTERNAL;
1356
1357         user_info = _bt_get_user_data(BT_COMMON);
1358
1359         value = g_dbus_proxy_call_finish(proxy, res, &error);
1360         characteristic.handle = user_data;
1361
1362         if (value == NULL) {
1363                 if (error != NULL) {
1364                         BT_ERR("Get characteristic descriptor failed\n errCode[%x],"
1365                                         "message[%s]\n", error->code, error->message);
1366                         g_clear_error(&error);
1367                 } else {
1368                         BT_ERR("Get characteristic descriptor failed\n");
1369                 }
1370                 if (user_info) {
1371                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1372                                 BLUETOOTH_ERROR_INTERNAL, NULL,
1373                                 user_info->cb, user_info->user_data);
1374                 }
1375                 g_free(characteristic.handle);
1376                 g_object_unref(proxy);
1377                 return;
1378         }
1379
1380         g_variant_get(value, "(v)", &char_value);
1381         g_variant_get(char_value, "ao", &char_iter);
1382
1383         while (g_variant_iter_loop(char_iter, "&o",  &char_handle)) {
1384                 BT_DBG("object path of descriptor = %s", char_handle);
1385                 if (char_handle) {
1386                         ret = __bluetooth_gatt_descriptor_iter(char_handle,
1387                                                 &characteristic);
1388                         BT_DBG("Descriptor read status [%d]", ret);
1389                 }
1390         }
1391
1392         if (user_info) {
1393                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1394                                 ret, &characteristic, user_info->cb, user_info->user_data);
1395         }
1396         bluetooth_gatt_free_char_property(&characteristic);
1397
1398         g_free(characteristic.handle);
1399         g_variant_iter_free(char_iter);
1400         g_variant_unref(value);
1401         BT_DBG("-");
1402 }
1403
1404 BT_EXPORT_API int bluetooth_gatt_discover_characteristic_descriptor(
1405                         const char *characteristic_handle)
1406 {
1407         GDBusProxy *properties_proxy = NULL;
1408         GDBusConnection *g_conn;
1409         char *handle;
1410         GError *error = NULL;
1411
1412         BT_CHECK_PARAMETER(characteristic_handle, return);
1413         BT_CHECK_ENABLED(return);
1414
1415         g_conn = _bt_gdbus_get_system_gconn();
1416         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1417
1418         properties_proxy = g_dbus_proxy_new_sync(g_conn,
1419                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1420                         BT_BLUEZ_NAME,
1421                         characteristic_handle,
1422                         BT_PROPERTIES_INTERFACE,
1423                         NULL, &error);
1424
1425         retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1426
1427         handle = g_strdup(characteristic_handle);
1428         g_dbus_proxy_call(properties_proxy,
1429                         "Get",
1430                         g_variant_new("(ss)",
1431                                 GATT_CHAR_INTERFACE, "Descriptors"),
1432                         G_DBUS_CALL_FLAGS_NONE,
1433                         -1, NULL,
1434                         (GAsyncReadyCallback)bluetooth_gatt_get_char_desc_cb,
1435                         (gpointer)handle);
1436
1437         return BLUETOOTH_ERROR_NONE;
1438 }
1439
1440 static void __bluetooth_internal_read_desc_cb(GObject *source_object,
1441                         GAsyncResult *res,
1442                         gpointer user_data)
1443 {
1444         GError *error = NULL;
1445         bt_user_info_t *user_info;
1446         bt_gatt_char_property_t char_value =  { 0, };
1447         GDBusConnection *system_gconn = NULL;
1448         GVariant *value;
1449         GByteArray *gp_byte_array = NULL;
1450         GVariantIter *iter;
1451         guint8 g_byte;
1452         int att_ecode = 0;
1453
1454         BT_DBG("+");
1455         user_info = _bt_get_user_data(BT_COMMON);
1456         system_gconn = _bt_gdbus_get_system_gconn();
1457
1458         char_value.handle = user_data;
1459         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1460
1461         if (error) {
1462                 att_ecode = __bluetooth_get_att_error_code(error);
1463                 g_clear_error(&error);
1464                 if (user_info) {
1465                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1466                                         att_ecode, NULL,
1467                                         user_info->cb, user_info->user_data);
1468                 }
1469                 g_free(char_value.handle);
1470                 g_variant_unref(value);
1471                 return;
1472         }
1473
1474         g_variant_get(value, "(ay)", &iter);
1475
1476         gp_byte_array = g_byte_array_new();
1477         while (g_variant_iter_loop(iter, "y",  &g_byte))
1478                 g_byte_array_append(gp_byte_array, &g_byte, 1);
1479
1480         if (gp_byte_array->len != 0) {
1481                 char_value.val_len = (unsigned int)gp_byte_array->len;
1482                 char_value.description = (char *)gp_byte_array->data;
1483         }
1484
1485         if (user_info) {
1486                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1487                                 BLUETOOTH_ATT_ERROR_NONE, &char_value,
1488                                 user_info->cb, user_info->user_data);
1489         }
1490
1491         g_byte_array_free(gp_byte_array, TRUE);
1492         g_free(char_value.handle);
1493         g_variant_unref(value);
1494         g_variant_iter_free(iter);
1495
1496         BT_DBG("-");
1497 }
1498
1499 BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *char_descriptor)
1500 {
1501         GDBusConnection *conn;
1502         GVariantBuilder *builder;
1503         guint offset = 0;
1504         char *handle;
1505
1506         BT_DBG("+");
1507         BT_CHECK_PARAMETER(char_descriptor, return);
1508         BT_CHECK_ENABLED(return);
1509
1510         conn = _bt_gdbus_get_system_gconn();
1511         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1512
1513         handle = g_strdup(char_descriptor);
1514
1515         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1516
1517         /*offset*/
1518         g_variant_builder_add(builder, "{sv}", "offset",
1519                                 g_variant_new("q", offset));
1520         /* Device Object path*/
1521 //  g_variant_builder_add(builder, "{sv}", "device",
1522 //  g_variant_new("o", serv_info->serv_path));
1523
1524         g_dbus_connection_call(conn,
1525                         BT_BLUEZ_NAME,
1526                         char_descriptor,
1527                         GATT_DESC_INTERFACE,
1528                         "ReadValue",
1529                         g_variant_new("(a{sv})", builder),
1530                         G_VARIANT_TYPE("(ay)"),
1531                         G_DBUS_CALL_FLAGS_NONE,
1532                         -1,
1533                         NULL,
1534                         (GAsyncReadyCallback)__bluetooth_internal_read_desc_cb,
1535                         (gpointer)handle);
1536         g_variant_builder_unref(builder);
1537
1538         BT_DBG("-");
1539         return BLUETOOTH_ERROR_NONE;
1540 }
1541
1542 static void __bluetooth_internal_write_desc_cb(GObject *source_object,
1543                         GAsyncResult *res,
1544                         gpointer user_data)
1545 {
1546         GError *error = NULL;
1547         bt_user_info_t *user_info;
1548         GDBusConnection *system_gconn = NULL;
1549         GVariant *value;
1550         int att_ecode = BLUETOOTH_ATT_ERROR_NONE;
1551
1552         BT_DBG("+");
1553         user_info = _bt_get_user_data(BT_COMMON);
1554
1555         system_gconn = _bt_gdbus_get_system_gconn();
1556         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1557
1558         if (error) {
1559                 att_ecode = __bluetooth_get_att_error_code(error);
1560                 g_clear_error(&error);
1561         }
1562
1563         if (user_info) {
1564                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1565                                 att_ecode, NULL,
1566                                 user_info->cb, user_info->user_data);
1567         }
1568
1569         if (value)
1570                 g_variant_unref(value);
1571
1572         BT_DBG("-");
1573 }
1574
1575 BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(
1576                         const char *desc_handle, const guint8 *value, int length)
1577 {
1578         GVariant *val, *options;
1579         GDBusConnection *conn;
1580         GVariantBuilder *builder1;
1581         GVariantBuilder *builder2;
1582         guint offset = 0;
1583         int i;
1584
1585         BT_DBG("+");
1586         BT_CHECK_PARAMETER(desc_handle, return);
1587         BT_CHECK_PARAMETER(value, return);
1588         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1589         BT_CHECK_ENABLED(return);
1590
1591         conn = _bt_gdbus_get_system_gconn();
1592         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1593
1594         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1595
1596         for (i = 0; i < length; i++)
1597                 g_variant_builder_add(builder1, "y", value[i]);
1598
1599         val = g_variant_new("ay", builder1);
1600
1601         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1602         /*offset*/
1603         g_variant_builder_add(builder2, "{sv}", "offset",
1604                                 g_variant_new_uint16(offset));
1605
1606         /* Device Object path*/
1607 //      g_variant_builder_add(builder2, "{sv}", "device",
1608 //      g_variant_new_object("o", NULL));
1609
1610         options = g_variant_new("a{sv}", builder2);
1611
1612         g_dbus_connection_call(conn,
1613                                 BT_BLUEZ_NAME,
1614                                 desc_handle,
1615                                 GATT_DESC_INTERFACE,
1616                                 "WriteValue",
1617                                 g_variant_new("(@ay@a{sv})",
1618                                 val, options),
1619                                 NULL,
1620                                 G_DBUS_CALL_FLAGS_NONE,
1621                                 -1, NULL,
1622                                 (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
1623                                 NULL);
1624
1625         g_variant_builder_unref(builder1);
1626         g_variant_builder_unref(builder2);
1627
1628         BT_DBG("-");
1629         return BLUETOOTH_ERROR_NONE;
1630 }
1631
1632 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle)
1633 {
1634         GDBusConnection *conn;
1635         GError *error = NULL;
1636         int ret = BLUETOOTH_ERROR_NONE;
1637
1638         BT_CHECK_PARAMETER(char_handle, return);
1639         BT_CHECK_ENABLED(return);
1640
1641         BT_INFO_C("### Enable CCCD : %s", char_handle);
1642
1643         conn = _bt_gdbus_get_system_gconn();
1644         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1645
1646         g_dbus_connection_call_sync(conn,
1647                         BT_BLUEZ_NAME,
1648                         char_handle,
1649                         GATT_CHAR_INTERFACE,
1650                         "StartNotify",
1651                         NULL,
1652                         NULL,
1653                         G_DBUS_CALL_FLAGS_NONE,
1654                         GATT_DEFAULT_TIMEOUT, NULL, &error);
1655
1656         if (error) {
1657                 g_dbus_error_strip_remote_error(error);
1658                 BT_ERR_C("### Watch Failed: %s", error->message);
1659                 if (g_strrstr(error->message, "Already notifying"))
1660                         ret = BLUETOOTH_ERROR_NONE;
1661                 else if (g_strrstr(error->message, "In Progress"))
1662                         ret = BLUETOOTH_ERROR_IN_PROGRESS;
1663                 else if (g_strrstr(error->message, "Operation is not supported"))
1664                         ret = BLUETOOTH_ERROR_NOT_SUPPORT;
1665 /*failed because of either Insufficient Authorization or Write Not Permitted */
1666                 else if (g_strrstr(error->message, "Write not permitted") ||
1667                                 g_strrstr(error->message, "Operation Not Authorized"))
1668                         ret = BLUETOOTH_ERROR_PERMISSION_DEINED;
1669 /* failed because of either Insufficient Authentication,
1670         Insufficient Encryption Key Size, or Insufficient Encryption. */
1671                 else if (g_strrstr(error->message, "Not paired"))
1672                         ret = BLUETOOTH_ERROR_NOT_PAIRED;
1673                 else
1674                         ret = BLUETOOTH_ERROR_INTERNAL;
1675
1676                 g_clear_error(&error);
1677         }
1678
1679         return ret;
1680 }
1681
1682 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle)
1683 {
1684
1685         GDBusConnection *conn;
1686         GError *error = NULL;
1687         int ret = BLUETOOTH_ERROR_NONE;
1688         BT_CHECK_PARAMETER(char_handle, return);
1689
1690         BT_CHECK_ENABLED(return);
1691
1692         BT_INFO("Disable CCCD : %s", char_handle);
1693
1694         conn = _bt_gdbus_get_system_gconn();
1695         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1696
1697         g_dbus_connection_call_sync(conn,
1698                         BT_BLUEZ_NAME,
1699                         char_handle,
1700                         GATT_CHAR_INTERFACE,
1701                         "StopNotify",
1702                         NULL,
1703                         NULL,
1704                         G_DBUS_CALL_FLAGS_NONE,
1705                         GATT_DEFAULT_TIMEOUT, NULL, &error);
1706
1707         if (error) {
1708                 BT_ERR("Watch Failed: %s", error->message);
1709                 g_clear_error(&error);
1710                 ret =  BLUETOOTH_ERROR_INTERNAL;
1711         }
1712
1713         return ret;
1714 }