Commit 3483a728 authored by Jakob Bornecrantz's avatar Jakob Bornecrantz Committed by Jakob Bornecrantz
Browse files

d/remote: Add remote driver

parent 0cf3c704
......@@ -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 -----#####")
......@@ -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
......
// Copyright 2020, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Controller remote driver.
* @author Jakob Bornecrantz <jakob@collabora.com>
* @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 <stdio.h>
/*
*
* 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;
}
// Copyright 2020, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief HMD remote driver.
* @author Jakob Bornecrantz <jakob@collabora.com>
* @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 <stdio.h>
/*
*
* 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;
}
// Copyright 2020, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Main hub of the remote driver.
* @author Jakob Bornecrantz <jakob@collabora.com>
* @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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
/*
*
* 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");