mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-16 03:45:24 +00:00
d/remote: Add remote driver
This commit is contained in:
parent
0cf3c704b6
commit
3483a7286d
|
@ -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
|
||||
|
|
195
src/xrt/drivers/remote/r_device.c
Normal file
195
src/xrt/drivers/remote/r_device.c
Normal file
|
@ -0,0 +1,195 @@
|
|||
// 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;
|
||||
}
|
180
src/xrt/drivers/remote/r_hmd.c
Normal file
180
src/xrt/drivers/remote/r_hmd.c
Normal file
|
@ -0,0 +1,180 @@
|
|||
// 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;
|
||||
}
|
318
src/xrt/drivers/remote/r_hub.c
Normal file
318
src/xrt/drivers/remote/r_hub.c
Normal file
|
@ -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 <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");
|
||||
|
||||
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;
|
||||
}
|
115
src/xrt/drivers/remote/r_interface.h
Normal file
115
src/xrt/drivers/remote/r_interface.h
Normal file
|
@ -0,0 +1,115 @@
|
|||
// Copyright 2020, Collabora, Ltd.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief Interface to remote driver.
|
||||
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||
* @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
|
91
src/xrt/drivers/remote/r_internal.h
Normal file
91
src/xrt/drivers/remote/r_internal.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
// Copyright 2020, Collabora, Ltd.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief Internal stuff in remote driver.
|
||||
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||
* @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
|
|
@ -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()
|
||||
|
|
Loading…
Reference in a new issue