--- /dev/null
+/*
+ * UWB Plug-in Logger
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * This file declares UWB dummy plugin logger functions and structures.
+ *
+ * @file uwb-plugin-dummy-private.h
+ * @author Jiung Yu (jiung.yu@samsung.com)
+ */
+
+#ifndef __UWB_PLUGIN_DUMMY_PRIVATE_H_
+#define __UWB_PLUGIN_DUMMY_PRIVATE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <dlog.h>
+#include <glib.h>
+#include <unistd.h>
+
+#undef LOG_TAG
+#define LOG_TAG "UWB_PLUGIN_DUMMY"
+
+#define UWB_PLUGIN_LOGV(format, args...) LOGV(format, ##args)
+#define UWB_PLUGIN_LOGD(format, args...) LOGD(format, ##args)
+#define UWB_PLUGIN_LOGI(format, args...) LOGI(format, ##args)
+#define UWB_PLUGIN_LOGW(format, args...) LOGW(format, ##args)
+#define UWB_PLUGIN_LOGE(format, args...) LOGE(format, ##args)
+#define UWB_PLUGIN_LOGF(format, args...) LOGF(format, ##args)
+
+#define __UWB_PLUGIN_LOG_FUNC_ENTER__ LOGD("Enter")
+#define __UWB_PLUGIN_LOG_FUNC_EXIT__ LOGD("Quit")
+
+#define UWB_PLUGIN_SECLOGI(format, args...) SECURE_LOG(LOG_INFO, LOG_TAG, format, ##args)
+#define UWB_PLUGIN_SECLOGD(format, args...) SECURE_LOG(LOG_DEBUG, LOG_TAG, format, ##args)
+
+#define ret_if(expr) do { \
+ if (expr) { \
+ UWB_PLUGIN_LOGE("(%s)", #expr); \
+ return; \
+ } \
+ } while (0)
+
+#define retv_if(expr, val) do { \
+ if (expr) { \
+ UWB_PLUGIN_LOGE("(%s)", #expr); \
+ return (val); \
+ } \
+ } while (0)
+
+typedef enum {
+ UWB_DUMMY_DATA_TYPE_INVALID = 0,
+ UWB_DUMMY_DATA_TYPE_SEND_MESSAGE,
+ UWB_DUMMY_DATA_TYPE_SET_POSITION,
+ UWB_DUMMY_DATA_TYPE_GET_NODE,
+ UWB_DUMMY_DATA_TYPE_MAX,
+} uwb_dwm1001_data_type_e;
+
+typedef enum {
+ UWB_DUMMY_DIRECTION_TYPE_INVALID = 0,
+ UWB_DUMMY_DIRECTION_TYPE_REQUEST,
+ UWB_DUMMY_DIRECTION_TYPE_RESPONSE,
+ UWB_DUMMY_DIRECTION_TYPE_MAX,
+} uwb_dwm1001_direction_type_e;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UWB_PLUGIN_DUMMY_PRIVATE_H_ */
--- /dev/null
+/*
+ * UWB Dummy Plug-in for ranging
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * This file implements UWB ranging plugin functions.
+ *
+ * @file uwb-plugin-dummy.c
+ * @author Jiung Yu (jiung.yu@samsung.com)
+ */
+#include <inttypes.h>
+
+#include "uwb-plugin-dummy.h"
+#include "uwb-plugin-dummy-private.h"
+
+/* dwm_api.h includes below */
+#ifndef _DWM_API_H_
+/**
+ * @brief Device modes
+ */
+typedef enum {
+ DWM_MODE_TAG = 0, //!< DWM_MODE_TAG
+ DWM_MODE_ANCHOR = 1//!< DWM_MODE_ANCHOR
+} dwm_mode_t;
+#endif //_DWM_API_H_
+/* dwm_api.h includes above */
+
+
+#define DBUS_DEBUG_VARIANT(var) \
+ do {\
+ gchar *var_debug_str = NULL;\
+ if (var)\
+ var_debug_str = g_variant_print((var), TRUE);\
+ UWB_PLUGIN_LOGI("value [%s]", var_debug_str ? var_debug_str : "NULL");\
+ g_free(var_debug_str);\
+ } while (0)
+
+#define MOCK_PLUGIN_DUMMY_PANID 0x1D1D
+#define MOCK_PLUGIN_DUMMY_NODEID 0x1D1D
+#define MOCK_PLUGIN_DUMMY_POS_X 0x1D1D
+#define MOCK_PLUGIN_DUMMY_POS_Y 0x1D1D
+#define MOCK_PLUGIN_DUMMY_POS_Z 0x1D1D
+#define MOCK_PLUGIN_DUMMY_DISTANCE 0x1D1D
+#define MOCK_PLUGIN_DUMMY_NETWORK_TIMEOUT 1500
+#define MOCK_PLUGIN_DUMMY_HARDWARE_WAIT_TIME 2000
+#define MOCK_PLUGIN_DUMMY_NODE_NUM 10
+
+static struct _dummy_ctx {
+ bool is_enable;
+ uint16_t pan_id;
+ uint64_t node_id;
+ uint16_t update_rate;
+ uint16_t stationary_update_rate;
+ int network_timeout;
+ int hardware_wait_time;
+ dwm_mode_t mode;
+ uwb_hpi_event_cbs_s *event_cbs;
+} dummy_ctx;
+
+static void __destroy_node(gpointer data)
+{
+ if (data != NULL) {
+ uwb_node_s *node = (uwb_node_s *)data;
+ free(node);
+ }
+}
+
+static void __clean_dummy_ctx()
+{
+ __UWB_PLUGIN_LOG_FUNC_ENTER__;
+
+ dummy_ctx.event_cbs = NULL;
+ dummy_ctx.is_enable = false;
+
+ __UWB_PLUGIN_LOG_FUNC_EXIT__;
+}
+
+static void __set_default_dummy_ctx()
+{
+ dummy_ctx.pan_id = MOCK_PLUGIN_DUMMY_PANID;
+ dummy_ctx.mode = DWM_MODE_ANCHOR;
+ dummy_ctx.update_rate = 1;
+ dummy_ctx.stationary_update_rate = 1;
+ dummy_ctx.network_timeout = MOCK_PLUGIN_DUMMY_NETWORK_TIMEOUT;
+ dummy_ctx.hardware_wait_time = MOCK_PLUGIN_DUMMY_HARDWARE_WAIT_TIME;
+}
+
+static int uwb_dummy_init(uwb_hpi_event_cbs_s *event_cbs)
+{
+ int ret = 0;
+
+ __UWB_PLUGIN_LOG_FUNC_ENTER__;
+
+ dummy_ctx.is_enable = false;
+ __set_default_dummy_ctx();
+ dummy_ctx.event_cbs = event_cbs;
+
+ __UWB_PLUGIN_LOG_FUNC_EXIT__;
+ return ret;
+}
+
+static int uwb_dummy_deinit(void)
+{
+ __UWB_PLUGIN_LOG_FUNC_ENTER__;
+
+ __clean_dummy_ctx();
+ dummy_ctx.is_enable = false;
+
+ __UWB_PLUGIN_LOG_FUNC_EXIT__;
+ return 0;
+}
+
+static int uwb_dummy_test(void)
+{
+ __UWB_PLUGIN_LOG_FUNC_ENTER__;
+
+ __UWB_PLUGIN_LOG_FUNC_EXIT__;
+ return 0;
+}
+
+static int uwb_dummy_reset(void)
+{
+ __UWB_PLUGIN_LOG_FUNC_ENTER__;
+
+ retv_if(!dummy_ctx.is_enable, -1);
+
+ g_usleep(dummy_ctx.hardware_wait_time * 1000);
+
+ __UWB_PLUGIN_LOG_FUNC_EXIT__;
+ return 0;
+}
+
+
+int uwb_dummy_factory_reset(void)
+{
+ __UWB_PLUGIN_LOG_FUNC_ENTER__;
+
+ retv_if(!dummy_ctx.is_enable, -1);
+
+ g_usleep(dummy_ctx.hardware_wait_time * 1000);
+
+ __UWB_PLUGIN_LOG_FUNC_EXIT__;
+ return 0;
+}
+
+int uwb_dummy_enable_network(void)
+{
+ __UWB_PLUGIN_LOG_FUNC_ENTER__;
+
+ retv_if(dummy_ctx.is_enable, -1);
+
+ dummy_ctx.node_id = MOCK_PLUGIN_DUMMY_NODEID;
+ dummy_ctx.is_enable = true;
+
+ __UWB_PLUGIN_LOG_FUNC_EXIT__;
+ return 0;
+}
+
+int uwb_dummy_disable_network(void)
+{
+ __UWB_PLUGIN_LOG_FUNC_ENTER__;
+
+ retv_if(!dummy_ctx.is_enable, -1);
+
+ __clean_dummy_ctx();
+ dummy_ctx.is_enable = false;
+
+ __UWB_PLUGIN_LOG_FUNC_EXIT__;
+ return 0;
+}
+
+int uwb_dummy_get_own_node(uwb_node_s **own_node)
+{
+ __UWB_PLUGIN_LOG_FUNC_ENTER__;
+
+ retv_if(own_node == NULL, -1);
+ retv_if(!dummy_ctx.is_enable, -1);
+
+ *own_node = (uwb_node_s *)malloc(sizeof(uwb_node_s));
+ if (*own_node == NULL) {
+ UWB_PLUGIN_LOGE("own_node is NULL");
+ __UWB_PLUGIN_LOG_FUNC_EXIT__;
+ return -1;
+ }
+
+ (*own_node)->distance = 0;
+ (*own_node)->is_remote = false;
+ (*own_node)->node_id = dummy_ctx.node_id;
+ (*own_node)->pan_id = dummy_ctx.pan_id;
+ if (dummy_ctx.mode == DWM_MODE_ANCHOR) {
+ (*own_node)->x = MOCK_PLUGIN_DUMMY_POS_X;
+ (*own_node)->y = MOCK_PLUGIN_DUMMY_POS_Y;
+ (*own_node)->z = MOCK_PLUGIN_DUMMY_POS_Z;
+ } else {
+ (*own_node)->x = 0;
+ (*own_node)->y = 0;
+ (*own_node)->z = 0;
+ }
+
+ UWB_PLUGIN_LOGI("obtained node_id : %" PRIu64, dummy_ctx.node_id);
+ UWB_PLUGIN_LOGI("X: %d Y: %d Z: %d", (*own_node)->x, (*own_node)->y, (*own_node)->z);
+ __UWB_PLUGIN_LOG_FUNC_EXIT__;
+
+ return 0;
+}
+
+static GSList *__get_anchor_list_anchor()
+{
+ GSList *node_list = NULL;
+
+ /* Insert Nodes to node list */
+ for (int i = 1; i <= MOCK_PLUGIN_DUMMY_NODE_NUM; ++i) {
+ uwb_node_s *node;
+
+ node = (uwb_node_s *)malloc(sizeof(uwb_node_s));
+ if (node == NULL) {
+ UWB_PLUGIN_LOGE("Alloc failed");
+ continue;
+ }
+ node->is_remote = true;
+ node->node_id = (uint64_t)(MOCK_PLUGIN_DUMMY_NODEID + i);
+ node->pan_id = dummy_ctx.pan_id;
+ node->x = MOCK_PLUGIN_DUMMY_POS_X + 1;
+ node->y = MOCK_PLUGIN_DUMMY_POS_Y + 1;
+ node->z = MOCK_PLUGIN_DUMMY_POS_Z + 1;
+ node->distance = 0;
+ node_list = g_slist_append(node_list, node);
+ }
+
+ return node_list;
+}
+
+static int test_node_x[] = {0, 0, 10, 0};
+static int test_node_y[] = {0, 10, 0, -10};
+
+static GSList *__get_anchor_list_tag()
+{
+ GSList *node_list = NULL;
+
+ for (int i = 1; i <= 3; ++i) {
+ uwb_node_s *node;
+ node = (uwb_node_s *)malloc(sizeof(uwb_node_s));
+ if (node == NULL) {
+ UWB_PLUGIN_LOGE("Alloc failed");
+ continue;
+ }
+
+ /*TODO: Should update valid position and distance */
+ node->distance = 10;
+ node->is_remote = true;
+ node->node_id = (uint64_t)(MOCK_PLUGIN_DUMMY_NODEID + i);
+ node->pan_id = dummy_ctx.pan_id;
+ node->x = test_node_x[i];
+ node->y = test_node_y[i];
+ node->z = 0;
+ node_list = g_slist_append(node_list, node);
+ }
+
+ return node_list;
+}
+
+int uwb_dummy_get_network_info(uwb_network_s **network_info)
+{
+ GSList *node_list = NULL;
+
+ __UWB_PLUGIN_LOG_FUNC_ENTER__;
+
+ retv_if(network_info == NULL, -1);
+ retv_if(!dummy_ctx.is_enable, -1);
+
+ /* Get Anchor list */
+ (dummy_ctx.mode == DWM_MODE_ANCHOR) ?
+ (node_list = __get_anchor_list_anchor()) :
+ (node_list = __get_anchor_list_tag());
+
+ *network_info = (uwb_network_s *)malloc(sizeof(uwb_network_s));
+ if (*network_info == NULL) {
+ UWB_PLUGIN_LOGE("network info is NULL");
+ g_slist_free_full(node_list, __destroy_node);
+ return -1;
+ }
+
+ (*network_info)->pan_id = dummy_ctx.pan_id;
+ (*network_info)->remote_node_list = node_list;
+ (*network_info)->remote_node_count = g_slist_length(node_list);
+
+ if ((*network_info)->remote_node_count == 0) {
+ UWB_PLUGIN_LOGE("No anchor in network");
+ }
+
+ __UWB_PLUGIN_LOG_FUNC_EXIT__;
+ return 0;
+}
+
+static void __set_dummy_ctx(GVariantIter *iter)
+{
+ const gchar *key = NULL;
+ GVariant *value = NULL;
+
+ if (!iter)
+ return;
+
+ while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
+ UWB_PLUGIN_LOGI("key : %s", key);
+ DBUS_DEBUG_VARIANT(value);
+ if (g_strcmp0(key, "MODE") == 0) {
+ const char *mode = NULL;
+ mode = g_variant_get_string(value, NULL);
+ if (strncmp(mode, "ANCHOR", strlen(mode)) == 0)
+ dummy_ctx.mode = DWM_MODE_ANCHOR;
+ else if (strncmp(mode, "TAG", strlen(mode)) == 0)
+ dummy_ctx.mode = DWM_MODE_TAG;
+
+ }
+
+ else if (g_strcmp0(key, "UPDATE_RATE") == 0)
+ dummy_ctx.update_rate = (int)g_variant_get_int64(value);
+ else if (g_strcmp0(key, "NETWORK_TIMEOUT") == 0)
+ dummy_ctx.network_timeout = (int)g_variant_get_int64(value);
+ else if (g_strcmp0(key, "HARDWARE_WAIT_TIME") == 0)
+ dummy_ctx.hardware_wait_time = (int)g_variant_get_int64(value);
+ else if (g_strcmp0(key, "PANID") == 0)
+ dummy_ctx.pan_id = (uint16_t)g_variant_get_int64(value);
+ }
+ UWB_PLUGIN_LOGE("pan_id : %d", (int)dummy_ctx.pan_id);
+ UWB_PLUGIN_LOGE("hardware_wait_time : %d", dummy_ctx.hardware_wait_time);
+ UWB_PLUGIN_LOGE("network_timeout : %d", dummy_ctx.network_timeout);
+}
+
+int uwb_dummy_set_configurations(uint16_t node_id, const GVariant *configurations)
+{
+ GVariantIter *iter = NULL;
+ __UWB_PLUGIN_LOG_FUNC_ENTER__;
+
+ retv_if(dummy_ctx.is_enable, -1);
+
+ g_variant_get((GVariant *)configurations, "a{sv}", &iter);
+
+ __set_dummy_ctx(iter);
+
+ g_variant_iter_free(iter);
+
+ __UWB_PLUGIN_LOG_FUNC_EXIT__;
+ return 0;
+}
+
+static void __build_configuration(GVariantBuilder *builder)
+{
+ if (!builder)
+ return;
+
+ if (dummy_ctx.mode == DWM_MODE_ANCHOR)
+ g_variant_builder_add(builder, "{sv}", "MODE", g_variant_new("s", "ANCHOR"));
+ else
+ g_variant_builder_add(builder, "{sv}", "MODE", g_variant_new("s", "TAG"));
+ UWB_PLUGIN_LOGE("network_timeout : %d", dummy_ctx.network_timeout);
+ g_variant_builder_add(builder, "{sv}", "NETWORK_TIMEOUT", g_variant_new("x", (int64_t)dummy_ctx.network_timeout));
+ g_variant_builder_add(builder, "{sv}", "HARDWARE_WAIT_TIME", g_variant_new("x", (int64_t)dummy_ctx.hardware_wait_time));
+ g_variant_builder_add(builder, "{sv}", "PANID", g_variant_new("x", (int64_t)dummy_ctx.pan_id));
+}
+
+int uwb_dummy_get_configurations(uint16_t node_id, GVariant **configurations)
+{
+ GVariantBuilder *builder;
+
+ __UWB_PLUGIN_LOG_FUNC_ENTER__;
+
+ builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+ __build_configuration(builder);
+ *configurations = g_variant_new("a{sv}", builder);
+
+ g_variant_builder_unref(builder);
+
+ __UWB_PLUGIN_LOG_FUNC_EXIT__;
+ return 0;
+}
+
+int uwb_dummy_set_position(uint64_t node_id, int x, int y, int z)
+{
+ __UWB_PLUGIN_LOG_FUNC_ENTER__;
+
+ retv_if(node_id == 0, -1);
+ retv_if(!dummy_ctx.is_enable, -1);
+
+ if (node_id != dummy_ctx.node_id) {
+ UWB_PLUGIN_LOGE("Invalid node ID");
+ return -1;
+
+ }
+
+ if (dummy_ctx.mode == DWM_MODE_TAG) {
+ UWB_PLUGIN_LOGE("Tag mode is not support set position");
+ return -1;
+ }
+
+ __UWB_PLUGIN_LOG_FUNC_EXIT__;
+ return 0;
+}
+
+int uwb_plugin_load(uwb_hpi_ops_s *ops)
+{
+ __UWB_PLUGIN_LOG_FUNC_ENTER__;
+
+ if (!ops) {
+ UWB_PLUGIN_LOGE("Invalid parameter");
+ __UWB_PLUGIN_LOG_FUNC_EXIT__;
+ return -1;
+ }
+
+ ops->init = uwb_dummy_init;
+ ops->deinit = uwb_dummy_deinit;
+ ops->test = uwb_dummy_test;
+ ops->reset = uwb_dummy_reset;
+ ops->factory_reset = uwb_dummy_factory_reset;
+ ops->enable_network = uwb_dummy_enable_network;
+ ops->disable_network = uwb_dummy_disable_network;
+ ops->get_own_node = uwb_dummy_get_own_node;
+ ops->get_network_info = uwb_dummy_get_network_info;
+ ops->set_configurations = uwb_dummy_set_configurations;
+ ops->get_configurations = uwb_dummy_get_configurations;
+ ops->set_position = uwb_dummy_set_position;
+ ops->send_message = NULL;
+ ops->send_message_to = NULL;
+ dummy_ctx.is_enable = false;
+
+ __UWB_PLUGIN_LOG_FUNC_EXIT__;
+ return 0;
+}