Fix issues in the merged Tizen 3.0 code
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-gatt.c
1 /*
2  * bluetooth-frwk
3  *
4  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *              http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <string.h>
21 #include <dbus/dbus.h>
22 #include <dbus/dbus-glib.h>
23 #include <glib.h>
24
25 #include "bluetooth-api.h"
26 #include "bt-common.h"
27 #include "bt-internal-types.h"
28
29
30 #define BLUEZ_CHAR_INTERFACE "org.bluez.Characteristic"
31
32 #define GATT_OBJECT_PATH  "/org/bluez/gatt_attrib"
33
34 typedef struct {
35         GObject parent;
36 } BluetoothGattService;
37
38 typedef struct {
39         GObjectClass parent;
40 } BluetoothGattServiceClass;
41
42 typedef struct {
43         char *char_uuid;
44         char **handle;
45 } char_pty_req_t;
46
47 GType bluetooth_gatt_service_get_type(void);
48
49 #define BLUETOOTH_GATT_TYPE_SERVICE (bluetooth_gatt_service_get_type())
50
51 #define BLUETOOTH_GATT_SERVICE(object)  \
52                 (G_TYPE_CHECK_INSTANCE_CAST((object), \
53                 BLUETOOTH_GATT_TYPE_SERVICE, BluetoothGattService))
54
55 #define BLUETOOTH_GATT_SERVICE_CLASS(klass)     \
56                 (G_TYPE_CHECK_CLASS_CAST((klass), \
57                 BLUETOOTH_GATT_TYPE_SERVICE, BluetoothGattServiceClass))
58
59 #define BLUETOOTH_GATT_IS_SERVICE(object)       \
60                 (G_TYPE_CHECK_INSTANCE_TYPE((object), BLUETOOTH_GATT_TYPE_SERVICE))
61
62 #define BLUETOOTH_GATT_IS_SERVICE_CLASS(klass)  \
63                 (G_TYPE_CHECK_CLASS_TYPE((klass), BLUETOOTH_GATT_TYPE_SERVICE))
64
65 #define BLUETOOTH_GATT_SERVICE_GET_CLASS(obj)   \
66                 (G_TYPE_INSTANCE_GET_CLASS((obj), \
67                 BLUETOOTH_GATT_TYPE_SERVICE, BluetoothGattServiceClass))
68
69 G_DEFINE_TYPE(BluetoothGattService, bluetooth_gatt_service, G_TYPE_OBJECT)
70
71 static gboolean bluetooth_gatt_value_changed(BluetoothGattService *agent,
72                                         gchar *obj_path,
73                                         GArray *byte_array,
74                                         DBusGMethodInvocation *context);
75
76 #include "bt-gatt-glue.h"
77
78 static void bluetooth_gatt_service_init(BluetoothGattService *obj)
79 {
80         g_assert(obj != NULL);
81 }
82
83 static void bluetooth_gatt_service_finalize(GObject *obj)
84 {
85         G_OBJECT_CLASS(bluetooth_gatt_service_parent_class)->finalize(obj);
86 }
87
88 static void bluetooth_gatt_service_class_init(BluetoothGattServiceClass *klass)
89 {
90         GObjectClass *object_class = (GObjectClass *)klass;
91
92         g_assert(klass != NULL);
93
94         object_class->finalize = bluetooth_gatt_service_finalize;
95
96         dbus_g_object_type_install_info(BLUETOOTH_GATT_TYPE_SERVICE,
97                                         &dbus_glib_bluetooth_gatt_object_info);
98 }
99
100 static gboolean bluetooth_gatt_value_changed(BluetoothGattService *agent,
101                                         gchar *obj_path,
102                                         GArray *byte_array,
103                                         DBusGMethodInvocation *context)
104 {
105         bt_gatt_char_value_t char_val;
106         bt_user_info_t *user_info;
107         BT_DBG("+");
108
109         char_val.char_handle = obj_path;
110         char_val.char_value = &g_array_index(byte_array, guint8, 0);
111         char_val.val_len = byte_array->len;
112         BT_DBG("Byte array length = %d", char_val.val_len);
113
114         user_info = _bt_get_user_data(BT_COMMON);
115
116         if (user_info) {
117                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED,
118                                 BLUETOOTH_ERROR_NONE, &char_val,
119                                 user_info->cb, user_info->user_data);
120         }
121
122         BT_DBG("-");
123
124         return TRUE;
125 }
126
127 static void __add_value_changed_method(DBusGConnection *conn)
128 {
129         static gboolean method_added = FALSE;
130         BluetoothGattService *bluetooth_gatt_obj = NULL;
131
132         if (method_added) {
133                 BT_ERR("Method already added. \n");
134                 return;
135         }
136
137         method_added = TRUE;
138
139         bluetooth_gatt_obj = g_object_new(BLUETOOTH_GATT_TYPE_SERVICE, NULL);
140
141         dbus_g_connection_register_g_object(conn, GATT_OBJECT_PATH,
142                         G_OBJECT(bluetooth_gatt_obj));
143
144 }
145
146 static char **__get_string_array_from_gptr_array(GPtrArray *gp)
147 {
148         gchar *gp_path = NULL;
149         char **path = NULL;
150         int i;
151
152         if (gp->len == 0)
153                 return NULL;
154
155         path = g_malloc0((gp->len + 1) * sizeof(char *));
156
157         for (i = 0; i < gp->len; i++) {
158                 gp_path = g_ptr_array_index(gp, i);
159                 path[i] = g_strdup(gp_path);
160                 BT_DBG("path[%d] : [%s]", i, path[i]);
161         }
162
163         return path;
164 }
165
166 static void __bluetooth_internal_get_char_cb(DBusGProxy *proxy,
167                                         DBusGProxyCall *call,
168                                         gpointer user_data)
169 {
170         GError *error = NULL;
171         GPtrArray *gp_array = NULL;
172         bt_gatt_discovered_char_t svc_char = { 0, };
173         bt_user_info_t *user_info;
174
175         svc_char.service_handle = user_data;
176
177         user_info = _bt_get_user_data(BT_COMMON);
178
179         if (!dbus_g_proxy_end_call(proxy, call, &error,
180                 dbus_g_type_get_collection("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
181                 &gp_array, G_TYPE_INVALID)) {
182                 BT_ERR("Error : %s \n", error->message);
183                 g_error_free(error);
184
185                 if (user_info) {
186                         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
187                                         BLUETOOTH_ERROR_NONE, &svc_char,
188                                         user_info->cb, user_info->user_data);
189                 }
190                 g_free(svc_char.service_handle);
191                 g_object_unref(proxy);
192                 return;
193         }
194
195         if (NULL != gp_array) {
196                 svc_char.handle_info.count = gp_array->len;
197                 svc_char.handle_info.handle = __get_string_array_from_gptr_array(gp_array);
198         }
199
200         if (user_info) {
201                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
202                                 BLUETOOTH_ERROR_NONE, &svc_char,
203                                 user_info->cb, user_info->user_data);
204         }
205
206         g_ptr_array_free(gp_array, TRUE);
207         g_free(svc_char.service_handle);
208         g_free(svc_char.handle_info.handle);
209         g_object_unref(proxy);
210 }
211
212 static void __free_char_req(char_pty_req_t *char_req)
213 {
214         g_free(char_req->char_uuid);
215         g_strfreev(char_req->handle);
216         g_free(char_req);
217 }
218
219 static gboolean __filter_chars_with_uuid(gpointer data)
220 {
221         int i = 0;
222         bt_gatt_char_property_t *char_pty;
223         char_pty_req_t *char_req = data;
224         bt_user_info_t *user_info;
225         int ret;
226
227         user_info = _bt_get_user_data(BT_COMMON);
228         if (user_info == NULL) {
229                 __free_char_req(char_req);
230                 return FALSE;
231         }
232
233         char_pty = g_new0(bt_gatt_char_property_t, 1);
234
235         while (char_req->handle[i] != NULL) {
236                 BT_DBG("char_pty[%d] = %s", i, char_req->handle[i]);
237                 ret = bluetooth_gatt_get_characteristics_property(char_req->handle[i],
238                                                                         char_pty);
239                 if (ret != BLUETOOTH_ERROR_NONE) {
240                         BT_ERR("get char property failed");
241                         goto done;
242                 }
243
244                 if (char_pty->uuid  && g_strstr_len(char_pty->uuid, -1,
245                                                 char_req->char_uuid) != NULL) {
246                         BT_DBG("Requested Char recieved");
247                         ret = BLUETOOTH_ERROR_NONE;
248                         break;
249                 }
250
251                 bluetooth_gatt_free_char_property(char_pty);
252
253                 i++;
254         }
255
256 done:
257         if (char_req->handle[i] == NULL)
258                 ret = BLUETOOTH_ERROR_NOT_FOUND;
259
260         _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret,
261                                 char_pty, user_info->cb, user_info->user_data);
262
263         g_free(char_pty);
264         __free_char_req(char_req);
265
266         return FALSE;
267 }
268
269 static void __disc_char_from_uuid_cb(DBusGProxy *proxy,
270                                         DBusGProxyCall *call,
271                                         gpointer user_data)
272 {
273         GError *error = NULL;
274         GPtrArray *gp_array = NULL;
275         bt_user_info_t *user_info;
276         char_pty_req_t *char_req = user_data;
277
278         user_info = _bt_get_user_data(BT_COMMON);
279         if (!user_info) {
280                 __free_char_req(char_req);
281                 return;
282         }
283
284         if (!dbus_g_proxy_end_call(proxy, call, &error,
285                 dbus_g_type_get_collection("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
286                 &gp_array, G_TYPE_INVALID)) {
287                 BT_ERR("Error : %s \n", error->message);
288                 g_error_free(error);
289
290                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
291                                         BLUETOOTH_ERROR_INTERNAL, NULL,
292                                         user_info->cb, user_info->user_data);
293
294                 __free_char_req(char_req);
295                 g_object_unref(proxy);
296                 return;
297         }
298
299         if (gp_array == NULL) {
300                 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
301                                         BLUETOOTH_ERROR_NOT_FOUND, NULL,
302                                         user_info->cb, user_info->user_data);
303
304                 __free_char_req(char_req);
305                 g_object_unref(proxy);
306
307                 return;
308         }
309
310         char_req->handle = __get_string_array_from_gptr_array(gp_array);
311
312         __filter_chars_with_uuid(char_req);
313
314         g_ptr_array_free(gp_array, TRUE);
315         g_object_unref(proxy);
316 }
317
318
319 static int __discover_char_from_uuid(const char *service_handle,
320                                                         const char *char_uuid){
321         DBusGProxy *service_proxy = NULL;
322         DBusGConnection *conn;
323         char_pty_req_t *char_req;
324
325         conn = _bt_get_system_gconn();
326         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
327
328         service_proxy = dbus_g_proxy_new_for_name(conn,
329                                                 BT_BLUEZ_NAME, service_handle,
330                                                 BLUEZ_CHAR_INTERFACE);
331         retv_if(service_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
332
333         char_req = g_new0(char_pty_req_t, 1);
334
335         char_req->char_uuid = g_strdup(char_uuid);
336         BT_DBG("Char uuid %s ", char_uuid);
337
338         if (!dbus_g_proxy_begin_call(service_proxy, "DiscoverCharacteristics",
339                         (DBusGProxyCallNotify)__disc_char_from_uuid_cb,
340                         char_req, NULL, G_TYPE_INVALID)) {
341                 __free_char_req(char_req);
342                 g_object_unref(service_proxy);
343                 return BLUETOOTH_ERROR_INTERNAL;
344         }
345
346         return BLUETOOTH_ERROR_NONE;
347 }
348
349 BT_EXPORT_API int bluetooth_gatt_free_primary_services(bt_gatt_handle_info_t *prim_svc)
350 {
351         BT_DBG("+");
352
353         BT_CHECK_PARAMETER(prim_svc, return);
354
355         g_strfreev(prim_svc->handle);
356
357         memset(prim_svc, 0, sizeof(bt_gatt_handle_info_t));
358
359         BT_DBG("-");
360         return BLUETOOTH_ERROR_NONE;
361 }
362
363 BT_EXPORT_API int bluetooth_gatt_free_service_property(bt_gatt_service_property_t *svc_pty)
364 {
365         BT_DBG("+");
366
367         BT_CHECK_PARAMETER(svc_pty, return);
368
369         g_free(svc_pty->uuid);
370         g_free(svc_pty->handle);
371         g_strfreev(svc_pty->handle_info.handle);
372
373         memset(svc_pty, 0, sizeof(bt_gatt_service_property_t));
374
375         BT_DBG("-");
376         return BLUETOOTH_ERROR_NONE;
377 }
378
379 BT_EXPORT_API int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty)
380 {
381         BT_DBG("+");
382
383         BT_CHECK_PARAMETER(char_pty, return);
384
385         g_free(char_pty->uuid);
386         g_free(char_pty->name);
387         g_free(char_pty->description);
388         g_free(char_pty->val);
389         g_free(char_pty->handle);
390
391         memset(char_pty, 0, sizeof(bt_gatt_char_property_t));
392
393         BT_DBG("-");
394         return BLUETOOTH_ERROR_NONE;
395 }
396
397 BT_EXPORT_API int bluetooth_gatt_get_primary_services(const bluetooth_device_address_t *address,
398                                                                 bt_gatt_handle_info_t *prim_svc)
399 {
400         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
401         gchar *device_path = NULL;
402         GError *error = NULL;
403         DBusGProxy *device_proxy = NULL;
404         GHashTable *hash = NULL;
405         GValue *value = NULL;
406         GPtrArray *gp_array  = NULL;
407         DBusGProxy *adapter_proxy;
408         DBusGConnection *conn;
409         int ret = BLUETOOTH_ERROR_INTERNAL;
410
411         BT_DBG("+");
412
413         BT_CHECK_PARAMETER(address, return);
414         BT_CHECK_PARAMETER(prim_svc, return);
415
416         BT_CHECK_ENABLED(return);
417
418         _bt_convert_addr_type_to_string(device_address,
419                                 (unsigned char *)address->addr);
420
421         BT_DBG("bluetooth address [%s]\n", device_address);
422
423         conn = _bt_get_system_gconn();
424         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
425
426         adapter_proxy = _bt_get_adapter_proxy(conn);
427         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
428
429         dbus_g_proxy_call(adapter_proxy, "FindDevice", &error,
430                 G_TYPE_STRING, device_address, G_TYPE_INVALID,
431                 DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID);
432         if (error) {
433                 BT_ERR("FindDevice Call Error %s[%s]", error->message, device_address);
434                 g_error_free(error);
435                 g_object_unref(adapter_proxy);
436                 return BLUETOOTH_ERROR_INTERNAL;
437         }
438
439         g_object_unref(adapter_proxy);
440
441         retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL);
442
443         device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
444                                       device_path, BT_DEVICE_INTERFACE);
445         g_free(device_path);
446         retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
447
448         dbus_g_proxy_call(device_proxy, "GetProperties", &error, G_TYPE_INVALID,
449                                 dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
450                                 &hash, G_TYPE_INVALID);
451         if (error) {
452                 BT_ERR("GetProperties Call Error %s[%s]", error->message, device_address);
453                 g_error_free(error);
454                 g_object_unref(device_proxy);
455                 return BLUETOOTH_ERROR_INTERNAL;
456         }
457
458         g_object_unref(device_proxy);
459
460         retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL);
461
462         value = g_hash_table_lookup(hash, "Services");
463         if (value == NULL) {
464                 BT_ERR("value == NULL");
465                 goto done;
466         }
467
468         gp_array = g_value_get_boxed(value);
469         if (gp_array == NULL) {
470                 BT_ERR("gp_array == NULL");
471                 goto done;
472         }
473
474         prim_svc->count = gp_array->len;
475         prim_svc->handle = __get_string_array_from_gptr_array(gp_array);
476
477         ret = BLUETOOTH_ERROR_NONE;
478 done:
479         g_hash_table_destroy(hash);
480         BT_DBG("-");
481         return ret;
482 }
483
484 BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(const char *service_handle)
485 {
486         DBusGProxy *service_proxy = NULL;
487         char *handle;
488         DBusGConnection *conn;
489
490         BT_CHECK_PARAMETER(service_handle, return);
491
492         BT_CHECK_ENABLED(return);
493
494         conn = _bt_get_system_gconn();
495         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
496
497         service_proxy = dbus_g_proxy_new_for_name(conn,
498                                                 BT_BLUEZ_NAME, service_handle,
499                                                 BLUEZ_CHAR_INTERFACE);
500
501         retv_if(service_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
502
503         handle = g_strdup(service_handle);
504         BT_DBG("Requested characteristic handle:%s \n ", handle);
505
506         if (!dbus_g_proxy_begin_call(service_proxy, "DiscoverCharacteristics",
507                         (DBusGProxyCallNotify)__bluetooth_internal_get_char_cb,
508                         handle, NULL, G_TYPE_INVALID)) {
509                 g_free(handle);
510                 g_object_unref(service_proxy);
511                 return BLUETOOTH_ERROR_INTERNAL;
512         }
513
514         return BLUETOOTH_ERROR_NONE;
515 }
516
517 BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle,
518                                                 bt_gatt_service_property_t *service)
519 {
520         DBusGProxy *service_proxy = NULL;
521         GHashTable *hash = NULL;
522         GError *error = NULL;
523         GValue *value = NULL;
524         GPtrArray *gp_array  = NULL ;
525         DBusGConnection *conn;
526
527         BT_CHECK_PARAMETER(service_handle, return);
528         BT_CHECK_PARAMETER(service, return);
529
530         BT_CHECK_ENABLED(return);
531
532         conn = _bt_get_system_gconn();
533         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
534
535         service_proxy = dbus_g_proxy_new_for_name(conn,
536                                                 BT_BLUEZ_NAME, service_handle,
537                                                 BLUEZ_CHAR_INTERFACE);
538
539         retv_if(service_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
540
541         dbus_g_proxy_call(service_proxy, "GetProperties", &error, G_TYPE_INVALID,
542                                 dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
543                                 &hash, G_TYPE_INVALID);
544         if (error != NULL) {
545                 BT_ERR("GetProperties Call Error %s\n", error->message);
546                 g_error_free(error);
547                 g_object_unref(service_proxy);
548                 return BLUETOOTH_ERROR_INTERNAL;
549         }
550         g_object_unref(service_proxy);
551
552         retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL);
553
554         memset(service, 0, sizeof(bt_gatt_service_property_t));
555
556         value = g_hash_table_lookup(hash, "UUID");
557         service->uuid = value ? g_value_dup_string(value) : NULL;
558         if (service->uuid) {
559                 BT_DBG("svc_pty.uuid = [%s] \n", service->uuid);
560         }
561
562         value = g_hash_table_lookup(hash, "Characteristics");
563         gp_array = value ? g_value_get_boxed(value) : NULL;
564         if (gp_array) {
565                 service->handle_info.count = gp_array->len;
566                 service->handle_info.handle = __get_string_array_from_gptr_array(gp_array);
567         }
568
569         service->handle = g_strdup(service_handle);
570         g_hash_table_destroy(hash);
571         return BLUETOOTH_ERROR_NONE;
572 }
573
574 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *service_handle)
575 {
576         DBusGProxy *watch_proxy = NULL;
577         GError *error = NULL;
578         DBusGConnection *conn;
579
580         BT_CHECK_PARAMETER(service_handle, return);
581
582         BT_CHECK_ENABLED(return);
583
584         BT_DBG("Entered service handle:%s \n ", service_handle);
585
586         conn = _bt_get_system_gconn();
587         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
588
589         watch_proxy = dbus_g_proxy_new_for_name(conn,
590                                 BT_BLUEZ_NAME, service_handle,
591                                 BLUEZ_CHAR_INTERFACE);
592
593         retv_if(watch_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
594
595         __add_value_changed_method(conn);
596
597         dbus_g_proxy_call(watch_proxy, "RegisterCharacteristicsWatcher", &error,
598                                 DBUS_TYPE_G_OBJECT_PATH, GATT_OBJECT_PATH,
599                                 G_TYPE_INVALID, G_TYPE_INVALID);
600         if (error) {
601                 BT_ERR("Method call  Fail: %s", error->message);
602                 g_error_free(error);
603                 g_object_unref(watch_proxy);
604                 return BLUETOOTH_ERROR_INTERNAL;
605         }
606
607         g_object_unref(watch_proxy);
608
609         return BLUETOOTH_ERROR_NONE;
610 }
611
612 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *service_handle)
613 {
614         DBusGProxy *watch_proxy = NULL;
615         GError *error = NULL;
616         DBusGConnection *conn;
617
618         BT_CHECK_PARAMETER(service_handle, return);
619
620         BT_CHECK_ENABLED(return);
621
622         conn = _bt_get_system_gconn();
623         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
624
625         watch_proxy = dbus_g_proxy_new_for_name(conn,
626                                 BT_BLUEZ_NAME, service_handle,
627                                 BLUEZ_CHAR_INTERFACE);
628
629         retv_if(watch_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
630
631         dbus_g_proxy_call(watch_proxy, "UnregisterCharacteristicsWatcher", &error,
632                                 DBUS_TYPE_G_OBJECT_PATH, GATT_OBJECT_PATH,
633                                 G_TYPE_INVALID, G_TYPE_INVALID);
634         if (error) {
635                 BT_ERR("Method call  Fail: %s", error->message);
636                 g_error_free(error);
637                 g_object_unref(watch_proxy);
638                 return BLUETOOTH_ERROR_INTERNAL;
639         }
640
641         g_object_unref(watch_proxy);
642
643         return BLUETOOTH_ERROR_NONE;
644 }
645
646 BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(const char *char_handle,
647                                                 bt_gatt_char_property_t *characteristic)
648 {
649         DBusGProxy *characteristic_proxy = NULL;
650         GHashTable *hash = NULL;
651         GError *error = NULL;
652         GValue *value = NULL;
653         GByteArray *gb_array = NULL;
654         DBusGConnection *conn;
655
656         BT_CHECK_PARAMETER(char_handle, return);
657         BT_CHECK_PARAMETER(characteristic, return);
658
659         BT_CHECK_ENABLED(return);
660
661         conn = _bt_get_system_gconn();
662         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
663
664         characteristic_proxy = dbus_g_proxy_new_for_name(conn,
665                                                 BT_BLUEZ_NAME, char_handle,
666                                                 BLUEZ_CHAR_INTERFACE);
667
668         retv_if(characteristic_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
669
670         dbus_g_proxy_call(characteristic_proxy, "GetProperties", &error, G_TYPE_INVALID,
671                                 dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
672                                 &hash, G_TYPE_INVALID);
673         if (error != NULL) {
674                 BT_ERR("GetProperties Call Error %s\n", error->message);
675                 g_error_free(error);
676                 g_object_unref(characteristic_proxy);
677                 return BLUETOOTH_ERROR_INTERNAL;
678         }
679         g_object_unref(characteristic_proxy);
680
681         retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL);
682
683         memset(characteristic, 0, sizeof(bt_gatt_char_property_t));
684
685         value = g_hash_table_lookup(hash, "UUID");
686         characteristic->uuid = value ? g_value_dup_string(value) : NULL;
687         if (characteristic->uuid) {
688                 BT_DBG("characteristic->uuid = [%s] \n", characteristic->uuid);
689         }
690
691         value = g_hash_table_lookup(hash, "Name");
692         characteristic->name = value ? g_value_dup_string(value) : NULL;
693         if (characteristic->name) {
694                 BT_DBG("characteristic->name = [%s] \n", characteristic->name);
695         }
696
697         value = g_hash_table_lookup(hash, "Description");
698         characteristic->description = value ? g_value_dup_string(value) : NULL;
699         if (characteristic->description) {
700                 BT_DBG("characteristic->description = [%s] \n", characteristic->description);
701         }
702
703         value = g_hash_table_lookup(hash, "Value");
704
705         gb_array = value ? g_value_get_boxed(value) : NULL;
706         if (gb_array) {
707                 if (gb_array->len) {
708                         BT_DBG("gb_array->len  = %d \n", gb_array->len);
709                         characteristic->val_len = gb_array->len;
710
711                         characteristic->val = g_malloc0(gb_array->len * sizeof(unsigned char));
712                         memcpy(characteristic->val, gb_array->data, gb_array->len);
713                 } else {
714                         characteristic->val = NULL;
715                         characteristic->val_len = 0;
716                 }
717         } else {
718                 characteristic->val = NULL;
719                 characteristic->val_len = 0;
720         }
721         characteristic->handle = g_strdup(char_handle);
722         g_hash_table_destroy(hash);
723         return BLUETOOTH_ERROR_NONE;
724 }
725
726 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(const char *char_handle,
727                                                 const guint8 *value, int length)
728 {
729         DBusGProxy *characteristic_proxy = NULL;
730         GValue *val;
731         GByteArray *gbarray;
732         GError *error = NULL;
733         DBusGConnection *conn;
734
735         BT_CHECK_PARAMETER(char_handle, return);
736         BT_CHECK_PARAMETER(value, return);
737         retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
738
739         BT_CHECK_ENABLED(return);
740
741         conn = _bt_get_system_gconn();
742         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
743
744         BT_DBG("Requested characteristic handle:%s \n ", char_handle);
745
746         characteristic_proxy = dbus_g_proxy_new_for_name(conn,
747                                                         BT_BLUEZ_NAME, char_handle,
748                                                         BLUEZ_CHAR_INTERFACE);
749
750         retv_if(characteristic_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
751
752         gbarray = g_byte_array_new();
753         g_byte_array_append(gbarray, (guint8 *)value, length);
754
755         val = g_new0(GValue, 1);
756         g_value_init(val, DBUS_TYPE_G_UCHAR_ARRAY);
757         g_value_take_boxed(val, gbarray);
758
759         dbus_g_proxy_call(characteristic_proxy, "SetProperty",
760                 &error, G_TYPE_STRING, "Value",
761                 G_TYPE_VALUE, val, G_TYPE_INVALID, G_TYPE_INVALID);
762
763         g_object_unref(characteristic_proxy);
764         g_free(val);
765
766         if (error) {
767                 BT_ERR("Set value Fail: %s", error->message);
768                 g_error_free(error);
769                 return BLUETOOTH_ERROR_INTERNAL;
770         }
771
772         return BLUETOOTH_ERROR_NONE;
773 }
774
775 BT_EXPORT_API int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address,
776                                         const char *service_uuid,
777                                         bt_gatt_service_property_t *service)
778 {
779         int i;
780         int ret;
781         bt_gatt_handle_info_t prim_svc;
782
783         BT_CHECK_PARAMETER(address, return);
784         BT_CHECK_PARAMETER(service_uuid, return);
785         BT_CHECK_PARAMETER(service, return);
786
787         BT_CHECK_ENABLED(return);
788
789         ret = bluetooth_gatt_get_primary_services(address, &prim_svc);
790         if (ret != BLUETOOTH_ERROR_NONE) {
791                 BT_ERR("Get primary service failed ");
792                 return ret;
793         }
794
795         for (i = 0; i < prim_svc.count; i++) {
796
797                 BT_DBG("prim_svc [%d] = %s", i, prim_svc.handle[i]);
798
799                 ret = bluetooth_gatt_get_service_property(prim_svc.handle[i],
800                                                                 service);
801                 if (ret != BLUETOOTH_ERROR_NONE) {
802                         BT_ERR("Get service property failed ");
803                         bluetooth_gatt_free_primary_services(&prim_svc);
804                         return ret;
805                 }
806
807                 BT_DBG("Service uuid %s", service->uuid);
808
809                 if (g_strstr_len(service->uuid, -1, service_uuid)) {
810                         BT_DBG("Found requested service");
811                         ret = BLUETOOTH_ERROR_NONE;
812                         break;
813                 }
814
815                 bluetooth_gatt_free_service_property(service);
816         }
817
818         if (i == prim_svc.count)
819                 ret = BLUETOOTH_ERROR_NOT_FOUND;
820
821         bluetooth_gatt_free_primary_services(&prim_svc);
822
823         return ret;
824 }
825
826 BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
827                                                 const char *char_uuid)
828 {
829         char **char_handles;
830         char_pty_req_t *char_pty;
831         int i;
832         bt_gatt_service_property_t svc_pty;
833
834         BT_CHECK_PARAMETER(service_handle, return);
835         BT_CHECK_PARAMETER(char_uuid, return);
836
837         BT_CHECK_ENABLED(return);
838
839         if (bluetooth_gatt_get_service_property(service_handle, &svc_pty) !=
840                                                         BLUETOOTH_ERROR_NONE) {
841                 BT_ERR("Invalid service");
842                 return BLUETOOTH_ERROR_NOT_FOUND;
843         }
844
845         char_handles = svc_pty.handle_info.handle;
846
847         if (char_handles == NULL)
848                 return __discover_char_from_uuid(svc_pty.handle, char_uuid);
849
850         char_pty = g_new0(char_pty_req_t, 1);
851
852         char_pty->handle = g_malloc0((svc_pty.handle_info.count + 1) *
853                                                         sizeof(char *));
854         for (i = 0; i < svc_pty.handle_info.count; i++) {
855                 char_pty->handle[i] = char_handles[i];
856                 BT_DBG("char_path[%d] : [%s]", i, char_pty->handle[i]);
857         }
858         char_pty->char_uuid = g_strdup(char_uuid);
859
860         g_idle_add(__filter_chars_with_uuid, char_pty);
861
862         return BLUETOOTH_ERROR_NONE;
863 }