Monado OpenXR Runtime
hydra_driver.c File Reference

Razer Hydra prober and driver code. More...

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xrt/xrt_prober.h"
#include "os/os_hid.h"
#include "os/os_time.h"
#include "os/os_threading.h"
#include "math/m_api.h"
#include "math/m_relation_history.h"
#include "math/m_space.h"
#include "util/u_debug.h"
#include "util/u_device.h"
#include "util/u_misc.h"
#include "util/u_time.h"
#include "util/u_logging.h"
#include "util/u_linux.h"
#include "util/u_trace_marker.h"
#include "util/u_var.h"
#include "hydra_interface.h"
Include dependency graph for hydra_driver.c:

Data Structures

struct  hydra_controller_state
 
struct  hydra_state_machine
 The details of the Hydra state machine in a convenient package. More...
 
struct  hydra_system
 A Razer Hydra system containing two controllers. More...
 
struct  hydra_device
 A Razer Hydra device, representing just a single controller. More...
 

Macros

#define HD_TRACE(d, ...)   U_LOG_XDEV_IFL_T(&d->base, d->sys->log_level, __VA_ARGS__)
 
#define HD_DEBUG(d, ...)   U_LOG_XDEV_IFL_D(&d->base, d->sys->log_level, __VA_ARGS__)
 
#define HD_INFO(d, ...)   U_LOG_XDEV_IFL_I(&d->base, d->sys->log_level, __VA_ARGS__)
 
#define HD_WARN(d, ...)   U_LOG_XDEV_IFL_W(&d->base, d->sys->log_level, __VA_ARGS__)
 
#define HD_ERROR(d, ...)   U_LOG_XDEV_IFL_E(&d->base, d->sys->log_level, __VA_ARGS__)
 
#define HS_TRACE(d, ...)   U_LOG_IFL_T(d->log_level, __VA_ARGS__)
 
#define HS_DEBUG(d, ...)   U_LOG_IFL_D(d->log_level, __VA_ARGS__)
 
#define HS_INFO(d, ...)   U_LOG_IFL_I(d->log_level, __VA_ARGS__)
 
#define HS_WARN(d, ...)   U_LOG_IFL_W(d->log_level, __VA_ARGS__)
 
#define HS_ERROR(d, ...)   U_LOG_IFL_E(d->log_level, __VA_ARGS__)
 
#define SET_INPUT(NAME)
 

Enumerations

enum  hydra_input_index {
  HYDRA_INDEX_1_CLICK , HYDRA_INDEX_2_CLICK , HYDRA_INDEX_3_CLICK , HYDRA_INDEX_4_CLICK ,
  HYDRA_INDEX_MIDDLE_CLICK , HYDRA_INDEX_BUMPER_CLICK , HYDRA_INDEX_JOYSTICK_CLICK , HYDRA_INDEX_JOYSTICK_VALUE ,
  HYDRA_INDEX_TRIGGER_VALUE , HYDRA_INDEX_GRIP_POSE , HYDRA_INDEX_AIM_POSE , HYDRA_MAX_CONTROLLER_INDEX
}
 
enum  hydra_button_bit {
  HYDRA_BUTTON_BIT_BUMPER = (1 << 0) , HYDRA_BUTTON_BIT_3 = (1 << 1) , HYDRA_BUTTON_BIT_1 = (1 << 2) , HYDRA_BUTTON_BIT_2 = (1 << 3) ,
  HYDRA_BUTTON_BIT_4 = (1 << 4) , HYDRA_BUTTON_BIT_MIDDLE = (1 << 5) , HYDRA_BUTTON_BIT_JOYSTICK = (1 << 6)
}
 
enum  hydra_sm_state { HYDRA_SM_LISTENING_AFTER_CONNECT = 0 , HYDRA_SM_LISTENING_AFTER_SET_FEATURE , HYDRA_SM_REPORTING }
 The states of the finite-state machine controlling the Hydra. More...
 

Functions

static void hydra_device_parse_controller (struct hydra_device *hd, uint8_t *buf, int64_t now)
 Parse the controller-specific part of a buffer into a hydra device. More...
 
static struct hydra_devicehydra_device (struct xrt_device *xdev)
 
static struct hydra_systemhydra_system (struct xrt_tracking_origin *xtrack)
 
static uint8_t hydra_read_uint8 (uint8_t **bufptr)
 
static int16_t hydra_read_int16_le (uint8_t **bufptr)
 
static int hydra_system_read_data_hid (struct hydra_system *hs)
 
static void hydra_system_enter_motion_control (struct hydra_system *hs, timepoint_ns now)
 Switch to motion controller mode. More...
 
static int hydra_system_update (struct hydra_system *hs)
 Update the internal state of the Hydra driver. More...
 
static void hydra_device_update_input_click (struct hydra_device *hd, timepoint_ns now, int index, uint32_t bit)
 
static void * hydra_usb_thread_run (void *user_data)
 
static xrt_result_t hydra_device_update_inputs (struct xrt_device *xdev)
 
static xrt_result_t hydra_device_get_tracked_pose (struct xrt_device *xdev, enum xrt_input_name name, int64_t at_timestamp_ns, struct xrt_space_relation *out_relation)
 
static void hydra_system_remove_child (struct hydra_system *hs, struct hydra_device *hd)
 
static void hydra_device_destroy (struct xrt_device *xdev)
 
int hydra_found (struct xrt_prober *xp, struct xrt_prober_device **devices, size_t device_count, size_t index, cJSON *attached_data, struct xrt_device **out_xdevs)
 Probing function for Razer Hydra devices. More...
 

Variables

static const uint8_t HYDRA_REPORT_START_MOTION []
 
static const uint8_t HYDRA_REPORT_START_GAMEPAD []
 
static struct xrt_binding_input_pair touch_inputs [19]
 
static struct xrt_binding_input_pair simple_inputs [4]
 
static struct xrt_binding_profile binding_profiles [2]
 

Detailed Description

Razer Hydra prober and driver code.

Author
Rylie Pavlik rylie.nosp@m..pav.nosp@m.lik@c.nosp@m.olla.nosp@m.bora..nosp@m.com
Jakob Bornecrantz jakob.nosp@m.@col.nosp@m.labor.nosp@m.a.co.nosp@m.m

Portions based on the VRPN Razer Hydra driver, originally written by Rylie Pavlik and available under the BSL-1.0.

Macro Definition Documentation

◆ SET_INPUT

#define SET_INPUT (   NAME)
Value:
do { \
(hd->base.inputs[HYDRA_INDEX_##NAME].name = XRT_INPUT_HYDRA_##NAME); \
} while (0)

Enumeration Type Documentation

◆ hydra_sm_state

The states of the finite-state machine controlling the Hydra.

Function Documentation

◆ hydra_device_parse_controller()

static void hydra_device_parse_controller ( struct hydra_device hd,
uint8_t *  buf,
int64_t  now 
)
static

Parse the controller-specific part of a buffer into a hydra device.

Todo:
the presence of this suggest we're not decoding the orientation right.

References hydra_read_int16_le(), xrt_quat::math_quat_normalize(), and xrt_quat::math_quat_rotate().

◆ hydra_read_int16_le()

static int16_t hydra_read_int16_le ( uint8_t **  bufptr)
inlinestatic
Todo:
nothing actually defines XRT_BIG_ENDIAN when needed!

Referenced by hydra_device_parse_controller().

◆ hydra_system_enter_motion_control()

static void hydra_system_enter_motion_control ( struct hydra_system hs,
timepoint_ns  now 
)
static

Switch to motion controller mode.

References hydra_system::was_in_gamepad_mode.

◆ hydra_system_update()

static int hydra_system_update ( struct hydra_system hs)
static

Update the internal state of the Hydra driver.

Reads devices, checks the state machine and timeouts, etc.

Variable Documentation

◆ binding_profiles

struct xrt_binding_profile binding_profiles[2]
static
Initial value:
= {
{
.name = XRT_DEVICE_TOUCH_CONTROLLER,
.inputs = touch_inputs,
.input_count = ARRAY_SIZE(touch_inputs),
},
{
.name = XRT_DEVICE_SIMPLE_CONTROLLER,
.inputs = simple_inputs,
.input_count = ARRAY_SIZE(simple_inputs),
},
}
#define ARRAY_SIZE(a)
Array size helper.
Definition: xrt_compiler.h:30

◆ HYDRA_REPORT_START_GAMEPAD

const uint8_t HYDRA_REPORT_START_GAMEPAD[]
static
Initial value:
= {
0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00}

◆ HYDRA_REPORT_START_MOTION

const uint8_t HYDRA_REPORT_START_MOTION[]
static
Initial value:
= {
0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00}

◆ simple_inputs

struct xrt_binding_input_pair simple_inputs[4]
static
Initial value:
= {
{XRT_INPUT_SIMPLE_SELECT_CLICK, XRT_INPUT_HYDRA_TRIGGER_VALUE},
{XRT_INPUT_SIMPLE_MENU_CLICK, XRT_INPUT_HYDRA_MIDDLE_CLICK},
{XRT_INPUT_SIMPLE_GRIP_POSE, XRT_INPUT_HYDRA_GRIP_POSE},
{XRT_INPUT_SIMPLE_AIM_POSE, XRT_INPUT_HYDRA_AIM_POSE},
}

◆ touch_inputs

struct xrt_binding_input_pair touch_inputs[19]
static
Initial value:
= {
{XRT_INPUT_TOUCH_X_CLICK, XRT_INPUT_HYDRA_2_CLICK},
{XRT_INPUT_TOUCH_X_TOUCH, XRT_INPUT_HYDRA_2_CLICK},
{XRT_INPUT_TOUCH_Y_CLICK, XRT_INPUT_HYDRA_4_CLICK},
{XRT_INPUT_TOUCH_Y_TOUCH, XRT_INPUT_HYDRA_4_CLICK},
{XRT_INPUT_TOUCH_MENU_CLICK, XRT_INPUT_HYDRA_MIDDLE_CLICK},
{XRT_INPUT_TOUCH_A_CLICK, XRT_INPUT_HYDRA_1_CLICK},
{XRT_INPUT_TOUCH_A_TOUCH, XRT_INPUT_HYDRA_1_CLICK},
{XRT_INPUT_TOUCH_B_CLICK, XRT_INPUT_HYDRA_3_CLICK},
{XRT_INPUT_TOUCH_B_TOUCH, XRT_INPUT_HYDRA_3_CLICK},
{XRT_INPUT_TOUCH_SYSTEM_CLICK, XRT_INPUT_HYDRA_MIDDLE_CLICK},
{XRT_INPUT_TOUCH_SQUEEZE_VALUE, XRT_INPUT_HYDRA_BUMPER_CLICK},
{XRT_INPUT_TOUCH_TRIGGER_TOUCH, XRT_INPUT_HYDRA_TRIGGER_VALUE},
{XRT_INPUT_TOUCH_TRIGGER_VALUE, XRT_INPUT_HYDRA_TRIGGER_VALUE},
{XRT_INPUT_TOUCH_THUMBSTICK_CLICK, XRT_INPUT_HYDRA_JOYSTICK_CLICK},
{XRT_INPUT_TOUCH_THUMBSTICK, XRT_INPUT_HYDRA_JOYSTICK_VALUE},
{XRT_INPUT_TOUCH_GRIP_POSE, XRT_INPUT_HYDRA_GRIP_POSE},
{XRT_INPUT_TOUCH_AIM_POSE, XRT_INPUT_HYDRA_AIM_POSE},
}