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