From 3483a7286dfd6b7c306c1bd82b850bc95466631e Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Tue, 13 Oct 2020 18:18:33 +0100 Subject: [PATCH] d/remote: Add remote driver --- CMakeLists.txt | 5 +- src/xrt/drivers/CMakeLists.txt | 14 ++ src/xrt/drivers/remote/r_device.c | 195 ++++++++++++++++ src/xrt/drivers/remote/r_hmd.c | 180 +++++++++++++++ src/xrt/drivers/remote/r_hub.c | 318 ++++++++++++++++++++++++++ src/xrt/drivers/remote/r_interface.h | 115 ++++++++++ src/xrt/drivers/remote/r_internal.h | 91 ++++++++ src/xrt/targets/common/CMakeLists.txt | 4 + 8 files changed, 920 insertions(+), 2 deletions(-) create mode 100644 src/xrt/drivers/remote/r_device.c create mode 100644 src/xrt/drivers/remote/r_hmd.c create mode 100644 src/xrt/drivers/remote/r_hub.c create mode 100644 src/xrt/drivers/remote/r_interface.h create mode 100644 src/xrt/drivers/remote/r_internal.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 563d780d2..bb19f3e21 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,8 +148,8 @@ cmake_dependent_option(XRT_BUILD_DRIVER_OHMD "Enable OpenHMD driver" ON "OPENHMD cmake_dependent_option(XRT_BUILD_DRIVER_DAYDREAM "Enable the Google Daydream View controller driver (BLE, via D-Bus)" ON "XRT_HAVE_DBUS" OFF) cmake_dependent_option(XRT_BUILD_DRIVER_ARDUINO "Enable Arduino input device with BLE via via D-Bus" ON "XRT_HAVE_DBUS" OFF) - option(XRT_BUILD_DRIVER_DUMMY "Enable dummy driver" ON) +option(XRT_BUILD_DRIVER_REMOTE "Enable remote debugging driver" ON) # These all use the Monado internal hid wrapper. cmake_dependent_option(XRT_BUILD_DRIVER_HDK "Enable HDK driver" ON "XRT_HAVE_INTERNAL_HID" OFF) @@ -162,7 +162,7 @@ cmake_dependent_option(XRT_BUILD_DRIVER_SURVIVE "Enable libsurvive driver" OFF " # You can set this from a superproject to add a driver # All drivers must be listed in here to be included in the generated header! -list(APPEND AVAILABLE_DRIVERS ARDUINO DUMMY HDK HYDRA NS OHMD PSMV PSVR RS V4L2 VIVE DAYDREAM SURVIVE) +list(APPEND AVAILABLE_DRIVERS ARDUINO DUMMY HDK HYDRA NS OHMD PSMV PSVR RS V4L2 VIVE DAYDREAM REMOTE SURVIVE) ### # Flags @@ -263,6 +263,7 @@ message(STATUS "# DRIVER_OHMD: ${XRT_BUILD_DRIVER_OHMD}") message(STATUS "# DRIVER_PSMV: ${XRT_BUILD_DRIVER_PSMV}") message(STATUS "# DRIVER_PSVR: ${XRT_BUILD_DRIVER_PSVR}") message(STATUS "# DRIVER_RS: ${XRT_BUILD_DRIVER_RS}") +message(STATUS "# DRIVER_REMOTE: ${XRT_BUILD_DRIVER_REMOTE}") message(STATUS "# DRIVER_SURVIVE: ${XRT_BUILD_DRIVER_SURVIVE}") message(STATUS "# DRIVER_VIVE: ${XRT_BUILD_DRIVER_VIVE}") message(STATUS "#####----- Config -----#####") diff --git a/src/xrt/drivers/CMakeLists.txt b/src/xrt/drivers/CMakeLists.txt index ee3497dec..f7520c8b0 100644 --- a/src/xrt/drivers/CMakeLists.txt +++ b/src/xrt/drivers/CMakeLists.txt @@ -134,6 +134,20 @@ if(XRT_BUILD_DRIVER_RS) list(APPEND ENABLED_HEADSET_DRIVERS rs) endif() +if(XRT_BUILD_DRIVER_REMOTE) + set(REMOTE_SOURCE_FILES + remote/r_device.c + remote/r_hmd.c + remote/r_hub.c + remote/r_interface.h + remote/r_internal.h + ) + + add_library(drv_remote STATIC ${REMOTE_SOURCE_FILES}) + target_link_libraries(drv_remote PRIVATE xrt-interfaces aux_util) + list(APPEND ENABLED_HEADSET_DRIVERS remote) +endif() + if(XRT_BUILD_DRIVER_VIVE) set(VIVE_SOURCE_FILES vive/vive_device.h diff --git a/src/xrt/drivers/remote/r_device.c b/src/xrt/drivers/remote/r_device.c new file mode 100644 index 000000000..29425b779 --- /dev/null +++ b/src/xrt/drivers/remote/r_device.c @@ -0,0 +1,195 @@ +// Copyright 2020, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Controller remote driver. + * @author Jakob Bornecrantz + * @ingroup drv_remote + */ + +#include "os/os_time.h" + +#include "util/u_var.h" +#include "util/u_misc.h" +#include "util/u_debug.h" +#include "util/u_device.h" + +#include "math/m_api.h" + +#include "r_internal.h" + +#include + + +/* + * + * Functions + * + */ + +static inline struct r_device * +r_device(struct xrt_device *xdev) +{ + return (struct r_device *)xdev; +} + +static void +r_device_destroy(struct xrt_device *xdev) +{ + struct r_device *rd = r_device(xdev); + + // Remove the variable tracking. + u_var_remove_root(rd); + + // Free this device with the helper. + u_device_free(&rd->base); +} + +static void +r_device_update_inputs(struct xrt_device *xdev) +{ + struct r_device *rd = r_device(xdev); + struct r_hub *r = rd->r; + + uint64_t now = os_monotonic_get_ns(); + struct r_remote_controller_data *latest = + rd->is_left ? &r->latest.left : &r->latest.right; + + if (!latest->active) { + xdev->inputs[0].active = false; + xdev->inputs[0].timestamp = now; + xdev->inputs[1].active = false; + xdev->inputs[1].timestamp = now; + xdev->inputs[2].active = false; + xdev->inputs[2].timestamp = now; + xdev->inputs[3].active = false; + xdev->inputs[3].timestamp = now; + } else { + xdev->inputs[0].active = true; + xdev->inputs[0].timestamp = now; + xdev->inputs[0].value.boolean = latest->select; + xdev->inputs[1].active = true; + xdev->inputs[1].timestamp = now; + xdev->inputs[1].value.boolean = latest->menu; + xdev->inputs[2].active = true; + xdev->inputs[2].timestamp = now; + xdev->inputs[3].active = true; + xdev->inputs[3].timestamp = now; + } +} + +static void +r_device_get_tracked_pose(struct xrt_device *xdev, + enum xrt_input_name name, + uint64_t at_timestamp_ns, + struct xrt_space_relation *out_relation) +{ + struct r_device *rd = r_device(xdev); + struct r_hub *r = rd->r; + + if (name != XRT_INPUT_SIMPLE_AIM_POSE && + name != XRT_INPUT_SIMPLE_GRIP_POSE) { + U_LOG_E("Unknown input name"); + return; + } + + struct r_remote_controller_data *latest = + rd->is_left ? &r->latest.left : &r->latest.right; + + /* + * It's easier to reason about angular velocity if it's controlled in + * body space, but the angular velocity returned in the relation is in + * the base space. + */ + math_quat_rotate_derivative(&latest->pose.orientation, + &latest->angular_velocity, + &out_relation->angular_velocity); + + out_relation->pose = latest->pose; + out_relation->linear_velocity = latest->linear_velocity; + out_relation->relation_flags = (enum xrt_space_relation_flags)( + XRT_SPACE_RELATION_ORIENTATION_VALID_BIT | + XRT_SPACE_RELATION_POSITION_VALID_BIT | + XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT | + XRT_SPACE_RELATION_POSITION_TRACKED_BIT | + XRT_SPACE_RELATION_LINEAR_VELOCITY_VALID_BIT | + XRT_SPACE_RELATION_ANGULAR_VELOCITY_VALID_BIT); +} + +static void +r_device_get_hand_tracking(struct xrt_device *xdev, + enum xrt_input_name name, + uint64_t at_timestamp_ns, + union xrt_hand_joint_set *out_value) +{ + // Empty +} + +static void +r_device_get_view_pose(struct xrt_device *xdev, + struct xrt_vec3 *eye_relation, + uint32_t view_index, + struct xrt_pose *out_pose) +{ + // Empty +} + +static void +r_device_set_output(struct xrt_device *xdev, + enum xrt_output_name name, + union xrt_output_value *value) +{ + struct r_device *rd = r_device(xdev); + (void)rd; +} + +/*! + * @public @memberof r_device + */ +struct xrt_device * +r_device_create(struct r_hub *r, bool is_left) +{ + // Allocate. + const enum u_device_alloc_flags flags = 0; + const uint32_t num_inputs = 4; + const uint32_t num_outputs = 1; + struct r_device *rd = U_DEVICE_ALLOCATE( // + struct r_device, flags, num_inputs, num_outputs); + + // Setup the basics. + rd->base.update_inputs = r_device_update_inputs; + rd->base.get_tracked_pose = r_device_get_tracked_pose; + rd->base.get_hand_tracking = r_device_get_hand_tracking; + rd->base.get_view_pose = r_device_get_view_pose; + rd->base.set_output = r_device_set_output; + rd->base.destroy = r_device_destroy; + rd->base.tracking_origin = &r->base; + rd->base.orientation_tracking_supported = true; + rd->base.position_tracking_supported = true; + rd->base.hand_tracking_supported = false; + rd->base.name = XRT_DEVICE_SIMPLE_CONTROLLER; + rd->r = r; + rd->is_left = is_left; + + // Print name. + snprintf(rd->base.str, sizeof(rd->base.str), "Remote %s Controller", + is_left ? "Left" : "Right"); + + // Inputs and outputs. + rd->base.inputs[0].name = XRT_INPUT_SIMPLE_SELECT_CLICK; + rd->base.inputs[1].name = XRT_INPUT_SIMPLE_MENU_CLICK; + rd->base.inputs[2].name = XRT_INPUT_SIMPLE_GRIP_POSE; + rd->base.inputs[3].name = XRT_INPUT_SIMPLE_AIM_POSE; + rd->base.outputs[0].name = XRT_OUTPUT_NAME_SIMPLE_VIBRATION; + + if (is_left) { + rd->base.device_type = XRT_DEVICE_TYPE_LEFT_HAND_CONTROLLER; + } else { + rd->base.device_type = XRT_DEVICE_TYPE_RIGHT_HAND_CONTROLLER; + } + + // Setup variable tracker. + u_var_add_root(rd, rd->base.str, true); + + return &rd->base; +} diff --git a/src/xrt/drivers/remote/r_hmd.c b/src/xrt/drivers/remote/r_hmd.c new file mode 100644 index 000000000..e837bedf8 --- /dev/null +++ b/src/xrt/drivers/remote/r_hmd.c @@ -0,0 +1,180 @@ +// Copyright 2020, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief HMD remote driver. + * @author Jakob Bornecrantz + * @ingroup drv_remote + */ + +#include "os/os_time.h" + +#include "util/u_var.h" +#include "util/u_misc.h" +#include "util/u_debug.h" +#include "util/u_device.h" +#include "util/u_distortion_mesh.h" + +#include "math/m_api.h" +#include "math/m_mathinclude.h" + +#include "r_internal.h" + +#include + + +/* + * + * Functions + * + */ + +static inline struct r_hmd * +r_hmd(struct xrt_device *xdev) +{ + return (struct r_hmd *)xdev; +} + +static void +r_hmd_destroy(struct xrt_device *xdev) +{ + struct r_hmd *rh = r_hmd(xdev); + + // Remove the variable tracking. + u_var_remove_root(rh); + + // Free this device with the helper. + u_device_free(&rh->base); +} + +static void +r_hmd_update_inputs(struct xrt_device *xdev) +{ + struct r_hmd *rh = r_hmd(xdev); + (void)rh; +} + +static void +r_hmd_get_tracked_pose(struct xrt_device *xdev, + enum xrt_input_name name, + uint64_t at_timestamp_ns, + struct xrt_space_relation *out_relation) +{ + struct r_hmd *rh = r_hmd(xdev); + + if (name != XRT_INPUT_GENERIC_HEAD_POSE) { + U_LOG_E("Unknown input name"); + return; + } + + out_relation->pose = rh->r->latest.hmd.pose; + out_relation->relation_flags = (enum xrt_space_relation_flags)( + XRT_SPACE_RELATION_ORIENTATION_VALID_BIT | + XRT_SPACE_RELATION_POSITION_VALID_BIT | + XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT | + XRT_SPACE_RELATION_POSITION_TRACKED_BIT); +} + +static void +r_hmd_get_hand_tracking(struct xrt_device *xdev, + enum xrt_input_name name, + uint64_t at_timestamp_ns, + union xrt_hand_joint_set *out_value) +{ + struct r_hmd *rh = r_hmd(xdev); + (void)rh; +} + +static void +r_hmd_get_view_pose(struct xrt_device *xdev, + struct xrt_vec3 *eye_relation, + uint32_t view_index, + struct xrt_pose *out_pose) +{ + struct xrt_pose pose = {{0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 0.0f}}; + bool adjust = view_index == 0; + + pose.position.x = eye_relation->x / 2.0f; + pose.position.y = eye_relation->y / 2.0f; + pose.position.z = eye_relation->z / 2.0f; + + // Adjust for left/right while also making sure there aren't any -0.f. + if (pose.position.x > 0.0f && adjust) { + pose.position.x = -pose.position.x; + } + if (pose.position.y > 0.0f && adjust) { + pose.position.y = -pose.position.y; + } + if (pose.position.z > 0.0f && adjust) { + pose.position.z = -pose.position.z; + } + + *out_pose = pose; +} + +static void +r_hmd_set_output(struct xrt_device *xdev, + enum xrt_output_name name, + union xrt_output_value *value) +{ + // Empty +} + +/*! + * @public @memberof r_hmd + */ +struct xrt_device * +r_hmd_create(struct r_hub *r) +{ + // Allocate. + const enum u_device_alloc_flags flags = U_DEVICE_ALLOC_HMD; + const uint32_t num_inputs = 1; + const uint32_t num_outputs = 0; + struct r_hmd *rh = U_DEVICE_ALLOCATE( // + struct r_hmd, flags, num_inputs, num_outputs); + + // Setup the basics. + rh->base.update_inputs = r_hmd_update_inputs; + rh->base.get_tracked_pose = r_hmd_get_tracked_pose; + rh->base.get_hand_tracking = r_hmd_get_hand_tracking; + rh->base.get_view_pose = r_hmd_get_view_pose; + rh->base.set_output = r_hmd_set_output; + rh->base.destroy = r_hmd_destroy; + rh->base.tracking_origin = &r->base; + rh->base.orientation_tracking_supported = true; + rh->base.position_tracking_supported = true; + rh->base.hand_tracking_supported = false; + rh->base.name = XRT_DEVICE_GENERIC_HMD; + rh->base.device_type = XRT_DEVICE_TYPE_HMD; + rh->base.inputs[0].name = XRT_INPUT_GENERIC_HEAD_POSE; + rh->base.inputs[0].active = true; + rh->r = r; + + // Print name. + snprintf(rh->base.str, sizeof(rh->base.str), "Remote HMD"); + + // Setup info. + struct u_device_simple_info info; + info.display.w_pixels = 1920; + info.display.h_pixels = 1080; + info.display.w_meters = 0.13f; + info.display.h_meters = 0.07f; + info.lens_horizontal_separation_meters = 0.13f / 2.0f; + info.lens_vertical_position_meters = 0.07f / 2.0f; + info.views[0].fov = 85.0f * (M_PI / 180.0f); + info.views[1].fov = 85.0f * (M_PI / 180.0f); + + if (!u_device_setup_split_side_by_side(&rh->base, &info)) { + U_LOG_E("Failed to setup basic device info"); + r_hmd_destroy(&rh->base); + return NULL; + } + + // Distortion information, fills in xdev->compute_distortion(). + u_distortion_mesh_set_none(&rh->base); + + // Setup variable tracker. + u_var_add_root(rh, rh->base.str, true); + + return &rh->base; +} diff --git a/src/xrt/drivers/remote/r_hub.c b/src/xrt/drivers/remote/r_hub.c new file mode 100644 index 000000000..7a21882eb --- /dev/null +++ b/src/xrt/drivers/remote/r_hub.c @@ -0,0 +1,318 @@ +// Copyright 2020, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Main hub of the remote driver. + * @author Jakob Bornecrantz + * @ingroup drv_remote + */ + +#include "util/u_var.h" +#include "util/u_misc.h" +#include "util/u_logging.h" + +#include "r_interface.h" +#include "r_internal.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +/* + * + * Function. + * + */ + +int +setup_accept_fd(struct r_hub *r) +{ + struct sockaddr_in server_address = {0}; + int ret; + + ret = socket(AF_INET, SOCK_STREAM, 0); + if (ret < 0) { + U_LOG_E("socket failed: %i", ret); + return ret; + } + + r->accept_fd = ret; + + int flag = 1; + ret = setsockopt(r->accept_fd, SOL_SOCKET, SO_REUSEADDR, &flag, + sizeof(flag)); + if (ret < 0) { + U_LOG_E("setsockopt failed: %i", ret); + close(r->accept_fd); + r->accept_fd = -1; + return ret; + } + + server_address.sin_family = AF_INET; + server_address.sin_addr.s_addr = htonl(INADDR_ANY); + server_address.sin_port = htons(r->port); + + ret = bind(r->accept_fd, (struct sockaddr *)&server_address, + sizeof(server_address)); + if (ret < 0) { + U_LOG_E("bind failed: %i", ret); + close(r->accept_fd); + r->accept_fd = -1; + return ret; + } + + listen(r->accept_fd, 5); + + return 0; +} + +int +do_accept(struct r_hub *r) +{ + struct sockaddr_in addr = {0}; + int ret, conn_fd; + + unsigned addr_length = sizeof(addr); + ret = accept(r->accept_fd, (struct sockaddr *)&addr, &addr_length); + if (ret < 0) { + U_LOG_E("accept failed: %i", ret); + return ret; + } + + conn_fd = ret; + + int flags = 1; + ret = setsockopt(conn_fd, SOL_TCP, TCP_NODELAY, (void *)&flags, + sizeof(flags)); + if (ret < 0) { + U_LOG_E("setsockopt failed: %i", ret); + close(conn_fd); + return ret; + } + + r->rc.fd = conn_fd; + + U_LOG_I("Connection received! %i", r->rc.fd); + + return 0; +} + +void * +run_thread(void *ptr) +{ + struct r_hub *r = (struct r_hub *)ptr; + int ret; + + ret = setup_accept_fd(r); + if (ret < 0) { + return NULL; + } + + while (true) { + U_LOG_I("Listening on port '%i'.", r->port); + + ret = do_accept(r); + + r_remote_connection_write_one(&r->rc, &r->reset); + r_remote_connection_write_one(&r->rc, &r->latest); + + while (true) { + struct r_remote_data data; + + ret = r_remote_connection_read_one(&r->rc, &data); + if (ret < 0) { + break; + } + + r->latest = data; + } + } + + return NULL; +} + +void +r_hub_destroy(struct r_hub *r) +{ + free(r); +} + + +/*! + * + * + * + */ + +int +r_create_devices(uint16_t port, + struct xrt_device **out_hmd, + struct xrt_device **out_controller_left, + struct xrt_device **out_controller_right) +{ + struct r_hub *r = U_TYPED_CALLOC(struct r_hub); + int ret; + + r->base.type = XRT_TRACKING_TYPE_RGB; + r->base.offset.orientation.w = 1.0f; // All other members are zero. + r->reset.hmd.pose.position.y = 1.6f; + r->reset.hmd.pose.orientation.w = 1.0f; + r->reset.left.active = true; + r->reset.left.pose.position.x = -0.2f; + r->reset.left.pose.position.y = 1.3f; + r->reset.left.pose.position.z = -0.5f; + r->reset.left.pose.orientation.w = 1.0f; + r->reset.right.active = true; + r->reset.right.pose.position.x = 0.2f; + r->reset.right.pose.position.y = 1.3f; + r->reset.right.pose.position.z = -0.5f; + r->reset.right.pose.orientation.w = 1.0f; + r->latest = r->reset; + r->gui.hmd = true; + r->gui.left = true; + r->gui.right = true; + r->port = port; + r->accept_fd = -1; + r->rc.fd = -1; + + snprintf(r->base.name, sizeof(r->base.name), "Remote Simulator"); + + ret = os_thread_helper_init(&r->oth); + if (ret != 0) { + U_LOG_E("Failed to init threading!"); + r_hub_destroy(r); + return ret; + } + + ret = os_thread_helper_start(&r->oth, run_thread, r); + if (ret != 0) { + U_LOG_E("Failed to start thread!"); + r_hub_destroy(r); + return ret; + } + + *out_hmd = r_hmd_create(r); + *out_controller_left = r_device_create(r, true); + *out_controller_right = r_device_create(r, false); + + // Setup variable tracker. + u_var_add_root(r, "Remote Hub", true); + // u_var_add_gui_header(r, &r->gui.hmd, "MHD"); + u_var_add_pose(r, &r->latest.hmd.pose, "hmd.pose"); + // u_var_add_gui_header(r, &r->gui.left, "Left"); + u_var_add_bool(r, &r->latest.left.active, "left.active"); + u_var_add_bool(r, &r->latest.left.select, "left.select"); + u_var_add_bool(r, &r->latest.left.menu, "left.menu"); + u_var_add_pose(r, &r->latest.left.pose, "left.pose"); + // u_var_add_gui_header(r, &r->gui.right, "Right"); + u_var_add_bool(r, &r->latest.right.active, "right.active"); + u_var_add_bool(r, &r->latest.right.select, "right.select"); + u_var_add_bool(r, &r->latest.right.menu, "right.menu"); + u_var_add_pose(r, &r->latest.right.pose, "right.pose"); + + return 0; +} + +int +r_remote_connection_init(struct r_remote_connection *rc, + const char *ip_addr, + uint16_t port) +{ + struct sockaddr_in addr = {0}; + int conn_fd; + int ret; + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + ret = inet_pton(AF_INET, ip_addr, &addr.sin_addr); + if (ret < 0) { + U_LOG_E("socket failed: %i", ret); + return ret; + } + + ret = socket(AF_INET, SOCK_STREAM, 0); + if (ret < 0) { + U_LOG_E("socket failed: %i", ret); + return ret; + } + + conn_fd = ret; + + ret = connect(conn_fd, (struct sockaddr *)&addr, sizeof(addr)); + if (ret < 0) { + U_LOG_E("connect failed: %i", ret); + close(conn_fd); + return ret; + } + + int flags = 1; + ret = setsockopt(conn_fd, SOL_TCP, TCP_NODELAY, (void *)&flags, + sizeof(flags)); + if (ret < 0) { + U_LOG_E("setsockopt failed: %i", ret); + close(conn_fd); + return ret; + } + + rc->fd = conn_fd; + + return 0; +} + +int +r_remote_connection_read_one(struct r_remote_connection *rc, + struct r_remote_data *data) +{ + const size_t size = sizeof(*data); + size_t current = 0; + + while (current < size) { + void *ptr = (uint8_t *)data + current; + + ssize_t ret = read(rc->fd, ptr, size - current); + if (ret < 0) { + return ret; + } else if (ret > 0) { + current += (size_t)ret; + } else { + U_LOG_I("Disconnected!"); + return -1; + } + } + + return 0; +} + +int +r_remote_connection_write_one(struct r_remote_connection *rc, + const struct r_remote_data *data) +{ + const size_t size = sizeof(*data); + size_t current = 0; + + while (current < size) { + const void *ptr = (const uint8_t *)data + current; + + ssize_t ret = write(rc->fd, ptr, size - current); + if (ret < 0) { + return ret; + } else if (ret > 0) { + current += (size_t)ret; + } else { + U_LOG_I("Disconnected!"); + return -1; + } + } + + return 0; +} diff --git a/src/xrt/drivers/remote/r_interface.h b/src/xrt/drivers/remote/r_interface.h new file mode 100644 index 000000000..f971f1763 --- /dev/null +++ b/src/xrt/drivers/remote/r_interface.h @@ -0,0 +1,115 @@ +// Copyright 2020, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Interface to remote driver. + * @author Jakob Bornecrantz + * @ingroup drv_remote + */ + +#pragma once + +#include "xrt/xrt_defines.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +struct xrt_device; + +/*! + * @defgroup drv_remote Remote debugging driver + * @ingroup drv + * + * @brief Driver for creating remote debugging devices. + */ + +/*! + * @dir drivers/remote + * + * @brief @ref drv_remote files. + */ + +/*! + * Header value to be set in the packet. + * + * @ingroup drv_remote + */ +#define R_HEADER_VALUE (*(uint64_t *)"mndrmt1\0") + +/*! + * Data per controller. + */ +struct r_remote_controller_data +{ + struct xrt_pose pose; + struct xrt_vec3 linear_velocity; + struct xrt_vec3 angular_velocity; + + bool active; + bool select; + bool menu; + bool _pad; +}; + +/*! + * Remote data sent from the debugger to the hub. + * + * @ingroup drv_remote + */ +struct r_remote_data +{ + uint64_t header; + + struct + { + struct xrt_pose pose; + } hmd; + + struct r_remote_controller_data left, right; +}; + +/*! + * Shared connection. + * + * @ingroup drv_remote + */ +struct r_remote_connection +{ + int fd; +}; + +/*! + * Creates the remote devices. + * + * @ingroup drv_remote + */ +int +r_create_devices(uint16_t port, + struct xrt_device **out_hmd, + struct xrt_device **out_controller_left, + struct xrt_device **out_controller_right); + +/*! + * Initializes and connects the connection. + * + * @ingroup drv_remote + */ +int +r_remote_connection_init(struct r_remote_connection *rc, + const char *addr, + uint16_t port); + +int +r_remote_connection_read_one(struct r_remote_connection *rc, + struct r_remote_data *data); + +int +r_remote_connection_write_one(struct r_remote_connection *rc, + const struct r_remote_data *data); + + +#ifdef __cplusplus +} +#endif diff --git a/src/xrt/drivers/remote/r_internal.h b/src/xrt/drivers/remote/r_internal.h new file mode 100644 index 000000000..4eb36658b --- /dev/null +++ b/src/xrt/drivers/remote/r_internal.h @@ -0,0 +1,91 @@ +// Copyright 2020, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Internal stuff in remote driver. + * @author Jakob Bornecrantz + * @ingroup drv_remote + */ + +#pragma once + +#include "xrt/xrt_device.h" +#include "xrt/xrt_tracking.h" + +#include "os/os_threading.h" + +#include "r_interface.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/*! + * Central object remote object. + * + * @ingroup drv_remote + */ +struct r_hub +{ + struct xrt_tracking_origin base; + + //! Connection to the controller. + struct r_remote_connection rc; + + //! The data that the is the reset position. + struct r_remote_data reset; + + //! The latest data received. + struct r_remote_data latest; + + + int accept_fd; + + uint16_t port; + + struct os_thread_helper oth; + + struct + { + bool hmd, left, right; + } gui; +}; + +/*! + * HMD + * + * @ingroup drv_remote + */ +struct r_hmd +{ + struct xrt_device base; + + struct r_hub *r; +}; + +/*! + * Device + * + * @ingroup drv_remote + */ +struct r_device +{ + struct xrt_device base; + + struct r_hub *r; + + bool is_left; +}; + + +struct xrt_device * +r_hmd_create(struct r_hub *r); + +struct xrt_device * +r_device_create(struct r_hub *r, bool is_left); + + +#ifdef __cplusplus +} +#endif diff --git a/src/xrt/targets/common/CMakeLists.txt b/src/xrt/targets/common/CMakeLists.txt index 25a933e82..662ab5738 100644 --- a/src/xrt/targets/common/CMakeLists.txt +++ b/src/xrt/targets/common/CMakeLists.txt @@ -60,6 +60,10 @@ if(XRT_BUILD_DRIVER_RS) target_link_libraries(target_lists PRIVATE drv_rs) endif() +if(XRT_BUILD_DRIVER_REMOTE) + target_link_libraries(target_lists PRIVATE drv_remote) +endif() + if(XRT_HAVE_V4L2) target_link_libraries(target_lists PRIVATE drv_v4l2) endif()