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