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