1be4838e83dabe541aef90902f06511f27acf6db
[platform/core/api/uwb.git] / src / uwb.c
1 /*
2  * Copyright (c) 2020 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 <stdio.h>
19 #include <unistd.h>
20 #include <stdlib.h>
21
22 #include <dlog.h>
23 #include <uwb.h>
24 #include <uwb-log.h>
25 #include <uwb-private.h>
26 #include <uwb-gdbus.h>
27 #include <uwb-util.h>
28 #include <inttypes.h>
29
30 #define UWB_DBUS_SERVICE "org.tizen.uwb"               /**< For uwb dbus */
31 #define UWB_DBUS_MANAGER_PATH "/org/tizen/uwb/manager"     /**< For manager dbus */
32
33
34 static struct _uwb_ctx {
35         Manager *manager_proxy;
36         uwb_message_received_cb message_received_cb;
37         void *message_received_user_data;
38         uwb_position_changed_cb position_changed_cb;
39         void *position_changed_user_data;
40         uwb_get_network_finished_cb get_network_finished_cb;
41         uwb_network_foreach_remote_node_cb foreach_remote_node_cb;
42 } uwb_ctx = {NULL,};
43
44 static inline void __handle_error(GError *error, int *ret)
45 {
46     if (!error)
47         return;
48
49     if (NULL == g_strrstr(error->message, "org.tizen.uwb.Error")) {
50                  if (NULL != g_strrstr(error->message, ".AccessDenied")) {
51                                         _DBG("Client doesn't have nmdaemon privilege");
52                                         *ret = UWB_ERROR_PERMISSION_DENIED;
53                  } else {
54                                         _DBG("DBus failure");
55                                         *ret = UWB_ERROR_OPERATION_FAILED;
56                  }
57     } else {
58         if (NULL != g_strrstr(error->message, ".NotPermitted")) {
59             _DBG("Client doesn't have uwb daemon privilege");
60             *ret = UWB_ERROR_PERMISSION_DENIED;
61         } else if (NULL != g_strrstr(error->message, ".InvalidParameter")) {
62                                 _DBG("Invalid Parameter");
63             *ret = UWB_ERROR_INVALID_PARAMETER;
64         } else if (NULL != g_strrstr(error->message, ".OutOfMemory")) {
65                         _DBG("Out of memory");
66             *ret = UWB_ERROR_OUT_OF_MEMORY;
67         } else {
68             _DBG("Operation Failed");
69             *ret = UWB_ERROR_OPERATION_FAILED;
70         }
71     }
72     g_error_free(error);
73 }
74
75 static void __message_received(GObject *source_object,
76         guint16 node_id, GVariant *message, gint message_length)
77 {
78         GVariantIter *iter;
79         unsigned char element;
80         unsigned char *buf = NULL;
81         int size = 0;
82
83         g_variant_get(message, "a(y)", &iter);
84         size = g_variant_iter_n_children(iter);
85
86         buf = (unsigned char *)malloc(sizeof(unsigned char) * size + 1);
87         for (int i = 0; g_variant_iter_loop(iter, "(y)", &element); i++)
88         {
89                 buf[i] = element;
90         }
91         buf[size] = '\0';
92
93         g_variant_iter_free(iter);
94
95         if (uwb_ctx.message_received_cb != NULL) {
96                 uwb_ctx.message_received_cb(node_id, buf, message_length,
97                         uwb_ctx.message_received_user_data);
98         }
99
100         free(buf);
101 }
102
103 static void __position_changed(GObject *source_object,
104                 guint16 node_id, gint x, gint y, gint z)
105 {
106         if (uwb_ctx.position_changed_cb != NULL)
107                 uwb_ctx.position_changed_cb(node_id, x, y, z, uwb_ctx.position_changed_user_data);
108 }
109
110 static int manager_proxy_init(void)
111 {
112         GError *error = NULL;
113
114         uwb_ctx.manager_proxy = manager_proxy_new_for_bus_sync(
115             G_BUS_TYPE_SYSTEM,
116             G_DBUS_PROXY_FLAGS_NONE,
117             UWB_DBUS_SERVICE,
118             UWB_DBUS_MANAGER_PATH,
119             NULL,
120             &error);
121         if (NULL == uwb_ctx.manager_proxy) {
122                 /* LCOV_EXCL_START */
123                 if (error != NULL) {
124                         _ERR("Failed to connect to the D-BUS daemon [%s]", error->message);
125                         g_error_free(error);
126                 }
127                 return UWB_ERROR_IO_ERROR;
128                 /* LCOV_EXCL_STOP */
129         }
130
131         g_signal_connect(uwb_ctx.manager_proxy, "message-received",
132                           G_CALLBACK(__message_received), NULL);
133
134         g_signal_connect(uwb_ctx.manager_proxy, "position-changed",
135                           G_CALLBACK(__position_changed), NULL);
136
137         return UWB_ERROR_NONE;
138 }
139
140 static void manager_proxy_deinit(void)
141 {
142         g_object_unref(uwb_ctx.manager_proxy);
143         uwb_ctx.manager_proxy = NULL;
144 }
145
146 EXPORT_API int uwb_initialize(void)
147 {
148         int ret = UWB_ERROR_NONE;
149
150         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
151         CHECK_ALREADY_INITIALIZED();
152
153         _BEGIN();
154
155         ret = manager_proxy_init();
156
157         _END();
158
159         return ret;
160 }
161
162 EXPORT_API int uwb_deinitialize(void)
163 {
164         int ret = UWB_ERROR_NONE;
165
166         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
167         CHECK_NOT_INITIALIZED();
168
169         _BEGIN();
170
171         manager_proxy_deinit();
172
173         _END();
174
175         return ret;
176 }
177
178 EXPORT_API int uwb_reset(void)
179 {
180         int ret = UWB_ERROR_NONE;
181         GError *error = NULL;
182
183         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
184         CHECK_NOT_INITIALIZED();
185
186         _BEGIN();
187
188         if (manager_call_reset_sync(uwb_ctx.manager_proxy, NULL, &error) == FALSE) {
189                 _ERR("manager_call_reset_sync failed : %s", error->message);
190                 __handle_error(error, &ret);
191         }
192
193         _END();
194
195         return ret;
196 }
197
198 EXPORT_API int uwb_factory_reset(void)
199 {
200         int ret = UWB_ERROR_NONE;
201         GError *error = NULL;
202
203         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
204         CHECK_NOT_INITIALIZED();
205
206         _BEGIN();
207
208         if (manager_call_factory_reset_sync(uwb_ctx.manager_proxy, NULL, &error) == FALSE) {
209                 _ERR("manager_call_factory_reset_sync failed : %s", error->message);
210                 __handle_error(error, &ret);
211         }
212
213         _END();
214
215         return ret;
216 }
217
218 EXPORT_API int uwb_set_message_received_cb(uwb_message_received_cb message_received_cb, void *user_data)
219 {
220         int ret = UWB_ERROR_NONE;
221
222         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
223
224         _BEGIN();
225
226         uwb_ctx.message_received_cb = message_received_cb;
227         uwb_ctx.message_received_user_data = user_data;
228
229         _END();
230
231         return ret;
232 }
233
234 EXPORT_API int uwb_set_position_changed_cb(uwb_position_changed_cb position_changed_cb, void *user_data)
235 {
236         int ret = UWB_ERROR_NONE;
237
238         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
239
240         _BEGIN();
241
242         uwb_ctx.position_changed_cb = position_changed_cb;
243         uwb_ctx.position_changed_user_data = user_data;
244
245         _END();
246
247         return ret;
248 }
249
250 EXPORT_API int uwb_unset_message_received_cb(void)
251 {
252         int ret = UWB_ERROR_NONE;
253
254         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
255
256         _BEGIN();
257
258         uwb_ctx.message_received_cb = NULL;
259         uwb_ctx.message_received_user_data = NULL;
260
261         _END();
262
263         return ret;
264 }
265
266 EXPORT_API int uwb_unset_position_changed_cb(void)
267 {
268         int ret = UWB_ERROR_NONE;
269
270         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
271
272         _BEGIN();
273
274         uwb_ctx.position_changed_cb = NULL;
275         uwb_ctx.position_changed_user_data = NULL;
276
277         _END();
278
279         return ret;
280 }
281
282 EXPORT_API int uwb_get_own_node(uwb_node_h *own_node)
283 {
284         int ret = UWB_ERROR_NONE;
285         GError *error = NULL;
286         GVariant *own_node_va = NULL;
287         uwb_node_s **_own_node = (uwb_node_s **)own_node;
288
289         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
290         CHECK_NOT_INITIALIZED();
291
292         _BEGIN();
293
294         uwb_check_null_ret_error("own_node", own_node, UWB_ERROR_INVALID_PARAMETER);
295
296         if (manager_call_get_own_node_sync(uwb_ctx.manager_proxy,
297                 &own_node_va, NULL, &error) == FALSE) {
298                 __handle_error(error, &ret);
299         }
300
301         if (ret == UWB_ERROR_NONE && own_node_va != NULL)
302                 *_own_node = uwb_util_get_node_from_variant(own_node_va);
303         else
304                 *_own_node = NULL;
305
306         _END();
307
308         return ret;
309 }
310
311 static void __network_get_cb(GObject *source_object, GAsyncResult *res, gpointer user_data)
312 {
313         int ret = UWB_ERROR_NONE;
314         uint16_t pan_id = 0;
315         GVariant *remote_node_list_va = NULL;
316         GError *error = NULL;
317         uwb_network_s *network_s;
318
319         if (manager_call_get_network_info_finish(
320                         MANAGER(source_object),
321                         &pan_id,
322                         &remote_node_list_va,
323                         res,
324                         &error) == FALSE) {
325                         _ERR("manager_call_get_network_info_finish failed : %s", error->message);
326                         __handle_error(error, &ret);
327
328                         if (uwb_ctx.get_network_finished_cb != NULL) {
329                                 uwb_ctx.get_network_finished_cb(ret, NULL, user_data);
330                         }
331
332                         return;
333         }
334
335         /* create network handle */
336         network_s = (uwb_network_s *)malloc(sizeof(uwb_network_s));
337
338         if (ret == UWB_ERROR_NONE) {
339                 GSList *remote_node_list = NULL;
340                 network_s->pan_id = pan_id;
341                 network_s->remote_node_count = g_variant_n_children(remote_node_list_va);
342
343                 if (network_s->remote_node_count > 0) {
344                         GVariantIter *iter = NULL;
345                         GVariant *nodes_va = NULL;
346
347                         g_variant_get(remote_node_list_va, "aa{sv}", &iter);
348                         while ((nodes_va = g_variant_iter_next_value(iter)) != NULL) {
349                                 uwb_node_s *node;
350
351                                 node = uwb_util_get_node_from_variant(nodes_va);
352                                 node->is_remote = true;
353
354                                 _DBG("(%d, %d, %d)", node->x, node->y, node->z);
355                                 remote_node_list = g_slist_append(remote_node_list, node);
356                         }
357                         g_variant_iter_free(iter);
358                 }
359                 network_s->remote_node_list = remote_node_list;
360
361                 g_variant_unref(remote_node_list_va);
362         }
363
364         if (uwb_ctx.get_network_finished_cb != NULL) {
365                 uwb_ctx.get_network_finished_cb(ret, (uwb_network_h)network_s, user_data);
366         }
367 }
368
369 EXPORT_API int uwb_network_get(uwb_get_network_finished_cb finished_cb, void *user_data)
370 {
371         int ret = UWB_ERROR_NONE;
372
373         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
374         CHECK_NOT_INITIALIZED();
375
376         _BEGIN();
377
378         uwb_check_null_ret_error("finished_cb", finished_cb, UWB_ERROR_INVALID_PARAMETER);
379
380         uwb_ctx.get_network_finished_cb = finished_cb;
381
382         manager_call_get_network_info(uwb_ctx.manager_proxy, NULL, __network_get_cb, user_data);
383
384         _END();
385
386         return ret;
387 }
388
389
390 static gpointer __copy_node(gconstpointer src, gpointer data)
391 {
392         if (!src)
393                 return NULL;
394
395         uwb_node_s *src_ptr = (uwb_node_s *)src;
396         uwb_node_s *dst_ptr = (uwb_node_s *)malloc(sizeof(uwb_node_s));
397         if (!dst_ptr)
398                 return NULL;
399
400         dst_ptr->node_id = src_ptr->node_id;
401         dst_ptr->pan_id = src_ptr->pan_id;
402         dst_ptr->is_remote = src_ptr->is_remote;
403         dst_ptr->distance = src_ptr->distance;
404         dst_ptr->x = src_ptr->x;
405         dst_ptr->y = src_ptr->y;
406         dst_ptr->z = src_ptr->z;
407
408         return (gpointer)dst_ptr;
409 }
410
411 EXPORT_API int uwb_network_clone(uwb_network_h source, uwb_network_h *target)
412 {
413         uwb_network_s *result_network = NULL;
414         uwb_network_s *src_network = (uwb_network_s *)source;
415         GSList *remote_node_list = NULL;
416         int ret = UWB_ERROR_NONE;
417
418         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
419
420         _BEGIN();
421
422         uwb_check_null_ret_error("source", source, UWB_ERROR_INVALID_PARAMETER);
423
424         result_network = (uwb_network_s *)malloc(sizeof(uwb_network_s));
425         if (result_network == NULL) {
426                 _ERR("malloc failed");
427                 return UWB_ERROR_OPERATION_FAILED;
428         }
429
430         result_network->pan_id = src_network->pan_id;
431         result_network->remote_node_count = src_network->remote_node_count;
432         remote_node_list = src_network->remote_node_list;
433         result_network->remote_node_list = g_slist_copy_deep(remote_node_list,
434                         __copy_node,
435                         NULL);
436
437         _END();
438
439         *target = result_network;
440         return ret;
441 }
442
443 EXPORT_API int uwb_network_destroy(uwb_network_h network)
444 {
445         int ret = UWB_ERROR_NONE;
446
447         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
448
449         _BEGIN();
450
451         uwb_check_null_ret_error("network", network, UWB_ERROR_INVALID_PARAMETER);
452
453         uwb_util_destroy_network(network);
454
455         _END();
456
457         return ret;
458 }
459
460 EXPORT_API int uwb_network_get_pan_id(uwb_network_h network, uint64_t *pan_id)
461 {
462         int ret = UWB_ERROR_NONE;
463
464         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
465
466         _BEGIN();
467
468         uwb_check_null_ret_error("network", network, UWB_ERROR_INVALID_PARAMETER);
469         uwb_check_null_ret_error("pan_id", pan_id, UWB_ERROR_INVALID_PARAMETER);
470
471         *pan_id = ((uwb_network_s *)network)->pan_id;
472
473         _END();
474
475         return ret;
476 }
477
478 EXPORT_API int uwb_network_get_remote_node_count(uwb_network_h network, int *remote_node_count)
479 {
480         int ret = UWB_ERROR_NONE;
481
482         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
483
484         _BEGIN();
485
486         uwb_check_null_ret_error("network", network, UWB_ERROR_INVALID_PARAMETER);
487         uwb_check_null_ret_error("remote_node_count", remote_node_count, UWB_ERROR_INVALID_PARAMETER);
488
489         *remote_node_count = ((uwb_network_s *)network)->remote_node_count;
490
491         _END();
492
493         return ret;
494 }
495
496 static void __foreach_node(gpointer data, gpointer user_data)
497 {
498         uwb_node_s *node = (uwb_node_s *)data;
499         _DBG("panid : 0x%X, nodeid : 0x%04"PRIX64", distance : %"PRId64"", node->pan_id, node->node_id, node->distance);
500
501         if (uwb_ctx.foreach_remote_node_cb != NULL)
502                 uwb_ctx.foreach_remote_node_cb((uwb_node_h)node, user_data);
503 }
504
505 EXPORT_API int uwb_network_foreach_remote_node(uwb_network_h network,
506         uwb_network_foreach_remote_node_cb node_cb, void *user_data)
507 {
508         int ret = UWB_ERROR_NONE;
509
510         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
511
512         _BEGIN();
513
514         uwb_check_null_ret_error("network", network, UWB_ERROR_INVALID_PARAMETER);
515
516         uwb_network_s *network_s = (uwb_network_s *)network;
517         if (network_s->remote_node_count == 0) {
518                 _DBG("remote_node_count  is 0");
519                 return ret;
520         }
521
522         uwb_ctx.foreach_remote_node_cb = node_cb;
523         g_slist_foreach(network_s->remote_node_list, __foreach_node, user_data);
524
525         _END();
526
527         return ret;
528 }
529
530 EXPORT_API int uwb_node_clone(uwb_node_h src, uwb_node_h *dst)
531 {
532         int ret = UWB_ERROR_NONE;
533
534         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
535
536         _BEGIN();
537
538         uwb_check_null_ret_error("source", src, UWB_ERROR_INVALID_PARAMETER);
539         uwb_check_null_ret_error("target", dst, UWB_ERROR_INVALID_PARAMETER);
540
541         uwb_node_s *_src = (uwb_node_s *)src;
542         *dst = (uwb_node_s *)malloc(sizeof(uwb_node_s));
543         uwb_node_s *_dst = *dst;
544
545         _dst->node_id = _src->node_id;
546         _dst->pan_id = _src->pan_id;
547         _dst->is_remote = _src->is_remote;
548         _dst->distance = _src->distance;
549         _dst->x = _src->x;
550         _dst->y = _src->y;
551         _dst->z = _src->z;
552
553         _END();
554
555         return ret;
556 }
557
558 EXPORT_API int uwb_node_destroy(uwb_node_h node)
559 {
560         int ret = UWB_ERROR_NONE;
561
562         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
563
564         _BEGIN();
565
566         uwb_check_null_ret_error("node", node, UWB_ERROR_INVALID_PARAMETER);
567
568         free(node);
569
570         _END();
571
572         return ret;
573 }
574
575 EXPORT_API int uwb_node_get_distance(uwb_node_h node, uint64_t *distance)
576 {
577         int ret = UWB_ERROR_NONE;
578
579         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
580
581         _BEGIN();
582
583         uwb_check_null_ret_error("node", node, UWB_ERROR_INVALID_PARAMETER);
584         uwb_check_null_ret_error("distance", distance, UWB_ERROR_INVALID_PARAMETER);
585
586         *distance = ((uwb_node_s *)node)->distance;
587
588         _END();
589
590         return ret;
591 }
592
593 EXPORT_API int uwb_node_get_node_id(uwb_node_h node, uint64_t *node_id)
594 {
595         int ret = UWB_ERROR_NONE;
596
597         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
598
599         _BEGIN();
600
601         uwb_check_null_ret_error("node", node, UWB_ERROR_INVALID_PARAMETER);
602         uwb_check_null_ret_error("node_id", node_id, UWB_ERROR_INVALID_PARAMETER);
603
604         *node_id = ((uwb_node_s *)node)->node_id;
605
606         _END();
607
608         return ret;
609 }
610
611 EXPORT_API int uwb_node_get_pan_id(uwb_node_h node, uint64_t *pan_id)
612 {
613         int ret = UWB_ERROR_NONE;
614
615         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
616
617         _BEGIN();
618
619         uwb_check_null_ret_error("node", node, UWB_ERROR_INVALID_PARAMETER);
620         uwb_check_null_ret_error("pan_id", pan_id, UWB_ERROR_INVALID_PARAMETER);
621
622         *pan_id = ((uwb_node_s *)node)->pan_id;
623
624         _END();
625
626         return ret;
627 }
628
629 EXPORT_API int uwb_node_get_is_remote(uwb_node_h node, bool *is_remote)
630 {
631         int ret = UWB_ERROR_NONE;
632
633         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
634
635         _BEGIN();
636
637         uwb_check_null_ret_error("node", node, UWB_ERROR_INVALID_PARAMETER);
638         uwb_check_null_ret_error("is_remote", is_remote, UWB_ERROR_INVALID_PARAMETER);
639
640         *is_remote = ((uwb_node_s *)node)->is_remote;
641
642         _END();
643
644         return ret;
645 }
646
647 EXPORT_API int uwb_node_get_position(uwb_node_h node, int *x, int *y, int *z)
648 {
649         int ret = UWB_ERROR_NONE;
650
651         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
652
653         _BEGIN();
654
655         uwb_check_null_ret_error("node", node, UWB_ERROR_INVALID_PARAMETER);
656         uwb_check_null_ret_error("x", x, UWB_ERROR_INVALID_PARAMETER);
657         uwb_check_null_ret_error("y", y, UWB_ERROR_INVALID_PARAMETER);
658         uwb_check_null_ret_error("z", z, UWB_ERROR_INVALID_PARAMETER);
659
660         *x = ((uwb_node_s *)node)->x;
661         *y = ((uwb_node_s *)node)->y;
662         *z = ((uwb_node_s *)node)->z;
663
664         _END();
665
666         return ret;
667 }
668
669 EXPORT_API int uwb_node_set_position(uwb_node_h node, int x, int y, int z)
670 {
671         int ret = UWB_ERROR_NONE;
672         GError *error = NULL;
673
674         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
675         CHECK_NOT_INITIALIZED();
676
677         _BEGIN();
678
679         uwb_check_null_ret_error("node", node, UWB_ERROR_INVALID_PARAMETER);
680
681         if (manager_call_set_position_sync(uwb_ctx.manager_proxy,
682                 ((uwb_node_s *)node)->node_id, x, y, z, NULL, &error) == FALSE) {
683                 _ERR("manager_call_set_position_sync failed : %s", error->message);
684                 __handle_error(error, &ret);
685         }
686
687         _END();
688
689         return ret;
690 }
691
692 static GVariant *__data_to_variant(const unsigned char *data, int length)
693 {
694         GVariantBuilder builder;
695
696         g_variant_builder_init(&builder, G_VARIANT_TYPE("a(y)"));
697
698         if (data && length > 0)
699         {
700                 for(int i = 0; i < length; i++)
701                         g_variant_builder_add(&builder, "(y)", *(data + i));
702         }
703
704         return g_variant_builder_end(&builder);
705 }
706
707 EXPORT_API int uwb_node_send_message(const unsigned char *message, int len)
708 {
709         int ret = UWB_ERROR_NONE;
710         GVariant *msg = NULL;
711         GError *error = NULL;
712
713         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
714         CHECK_NOT_INITIALIZED();
715
716         _BEGIN();
717
718         uwb_check_null_ret_error("message", message, UWB_ERROR_INVALID_PARAMETER);
719         cond_expr_ret(len <= 0, UWB_ERROR_INVALID_PARAMETER);
720
721         msg = __data_to_variant(message, len);
722
723         if (manager_call_send_message_sync(uwb_ctx.manager_proxy,
724                 msg, len, NULL, &error) == FALSE) {
725                 _ERR("manager_call_send_message_sync failed : %s", error->message);
726                 __handle_error(error, &ret);
727         }
728
729         _END();
730
731         return ret;
732 }
733
734 EXPORT_API int uwb_node_send_message_to(uwb_node_h node, const unsigned char *message, int len)
735 {
736         int ret = UWB_ERROR_NONE;
737         GVariant *msg = NULL;
738         GError *error = NULL;
739
740         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
741         CHECK_NOT_INITIALIZED();
742
743         _BEGIN();
744
745         uwb_check_null_ret_error("node", node, UWB_ERROR_INVALID_PARAMETER);
746         uwb_check_null_ret_error("message", message, UWB_ERROR_INVALID_PARAMETER);
747         cond_expr_ret(len <= 0, UWB_ERROR_INVALID_PARAMETER);
748
749         msg = __data_to_variant(message, len);
750
751         if (manager_call_send_message_to_sync(uwb_ctx.manager_proxy, ((uwb_node_s *)node)->node_id,
752                 msg, len, NULL, &error) == FALSE) {
753                 _ERR("manager_call_send_message_to_sync failed : %s", error->message);
754                 __handle_error(error, &ret);
755         }
756
757         _END();
758
759         return ret;
760 }
761
762 static int __get_configurations(uwb_node_h node, char *key,
763         const GVariantType *va_type, GVariant **va_out)
764 {
765         int ret = UWB_ERROR_NONE;
766         GError *error = NULL;
767         GVariant *va = NULL;
768
769         if (manager_call_get_configurations_sync(uwb_ctx.manager_proxy,
770                 ((uwb_node_s *)node)->node_id, &va, NULL, &error) == FALSE) {
771                 _ERR("__get_configurations failed : %s", error->message);
772                 __handle_error(error, &ret);
773         } else {
774                 *va_out = g_variant_lookup_value(va, key, va_type);
775         }
776
777         return ret;
778 }
779
780 EXPORT_API int uwb_node_get_configuration_int32(uwb_node_h node, char *key, int32_t *value)
781 {
782         int ret = UWB_ERROR_NONE;
783         GVariant *value_va = NULL;
784
785         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
786         CHECK_NOT_INITIALIZED();
787
788         _BEGIN();
789
790         uwb_check_null_ret_error("node", node, UWB_ERROR_INVALID_PARAMETER);
791
792         ret = __get_configurations(node, key, G_VARIANT_TYPE_INT32, &value_va);
793
794         if (value_va != NULL)
795                 *value = g_variant_get_int32(value_va);
796         else
797                 *value = 0;
798
799         _END();
800
801         return ret;
802 }
803
804 EXPORT_API int uwb_node_get_configuration_int64(uwb_node_h node, char *key, int64_t *value)
805 {
806         int ret = UWB_ERROR_NONE;
807         GVariant *value_va = NULL;
808
809         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
810         CHECK_NOT_INITIALIZED();
811
812         _BEGIN();
813
814         uwb_check_null_ret_error("node", node, UWB_ERROR_INVALID_PARAMETER);
815
816         ret = __get_configurations(node, key, G_VARIANT_TYPE_INT64, &value_va);
817
818         if (value_va != NULL)
819                 *value = g_variant_get_int64(value_va);
820         else
821                 *value = 0;
822
823         _END();
824
825         return ret;
826 }
827
828 EXPORT_API int uwb_node_get_configuration_string(uwb_node_h node, char *key, const char **value)
829 {
830         int ret = UWB_ERROR_NONE;
831         GVariant *value_va = NULL;
832
833         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
834         CHECK_NOT_INITIALIZED();
835
836         _BEGIN();
837
838         uwb_check_null_ret_error("node", node, UWB_ERROR_INVALID_PARAMETER);
839
840         ret = __get_configurations(node, key, G_VARIANT_TYPE_STRING, &value_va);
841
842         if (value_va != NULL)
843                 *value = g_variant_get_string(value_va, NULL);
844         else
845                 *value = 0;
846
847         _END();
848
849         return ret;
850 }
851
852 static int __set_configuration(uwb_node_h node, char *key, GVariant *va)
853 {
854         int ret = UWB_ERROR_NONE;
855         GError *error = NULL;
856
857         if (manager_call_set_configurations_sync(uwb_ctx.manager_proxy, ((uwb_node_s *)node)->node_id,
858                 va, NULL, &error) == FALSE) {
859                 _ERR("__set_configurations : %s", error->message);
860                 __handle_error(error, &ret);
861         }
862
863         return ret;
864 }
865
866 static GVariant *__build_configuration(char *key, GVariant *value)
867 {
868         GVariant *va = NULL;
869         GVariantBuilder *builder;
870
871         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
872         g_variant_builder_open(builder, G_VARIANT_TYPE_VARDICT);
873         g_variant_builder_add(builder, "{sv}", key, value);
874         g_variant_builder_close(builder);
875         va = g_variant_builder_end(builder);
876         g_variant_builder_unref(builder);
877
878         return va;
879 }
880
881 EXPORT_API int uwb_node_set_configuration_int32(uwb_node_h node, char *key, int32_t value)
882 {
883         int ret = UWB_ERROR_NONE;
884         GVariant *configuration = NULL;
885
886         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
887         CHECK_NOT_INITIALIZED();
888
889         _BEGIN();
890
891         uwb_check_null_ret_error("node", node, UWB_ERROR_INVALID_PARAMETER);
892
893         configuration = __build_configuration(key, g_variant_new_int32(value));
894
895         ret = __set_configuration(node, key, configuration);
896
897         _END();
898
899         return ret;
900 }
901
902 EXPORT_API int uwb_node_set_configuration_int64(uwb_node_h node, char *key, int64_t value)
903 {
904         int ret = UWB_ERROR_NONE;
905         GVariant *configuration = NULL;
906
907         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
908         CHECK_NOT_INITIALIZED();
909
910         _BEGIN();
911
912         uwb_check_null_ret_error("node", node, UWB_ERROR_INVALID_PARAMETER);
913
914         configuration = __build_configuration(key, g_variant_new_int64(value));
915
916         ret = __set_configuration(node, key, configuration);
917
918         _END();
919
920         return ret;
921 }
922
923 EXPORT_API int uwb_node_set_configuration_string(uwb_node_h node, char *key, const char *value)
924 {
925         int ret = UWB_ERROR_NONE;
926         GVariant *configuration = NULL;
927
928         CHECK_FEATURE_SUPPORTED(UWB_FEATURE);
929         CHECK_NOT_INITIALIZED();
930
931         _BEGIN();
932
933         uwb_check_null_ret_error("node", node, UWB_ERROR_INVALID_PARAMETER);
934
935         configuration = __build_configuration(key, g_variant_new_string(value));
936
937         ret = __set_configuration(node, key, configuration);
938
939         _END();
940
941         return ret;
942 }
943