Monado OpenXR Runtime
rift_interface.h
Go to the documentation of this file.
1// Copyright 2025, Beyley Cardellio
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Interface to Oculus Rift driver code.
6 * @author Beyley Cardellion <ep1cm1n10n123@gmail.com>
7 * @ingroup drv_rift
8 */
9
10#pragma once
11
12#include "xrt/xrt_device.h"
13#include "xrt/xrt_defines.h"
14#include "xrt/xrt_prober.h"
15
16#include "os/os_hid.h"
17#include "os/os_threading.h"
18
19#include "util/u_device.h"
20#include "util/u_logging.h"
21
22#include "math/m_imu_3dof.h"
23#include "math/m_api.h"
24#include "math/m_mathinclude.h"
25
26#include <stdlib.h>
27#include <stdio.h>
28
29#ifdef __cplusplus
30extern "C" {
31#endif
32
33#define REPORT_MAX_SIZE 69 // max size of a feature report (FEATURE_REPORT_CALIBRATE)
34#define KEEPALIVE_INTERVAL_NS 10000000000 // 10 seconds
35// give a 5% breathing room (at 10 seconds, this is 500 milliseconds of breathing room)
36#define KEEPALIVE_SEND_RATE_NS ((KEEPALIVE_INTERVAL_NS * 19) / 20)
37#define IMU_SAMPLE_RATE (1000) // 1000hz
38#define NS_PER_SAMPLE (1000 * 1000) // 1ms (1,000,000 ns) per sample
39
40#define DEG_TO_RAD(DEG) (DEG * M_PI / 180.0)
41#define MICROMETERS_TO_METERS(microns) (float)microns / 1000000.0f
42
43// value taken from LibOVR 0.4.4
44#define DEFAULT_EXTRA_EYE_ROTATION DEG_TO_RAD(30.0f)
45
46enum rift_feature_reports
47{
48 // DK1
49 FEATURE_REPORT_CONFIG = 2, // get + set
50 FEATURE_REPORT_CALIBRATE = 3, // get + set
51 FEATURE_REPORT_RANGE = 4, // get + set
52 FEATURE_REPORT_REGISTER = 5, // get + set
53 FEATURE_REPORT_DFU = 6, // get + set
54 FEATURE_REPORT_DK1_KEEP_ALIVE = 8, // get + set
55 FEATURE_REPORT_DISPLAY_INFO = 9, // get + set
56 FEATURE_REPORT_SERIAL = 10, // get + set
57
58 // DK2
59 FEATURE_REPORT_TRACKING = 12, // get + set
60 FEATURE_REPORT_DISPLAY = 13, // get + set
61 FEATURE_REPORT_MAG_CALIBRATION = 14, // get + set
62 FEATURE_REPORT_POS_CALIBRATION = 15, // get + set
63 FEATURE_REPORT_CUSTOM_PATTERN = 16, // get + set
64 FEATURE_REPORT_KEEPALIVE_MUX = 17, // get + set
65 FEATURE_REPORT_MANUFACTURING = 18, // get + set
66 FEATURE_REPORT_UUID = 19, // get + set
67 FEATURE_REPORT_TEMPERATURE = 20, // get + set
68 FEATURE_REPORT_GYROOFFSET = 21, // get only
69 FEATURE_REPORT_LENS_DISTORTION = 22, // get + set
70};
71
72enum rift_config_report_flags
73{
74 // output the sample data raw from the sensors without converting them to known units
75 RIFT_CONFIG_REPORT_USE_RAW = 1,
76 // internal test mode for calibrating zero rate drift on gyro
77 RIFT_CONFIG_REPORT_INTERNAL_CALIBRATION = 1 << 1,
78 // use the calibration parameters stored on the device
79 RIFT_CONFIG_REPORT_USE_CALIBRATION = 1 << 2,
80 // recalibrate the gyro zero rate offset when the device is stationary
81 RIFT_CONFIG_REPORT_AUTO_CALIBRATION = 1 << 3,
82 // stop sending IN reports when the device has stopped moving for Interval milliseconds
83 RIFT_CONFIG_REPORT_MOTION_KEEP_ALIVE = 1 << 4,
84 // stop sending IN reports when the device has stopped receiving feature reports for Interval milliseconds
85 RIFT_CONFIG_REPORT_COMMAND_KEEP_ALIVE = 1 << 5,
86 // output the IN report data in the coordinate system used by LibOVR relative to the tracker, otherwise, report
87 // in the coordinate system of the device
88 RIFT_CONFIG_REPORT_USE_SENSOR_COORDINATES = 1 << 6,
89 // override the power state of the USB hub, forcing it to act as if the external power source is connected (DK2
90 // only, does nothing on DK1)
91 RIFT_CONFIG_REPORT_OVERRIDE_POWER = 1 << 7,
92};
93
94enum rift_distortion_type
95{
96 RIFT_DISTORTION_TYPE_DIMS = 1,
97 RIFT_DISTORTION_TYPE_K = 2,
98};
99
100enum rift_lens_type
101{
102 // firmware indirectly states lens type A is 0
103 RIFT_LENS_TYPE_A = 0,
104 // firmware does not state what lens type B is, 1 is an educated guess
105 RIFT_LENS_TYPE_B = 1,
106};
107
108#define IN_REPORT_DK2 11
109
110#define CATMULL_COEFFICIENTS 11
111#define CHROMATIC_ABBERATION_COEFFEICENT_COUNT 4
112
113enum rift_lens_distortion_version
114{
115 // no distortion data is stored
116 RIFT_LENS_DISTORTION_NONE = 0,
117 // standard distortion matrix
118 RIFT_LENS_DISTORTION_LCSV_CATMULL_ROM_10_VERSION_1 = 1,
119};
120
121/*
122 *
123 * Packed structs for USB communication (borrowed from Rokid driver)
124 *
125 */
126
127#if defined(__GNUC__)
128#define RIFT_PACKED __attribute__((packed))
129#else
130#define RIFT_PACKED
131#endif /* __GNUC__ */
132
133#if defined(_MSC_VER)
134#pragma pack(push, 1)
135#endif
136
138{
139 uint16_t command_id;
140 uint8_t config_flags;
141 // the IN report rate of the headset, rate is calculated as `sample_rate / (1 + interval)`
142 uint8_t interval;
143 // sample rate of the IMU, always 1000hz on DK1/DK2, read-only
144 uint16_t sample_rate;
145} RIFT_PACKED;
146
148{
149 uint16_t command_id;
150 uint8_t distortion_type;
151 // the horizontal resolution of the display, in pixels
152 uint16_t resolution_x;
153 // the vertical resolution of the display, in pixels
154 uint16_t resolution_y;
155 // width in micrometers
156 uint32_t display_width;
157 // height in micrometers
158 uint32_t display_height;
159 // the vertical center of the display, in micrometers
160 uint32_t center_v;
161 // the separation between the two lenses, in micrometers
162 uint32_t lens_separation;
163 uint32_t lens_distance[2];
164 float distortion[6];
165} RIFT_PACKED;
166
168{
169 // eye relief setting, in micrometers from front surface of lens
170 uint16_t eye_relief;
171 // the k coeffecients of the distortion
172 uint16_t k[CATMULL_COEFFICIENTS];
173 uint16_t max_r;
174 uint16_t meters_per_tan_angle_at_center;
175 uint16_t chromatic_abberation[CHROMATIC_ABBERATION_COEFFEICENT_COUNT];
176 uint8_t unused[14];
177} RIFT_PACKED;
178
180{
181 uint16_t command_id;
182 // the amount of distortions on this device
183 uint8_t num_distortions;
184 // the index of this distortion in the devices array
185 uint8_t distortion_idx;
186 // unused bitmask field
187 uint8_t bitmask;
188 // the type of the lenses
189 uint16_t lens_type;
190 // the version of the lens distortion data
191 uint16_t distortion_version;
192
193 union {
194 struct rift_catmull_rom_distortion_report_data lcsv_catmull_rom_10;
195 } RIFT_PACKED data;
196} RIFT_PACKED;
197
199{
200 uint16_t command;
201 uint8_t in_report;
202 uint16_t interval;
203} RIFT_PACKED;
204
205enum rift_display_mode
206{
207 RIFT_DISPLAY_MODE_GLOBAL,
208 RIFT_DISPLAY_MODE_ROLLING_TOP_BOTTOM,
209 RIFT_DISPLAY_MODE_ROLLING_LEFT_RIGHT,
210 RIFT_DISPLAY_MODE_ROLLING_RIGHT_LEFT,
211};
212
213enum rift_display_limit
214{
215 RIFT_DISPLAY_LIMIT_ACL_OFF = 0,
216 RIFT_DISPLAY_LIMIT_ACL_30 = 1,
217 RIFT_DISPLAY_LIMIT_ACL_25 = 2,
218 RIFT_DISPLAY_LIMIT_ACL_50 = 3,
219};
220
221enum rift_display_flags
222{
223 RIFT_DISPLAY_USE_ROLLING = 1 << 6,
224 RIFT_DISPLAY_REVERSE_ROLLING = 1 << 7,
225 RIFT_DISPLAY_HIGH_BRIGHTNESS = 1 << 8,
226 RIFT_DISPLAY_SELF_REFRESH = 1 << 9,
227 RIFT_DISPLAY_READ_PIXEL = 1 << 10,
228 RIFT_DISPLAY_DIRECT_PENTILE = 1 << 11,
229};
230
232{
233 uint16_t command_id;
234 // relative brightness setting independent of pixel persistence, only effective when high brightness is disabled
235 uint8_t brightness;
236 // a set of flags, ordered from LSB -> MSB
237 // - panel mode/shutter type (4 bits), read only, see rift_display_mode
238 // - current limit (2 bits), see rift_display_limit
239 // - use rolling (1 bit)
240 // - reverse rolling (1 bit), unavailable on released DK2 firmware for unknown reason
241 // - high brightness (1 bit), unavailable on released DK2 firmware for unpublished reason
242 // - self refresh (1 bit)
243 // - read pixel (1 bit)
244 // - direct pentile (1 bit)
245 uint32_t flags;
246 // the length of time in rows that the display is lit each frame, defaults to the full size of the display, full
247 // persistence
248 uint16_t persistence;
249 // the offset in rows from vsync that the panel is lit when using global shutter, no effect in rolling shutter,
250 // disabled on released DK2 firmware for unknown reason
251 uint16_t lighting_offset;
252 // the time in microseconds it is estimated for a pixel to settle to one value after it is set, read only
253 uint16_t pixel_settle;
254 // the number of rows including active area and blanking period used with persistence and lightingoffset, read
255 // only
256 uint16_t total_rows;
257} RIFT_PACKED;
258
260{
261 uint8_t data[8];
262} RIFT_PACKED;
263
265{
266 struct dk2_sensor_sample accel;
267 struct dk2_sensor_sample gyro;
268} RIFT_PACKED;
269
270#define DK2_MAX_SAMPLES 2
272{
273 uint16_t command_id;
274 uint8_t num_samples;
275 uint16_t sample_count;
276 uint16_t temperature;
277 uint32_t sample_timestamp;
278 struct dk2_sample_pack samples[DK2_MAX_SAMPLES];
279 int16_t mag_x;
280 int16_t mag_y;
281 int16_t mag_z;
282 uint16_t frame_count;
283 uint32_t frame_timestamp;
284 uint8_t frame_id;
285 uint8_t tracking_pattern;
286 uint16_t tracking_count;
287 uint32_t tracking_timestamp;
288} RIFT_PACKED;
289
290#if defined(_MSC_VER)
291#pragma pack(pop)
292#endif
293
295{
296 // the k coeffecients of the distortion
297 float k[CATMULL_COEFFICIENTS];
298 float max_r;
299 float meters_per_tan_angle_at_center;
300 float chromatic_abberation[CHROMATIC_ABBERATION_COEFFEICENT_COUNT];
301};
302
304{
305 // the version of the lens distortion data
306 uint16_t distortion_version;
307 // eye relief setting, in meters from surface of lens
308 float eye_relief;
309
310 union {
311 struct rift_catmull_rom_distortion_data lcsv_catmull_rom_10;
312 } RIFT_PACKED data;
313};
314
316{
317 struct xrt_vec2 scale;
318 struct xrt_vec2 offset;
319};
320
322{
323 float up_tan;
324 float down_tan;
325 float left_tan;
326 float right_tan;
327};
328
330{
331 // gap left between the two eyes
332 float screen_gap_meters;
333 // the diameter of the lenses, may need to be extended to an array
334 float lens_diameter_meters;
335 // ipd of the headset
336 float icd;
337
338 // the fov of the headset
339 struct rift_viewport_fov_tan fov;
340 // mapping from tan-angle space to target NDC space
341 struct rift_scale_and_offset eye_to_source_ndc;
342 struct rift_scale_and_offset eye_to_source_uv;
343};
344
345enum rift_variant
346{
347 RIFT_VARIANT_DK1,
348 RIFT_VARIANT_DK2,
349};
350
351#define OCULUS_VR_VID 0x2833
352
353#define OCULUS_DK2_PID 0x0021
354
355/*!
356 * Probing function for Oculus Rift devices.
357 *
358 * @ingroup drv_rift
359 * @see xrt_prober_found_func_t
360 */
361int
362rift_found(struct xrt_prober *xp,
363 struct xrt_prober_device **devices,
364 size_t device_count,
365 size_t index,
366 cJSON *attached_data,
367 struct xrt_device **out_xdev);
368
369/*!
370 * A rift HMD device.
371 *
372 * @implements xrt_device
373 */
375{
376 struct xrt_device base;
377
378 struct xrt_pose pose;
379
380 enum u_logging_level log_level;
381
382 // has built-in mutex so thread safe
383 struct m_relation_history *relation_hist;
384
385 struct os_hid_device *hid_dev;
386 struct os_thread_helper sensor_thread;
387 bool processed_sample_packet;
388 uint32_t last_remote_sample_time_us;
389 int64_t last_remote_sample_time_ns;
390
391 struct m_imu_3dof fusion;
392 struct m_clock_windowed_skew_tracker *clock_tracker;
393
394 int64_t last_keepalive_time;
395 enum rift_variant variant;
396 struct rift_config_report config;
398
399 struct rift_lens_distortion *lens_distortions;
400 uint16_t num_lens_distortions;
401 uint16_t distortion_in_use;
402
403 struct rift_extra_display_info extra_display_info;
404};
405
406/// Casting helper function
407static inline struct rift_hmd *
408rift_hmd(struct xrt_device *xdev)
409{
410 return (struct rift_hmd *)xdev;
411}
412
413struct rift_hmd *
414rift_hmd_create(struct os_hid_device *dev, enum rift_variant variant, char *device_name, char *serial_number);
415
416/*!
417 * @dir drivers/rift
418 *
419 * @brief @ref drv_rift files.
420 */
421
422#ifdef __cplusplus
423}
424#endif
u_logging_level
Logging level enum.
Definition: u_logging.h:44
C interface to math library.
A IMU fusion specially made for 3dof devices.
Wrapper header for <math.h> to ensure pi-related math constants are defined.
Wrapper around OS native hid functions.
Wrapper around OS threading native functions.
int rift_found(struct xrt_prober *xp, struct xrt_prober_device **devices, size_t device_count, size_t index, cJSON *attached_data, struct xrt_device **out_xdev)
Probing function for Oculus Rift devices.
Definition: rift_prober.c:19
static struct rift_hmd * rift_hmd(struct xrt_device *xdev)
Casting helper function.
Definition: rift_interface.h:408
Definition: oh_device.c:483
Definition: rift_interface.h:272
Definition: rift_interface.h:199
Definition: rift_interface.h:265
Definition: rift_interface.h:260
Definition: m_space.cpp:87
Definition: m_clock_tracking.c:35
Definition: m_imu_3dof.h:35
Definition: m_relation_history.cpp:50
Representing a single hid interface on a device.
Definition: os_hid.h:29
All in one helper that handles locking, waiting for change and starting a thread.
Definition: os_threading.h:453
Definition: rift_interface.h:295
Definition: rift_interface.h:168
Definition: rift_interface.h:138
Definition: rift_interface.h:148
Definition: rift_interface.h:232
Definition: rift_interface.h:330
A rift HMD device.
Definition: rift_interface.h:375
Definition: rift_interface.h:180
Definition: rift_interface.h:304
Definition: rift_interface.h:316
Definition: rift_interface.h:322
A single HMD or input device.
Definition: xrt_device.h:281
A pose composed of a position and orientation.
Definition: xrt_defines.h:467
A probed device, may or may not be opened.
Definition: xrt_prober.h:85
The main prober that probes and manages found but not opened HMD devices that are connected to the sy...
Definition: xrt_prober.h:132
A 2 element vector with single floats.
Definition: xrt_defines.h:252
Misc helpers for device drivers.
Basic logging functionality.
Common defines and enums for XRT.
Header defining an xrt display or controller device.
Common interface to probe for devices.