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