Monado OpenXR Runtime
Loading...
Searching...
No Matches
rift_internal.h
Go to the documentation of this file.
1// Copyright 2025, Beyley Cardellio
2// Copyright 2026, NVIDIA CORPORATION.
3// SPDX-License-Identifier: BSL-1.0
4/*!
5 * @file
6 * @brief Interface to Oculus Rift driver code.
7 * @author Beyley Cardellio <ep1cm1n10n123@gmail.com>
8 * @ingroup drv_rift
9 */
10
11#pragma once
12
13#include "xrt/xrt_byte_order.h"
14
15#include "util/u_device.h"
16#include "util/u_logging.h"
17
18#include "math/m_imu_3dof.h"
19#include "math/m_api.h"
20#include "math/m_mathinclude.h"
22#include "math/m_filter_fifo.h"
23
24#include "tracking/t_imu.h"
26
27#include "os/os_hid.h"
28#include "os/os_threading.h"
29
31
32#include <stdlib.h>
33#include <stdio.h>
34#include <assert.h>
35
36#include "rift_interface.h"
37
38
39#define HMD_TRACE(hmd, ...) U_LOG_XDEV_IFL_T(&hmd->base, hmd->log_level, __VA_ARGS__)
40#define HMD_DEBUG(hmd, ...) U_LOG_XDEV_IFL_D(&hmd->base, hmd->log_level, __VA_ARGS__)
41#define HMD_INFO(hmd, ...) U_LOG_XDEV_IFL_I(&hmd->base, hmd->log_level, __VA_ARGS__)
42#define HMD_WARN(hmd, ...) U_LOG_XDEV_IFL_W(&hmd->base, hmd->log_level, __VA_ARGS__)
43#define HMD_ERROR(hmd, ...) U_LOG_XDEV_IFL_E(&hmd->base, hmd->log_level, __VA_ARGS__)
44
45#define REPORT_MAX_SIZE 69 // max size of a feature report (FEATURE_REPORT_CALIBRATE)
46#define KEEPALIVE_INTERVAL_NS 10000000000 // 10 seconds
47// give a 5% breathing room (at 10 seconds, this is 500 milliseconds of breathing room)
48#define KEEPALIVE_SEND_RATE_NS ((KEEPALIVE_INTERVAL_NS * 19) / 20)
49#define IMU_SAMPLE_RATE (1000) // 1000hz
50#define NS_PER_SAMPLE (1000 * 1000) // 1ms (1,000,000 ns) per sample
51#define SERIAL_NUMBER_LENGTH 14
52
53#define CALIBRATION_HASH_BYTE_OFFSET 0x1bf0
54#define CALIBRATION_HASH_BYTE_LENGTH 0x10
55
56#define RIFT_CONFIG_SUBDIR "rift"
57
58#define CALIBRATION_HEADER_BYTE_OFFSET 0x0
59#define CALIBRATION_HEADER_BYTE_LENGTH 0x4
60
61#define CALIBRATION_BODY_BYTE_OFFSET 0x4
62#define CALIBRATION_BODY_BYTE_CHUNK_LENGTH 0x14
63
64#define MICROMETERS_TO_METERS(microns) ((float)microns / 1000000.0f)
65
66// value taken from LibOVR 0.4.4
67#define DEFAULT_EXTRA_EYE_ROTATION DEG_TO_RAD(30.0f)
68
69#define IN_REPORT_DK2 11 // sent on the HMD HID interface
70#define IN_REPORT_RADIO_DATA 12 // sent on the radio HID interface
71#define IN_REPORT_CV1_RADIO_KEEPALIVE 13 // sent on the HMD HID interface when no devices are connected
72
73#define IN_REPORT_RADIO_DATA_SIZE 64
74
75#ifdef __cplusplus
76extern "C" {
77#endif
78
79// asserts the size of a type is equal to the byte size provided
80#define SIZE_ASSERT(type, size) \
81 static_assert(sizeof(type) == (size), "Size of " #type " is not " #size " bytes as was expected")
82
83enum rift_feature_reports
84{
85 // DK1
86 FEATURE_REPORT_CONFIG = 2, // get + set
87 FEATURE_REPORT_CALIBRATE = 3, // get + set
88 FEATURE_REPORT_RANGE = 4, // get + set
89 FEATURE_REPORT_REGISTER = 5, // get + set
90 FEATURE_REPORT_DFU = 6, // get + set
91 FEATURE_REPORT_DK1_KEEP_ALIVE = 8, // get + set
92 FEATURE_REPORT_DISPLAY_INFO = 9, // get + set
93 FEATURE_REPORT_SERIAL = 10, // get + set
94
95 // DK2
96 FEATURE_REPORT_TRACKING = 12, // get + set
97 FEATURE_REPORT_DISPLAY = 13, // get + set
98 FEATURE_REPORT_MAG_CALIBRATION = 14, // get + set
99 FEATURE_REPORT_POS_CALIBRATION = 15, // get + set
100 FEATURE_REPORT_CUSTOM_PATTERN = 16, // get + set
101 FEATURE_REPORT_KEEPALIVE_MUX = 17, // get + set
102 FEATURE_REPORT_MANUFACTURING = 18, // get + set
103 FEATURE_REPORT_UUID = 19, // get + set
104 FEATURE_REPORT_TEMPERATURE = 20, // get + set
105 FEATURE_REPORT_GYROOFFSET = 21, // get only
106 FEATURE_REPORT_LENS_DISTORTION = 22, // get + set
107
108 // CV1
109 FEATURE_REPORT_RADIO_CONTROL = 26, // get + set
110 FEATURE_REPORT_RADIO_READ_DATA_CMD = 27, // @todo: get + ???
111 FEATURE_REPORT_ENABLE_COMPONENTS = 29, // @todo: ??? + set
112};
113
114enum rift_config_report_flags
115{
116 // output the sample data raw from the sensors without converting them to known units
117 RIFT_CONFIG_REPORT_USE_RAW = 1,
118 // internal test mode for calibrating zero rate drift on gyro
119 RIFT_CONFIG_REPORT_INTERNAL_CALIBRATION = 1 << 1,
120 // use the calibration parameters stored on the device
121 RIFT_CONFIG_REPORT_USE_CALIBRATION = 1 << 2,
122 // recalibrate the gyro zero rate offset when the device is stationary
123 RIFT_CONFIG_REPORT_AUTO_CALIBRATION = 1 << 3,
124 // stop sending IN reports when the device has stopped moving for Interval milliseconds
125 RIFT_CONFIG_REPORT_MOTION_KEEP_ALIVE = 1 << 4,
126 // stop sending IN reports when the device has stopped receiving feature reports for Interval milliseconds
127 RIFT_CONFIG_REPORT_COMMAND_KEEP_ALIVE = 1 << 5,
128 // output the IN report data in the coordinate system used by LibOVR relative to the tracker, otherwise, report
129 // in the coordinate system of the device
130 RIFT_CONFIG_REPORT_USE_SENSOR_COORDINATES = 1 << 6,
131 // override the power state of the USB hub, forcing it to act as if the external power source is connected (DK2
132 // only, does nothing on DK1)
133 RIFT_CONFIG_REPORT_OVERRIDE_POWER = 1 << 7,
134};
135
136enum rift_distortion_type
137{
138 RIFT_DISTORTION_TYPE_DIMS = 1,
139 RIFT_DISTORTION_TYPE_K = 2,
140};
141
142enum rift_lens_type
143{
144 // firmware indirectly states lens type A is 0
145 RIFT_LENS_TYPE_A = 0,
146 // firmware does not state what lens type B is, 1 is an educated guess
147 RIFT_LENS_TYPE_B = 1,
148};
149
150enum rift_lens_distortion_version
151{
152 // no distortion data is stored
153 RIFT_LENS_DISTORTION_NONE = 0,
154 // standard distortion matrix
155 RIFT_LENS_DISTORTION_LCSV_CATMULL_ROM_10_VERSION_1 = 1,
156};
157
158enum rift_component_flags
159{
160 RIFT_COMPONENT_DISPLAY = 1 << 0,
161 RIFT_COMPONENT_AUDIO = 1 << 1,
162 RIFT_COMPONENT_LEDS = 1 << 2,
163};
164
165/*
166 *
167 * Packed structs for USB communication
168 *
169 */
170
171#pragma pack(push, 1)
172
174{
175 uint16_t command_id;
176 uint8_t config_flags;
177 // the IN report rate of the headset, rate is calculated as `sample_rate / (1 + interval)`
178 uint8_t interval;
179 // sample rate of the IMU, always 1000hz on DK1/DK2, read-only
180 uint16_t sample_rate;
181};
182
183SIZE_ASSERT(struct rift_config_report, 6);
184
186{
187 uint16_t command_id;
188 uint8_t distortion_type;
189 // the horizontal resolution of the display, in pixels
190 uint16_t resolution_x;
191 // the vertical resolution of the display, in pixels
192 uint16_t resolution_y;
193 // width in micrometers
194 uint32_t display_width;
195 // height in micrometers
196 uint32_t display_height;
197 // the vertical center of the display, in micrometers
198 uint32_t center_v;
199 // the separation between the two lenses, in micrometers
200 uint32_t lens_separation;
201 uint32_t lens_distance[2];
202 float distortion[6];
203};
204
205SIZE_ASSERT(struct rift_display_info_report, 55);
206
207#define CATMULL_COEFFICIENTS 11
208#define CHROMATIC_ABBERATION_COEFFEICENT_COUNT 4
209
211{
212 // eye relief setting, in micrometers from front surface of lens
213 uint16_t eye_relief;
214 // the k coeffecients of the distortion
215 uint16_t k[CATMULL_COEFFICIENTS];
216 uint16_t max_r;
217 uint16_t meters_per_tan_angle_at_center;
218 uint16_t chromatic_abberation[CHROMATIC_ABBERATION_COEFFEICENT_COUNT];
219 uint8_t unused[14];
220};
221
222SIZE_ASSERT(struct rift_catmull_rom_distortion_report_data, 50);
223
225{
226 uint16_t command_id;
227 // the amount of distortions on this device
228 uint8_t num_distortions;
229 // the index of this distortion in the devices array
230 uint8_t distortion_idx;
231 // unused bitmask field
232 uint8_t bitmask;
233 // the type of the lenses
234 uint16_t lens_type;
235 // the version of the lens distortion data
236 uint16_t distortion_version;
237
238 union {
239 struct rift_catmull_rom_distortion_report_data lcsv_catmull_rom_10;
240 } data;
241};
242
243SIZE_ASSERT(struct rift_lens_distortion_report, 9 + sizeof(struct rift_catmull_rom_distortion_report_data));
244
245enum rift_position_calibration_version
246{
247 // no data stored
248 RIFT_POSITION_CALIBRATION_VERSION_NONE = 0,
249 // hard-coded default positions
250 RIFT_POSITION_CALIBRATION_VERSION_DEFAULT = 1,
251 // factory calibrated
252 RIFT_POSITION_CALIBRATION_VERSION_FACTORY = 2,
253 // user calibrated
254 RIFT_POSITION_CALIBRATION_VERSION_USER = 3,
255};
256
257enum rift_position_calibration_type
258{
259 RIFT_POSITION_CALIBRATION_TYPE_LED = 0,
260 RIFT_POSITION_CALIBRATION_TYPE_INERTIAL_SENSOR = 1,
261};
262
264{
265 uint16_t command_id;
266 // the version/type of calibration, see rift_position_calibration_version
267 uint8_t version;
268 // the x/y/z position of the object, this is a signed integer in micrometers, position is relative to the center
269 // of the emitter plane of the display at nominal focus.
270 int32_t position[3];
271 // the x/y/z axis normal of the object, this is a signed integer in micrometers, normal is relative to the
272 // position
273 int16_t normal[3];
274 // rotation around the normal, in units of 10^-4 radians
275 uint16_t rotation;
276 // the current position in the array of LEDs, increments on reads, gets set to the value on writes
277 uint16_t position_index;
278 // read-only value of the number of LEDs
279 uint16_t position_count;
280 // the type of the object being described, see rift_position_calibration_type
281 uint16_t position_type;
282};
283
284SIZE_ASSERT(struct rift_position_calibration_report, 29);
285
286enum rift_custom_pattern_state
287{
288 RIFT_CUSTOM_PATTERN_STAT_OFF = 0,
289 RIFT_CUSTOM_PATTERN_STAT_LOW = 1,
290 RIFT_CUSTOM_PATTERN_STAT_HIGH = 3,
291};
292
294{
295 uint16_t command_id;
296 // the length of the sequence that each LED goes through
297 uint8_t sequence_length;
298 // the sequence the specific LED goes through, 2 bits per state, 0 (off), 1 (low), and 3 (high), ordered from
299 // LSB to MSB
300 uint32_t sequence;
301 // the current LED being described, increments on reads, gets set to the value on writes
302 uint16_t led_index;
303 // the number of tracking LEDs present on the device
304 uint16_t led_count;
305};
306
307SIZE_ASSERT(struct rift_custom_pattern_report, 11);
308
310{
311 uint16_t command;
312 uint8_t in_report;
313 uint16_t interval;
314};
315
316SIZE_ASSERT(struct rift_dk2_keepalive_mux_report, 5);
317
318enum rift_display_mode
319{
320 RIFT_DISPLAY_MODE_GLOBAL,
321 RIFT_DISPLAY_MODE_ROLLING_TOP_BOTTOM,
322 RIFT_DISPLAY_MODE_ROLLING_LEFT_RIGHT,
323 RIFT_DISPLAY_MODE_ROLLING_RIGHT_LEFT,
324};
325
326enum rift_display_limit
327{
328 RIFT_DISPLAY_LIMIT_ACL_OFF = 0,
329 RIFT_DISPLAY_LIMIT_ACL_30 = 1,
330 RIFT_DISPLAY_LIMIT_ACL_25 = 2,
331 RIFT_DISPLAY_LIMIT_ACL_50 = 3,
332};
333
334enum rift_display_flags
335{
336 RIFT_DISPLAY_USE_ROLLING = 1 << 6,
337 RIFT_DISPLAY_REVERSE_ROLLING = 1 << 7,
338 RIFT_DISPLAY_HIGH_BRIGHTNESS = 1 << 8,
339 RIFT_DISPLAY_SELF_REFRESH = 1 << 9,
340 RIFT_DISPLAY_READ_PIXEL = 1 << 10,
341 RIFT_DISPLAY_DIRECT_PENTILE = 1 << 11,
342};
343
345{
346 uint16_t command_id;
347 // relative brightness setting independent of pixel persistence, only effective when high brightness is disabled
348 uint8_t brightness;
349 // a set of flags, ordered from LSB -> MSB
350 // - panel mode/shutter type (4 bits), read only, see rift_display_mode
351 // - current limit (2 bits), see rift_display_limit
352 // - use rolling (1 bit)
353 // - reverse rolling (1 bit), unavailable on released DK2 firmware for unknown reason
354 // - high brightness (1 bit), unavailable on released DK2 firmware for unpublished reason
355 // - self refresh (1 bit)
356 // - read pixel (1 bit)
357 // - direct pentile (1 bit)
358 uint32_t flags;
359 // the length of time in rows that the display is lit each frame, defaults to the full size of the display, full
360 // persistence
361 uint16_t persistence;
362 // the offset in rows from vsync that the panel is lit when using global shutter, no effect in rolling shutter,
363 // disabled on released DK2 firmware for unknown reason
364 uint16_t lighting_offset;
365 // the time in microseconds it is estimated for a pixel to settle to one value after it is set, read only
366 uint16_t pixel_settle;
367 // the number of rows including active area and blanking period used with persistence and lightingoffset, read
368 // only
369 uint16_t total_rows;
370};
371
372SIZE_ASSERT(struct rift_display_report, 15);
373
375{
376 uint8_t data[8];
377};
378
379SIZE_ASSERT(struct rift_dk2_sensor_sample, 8);
380
382{
383 struct rift_dk2_sensor_sample accel;
384 struct rift_dk2_sensor_sample gyro;
385};
386
387SIZE_ASSERT(struct rift_dk2_sample_pack, sizeof(struct rift_dk2_sensor_sample) * 2);
388
390{
391 int16_t mag_x;
392 int16_t mag_y;
393 int16_t mag_z;
394};
395
396SIZE_ASSERT(struct rift_dk2_version_data, 6);
397
399{
400 uint16_t presence_sensor;
401 uint16_t iad_adc_value;
402 uint16_t unk;
403};
404
405SIZE_ASSERT(struct rift_cv1_version_data, 6);
406static_assert(sizeof(struct rift_cv1_version_data) == sizeof(struct rift_dk2_version_data),
407 "Incorrect version data size");
408
409#define DK2_MAX_SAMPLES 2
411{
412 uint16_t command_id;
413 uint8_t num_samples;
414 uint16_t sample_count;
415 uint16_t temperature;
416 uint32_t sample_timestamp;
417 struct rift_dk2_sample_pack samples[DK2_MAX_SAMPLES];
418 union {
419 struct rift_dk2_version_data dk2;
420 struct rift_cv1_version_data cv1;
421 };
422 uint16_t frame_count;
423 uint32_t frame_timestamp;
424 uint8_t frame_id;
425 uint8_t tracking_pattern;
426 uint16_t tracking_count;
427 uint32_t tracking_timestamp;
428};
429
430SIZE_ASSERT(struct dk2_in_report, 63);
431
433{
434 uint16_t command_id;
435 // which components to enable, see rift_component_flags
436 uint8_t flags;
437};
438
439SIZE_ASSERT(struct rift_enable_components_report, 3);
440
442{
443 uint16_t command_id;
444 struct rift_dk2_sample_pack offset;
445 struct rift_dk2_sample_pack matrix_samples[3];
446 uint16_t temperature;
447};
448
449SIZE_ASSERT(struct rift_imu_calibration_report, sizeof(struct rift_dk2_sample_pack) * 4 + 4);
450
451enum rift_radio_read_cmd
452{
453 RIFT_RADIO_READ_CMD_FLASH_CONTROL = 0x0a,
454 RIFT_RADIO_READ_CMD_SERIAL = 0x88,
455};
456
458{
459 uint16_t command_id;
460 uint8_t a;
461 uint8_t b;
462 uint8_t c;
463};
464
465SIZE_ASSERT(struct rift_radio_cmd_report, 5);
466
468{
469 uint16_t command_id;
470 uint16_t offset;
471 uint16_t length;
472 uint8_t unk[28];
473};
474
475SIZE_ASSERT(struct rift_radio_data_read_cmd, 34);
476
478{
479 uint8_t unk[5];
480 __le16 data_length;
481};
482SIZE_ASSERT(struct rift_radio_flash_read_response_header, 7);
483
485{
486 uint16_t command_id;
487 uint8_t radio_address[5];
488};
489
490SIZE_ASSERT(struct rift_radio_address_radio_report, 7);
491
492enum rift_radio_report_remote_button_masks
493{
494 RIFT_REMOTE_BUTTON_MASK_DPAD_UP = 0x001,
495 RIFT_REMOTE_BUTTON_MASK_DPAD_DOWN = 0x002,
496 RIFT_REMOTE_BUTTON_MASK_DPAD_LEFT = 0x004,
497 RIFT_REMOTE_BUTTON_MASK_DPAD_RIGHT = 0x008,
498 RIFT_REMOTE_BUTTON_MASK_SELECT = 0x010,
499 RIFT_REMOTE_BUTTON_MASK_VOLUME_UP = 0x020,
500 RIFT_REMOTE_BUTTON_MASK_VOLUME_DOWN = 0x040,
501 RIFT_REMOTE_BUTTON_MASK_OCULUS = 0x080,
502 RIFT_REMOTE_BUTTON_MASK_BACK = 0x100,
503};
504
506{
507 // the button state of the controller, see rift_radio_report_remote_button_masks
508 uint16_t buttons;
509};
510
511SIZE_ASSERT(struct rift_radio_report_remote_message, 2);
512
513enum rift_radio_report_touch_buttons
514{
515 RIFT_TOUCH_CONTROLLER_BUTTON_A = 0x01,
516 RIFT_TOUCH_CONTROLLER_BUTTON_X = 0x01,
517 RIFT_TOUCH_CONTROLLER_BUTTON_B = 0x02,
518 RIFT_TOUCH_CONTROLLER_BUTTON_Y = 0x02,
519 RIFT_TOUCH_CONTROLLER_BUTTON_MENU = 0x04,
520 RIFT_TOUCH_CONTROLLER_BUTTON_OCULUS = 0x04,
521 RIFT_TOUCH_CONTROLLER_BUTTON_STICK = 0x08,
522};
523
524enum rift_radio_report_adc_channel
525{
526 RIFT_TOUCH_CONTROLLER_ADC_STICK = 0x01,
527 RIFT_TOUCH_CONTROLLER_ADC_B_Y = 0x02,
528 RIFT_TOUCH_CONTROLLER_ADC_TRIGGER = 0x03,
529 RIFT_TOUCH_CONTROLLER_ADC_A_X = 0x04,
530 RIFT_TOUCH_CONTROLLER_ADC_THUMBREST = 0x08,
531 // seen with values varying per controller, maybe power draw? temperature? my left controller while powered on
532 // had the value slowly rise from 2800 to 3000 over the span of a couple minutes, dunno what that could be tbh
533 RIFT_TOUCH_CONTROLLER_ADC_UNK1 = 0x20,
534 RIFT_TOUCH_CONTROLLER_ADC_BATTERY = 0x21,
535 RIFT_TOUCH_CONTROLLER_ADC_HAPTIC_COUNTER = 0x23,
536};
537
539{
540 uint32_t timestamp;
541 int16_t accel[3];
542 int16_t gyro[3];
543 uint8_t buttons;
544 uint8_t touch_grip_stick_state[5];
545 // see rift_radio_report_adc_channel
546 uint8_t adc_channel;
547 uint16_t adc_value;
548};
549
550SIZE_ASSERT(struct rift_radio_report_touch_message, 25);
551
552enum rift_radio_device_type
553{
554 RIFT_RADIO_DEVICE_REMOTE = 1,
555 RIFT_RADIO_DEVICE_LEFT_TOUCH = 2,
556 RIFT_RADIO_DEVICE_RIGHT_TOUCH = 3,
557 RIFT_RADIO_DEVICE_TRACKED_OBJECT = 6,
558};
559
561{
562 uint16_t flags;
563 // the type of device sending the message, see rift_radio_device_type
564 uint8_t device_type;
565 union {
568 };
569};
570
571SIZE_ASSERT(struct rift_radio_report_message, 3 + sizeof(struct rift_radio_report_touch_message));
572
574{
575 uint16_t command_id;
576 struct rift_radio_report_message messages[2];
577};
578
579enum rift_tracking_flags
580{
581 // enable the tracking LED exposure and updating
582 RIFT_TRACKING_ENABLE = 1 << 0,
583 // automatically increment the pattern index after each exposure
584 RIFT_TRACKING_AUTO_INCREMENT = 1 << 1,
585 // modulate the tracking LEDs at 85kHz to allow wireless sync, defaults to on
586 RIFT_TRACKING_USE_CARRIER = 1 << 2,
587 // trigger LED exposure using a rising edge of GPIO1, else triggered on a timer
588 RIFT_TRACKING_SYNC_INPUT = 1 << 3,
589 // trigger LED exposure on each vsync rather than an internal or external timer
590 RIFT_TRACKING_VSYNC_LOCK = 1 << 4,
591 // use the custom pattern given to the headset
592 RIFT_TRACKING_CUSTOM_PATTERN = 1 << 5,
593};
594
596{
597 uint16_t command_id;
598 // the index of the current pattern being flashed, pattern 255 is reserved for "all high"
599 uint8_t pattern_idx;
600 // the enabled tracking flags, see rift_tracking_flags
601 uint16_t flags;
602 // the amount of time to enable the LEDs for during an exposure, sync output also follows this length, cannot be
603 // longer than frame_interval, and has a minimum of 10 microseconds
604 uint16_t exposure_length;
605 // when SYNCINPUT and VSYNC_LOCK are false, the tracking LEDs are exposed on the interval set here, in
606 // microseconds
607 uint16_t frame_interval;
608 // when VSYNC_LOCK is true, this gives a fixed microsecond offset from the vsync to when the LEDs are triggered
609 uint16_t vsync_offset;
610 // the duty cycle of the 85kHz modulation, defaults to 128, resulting in a 50% duty cycle
611 uint8_t duty_cycle;
612};
613
614SIZE_ASSERT(struct rift_tracking_report, 12);
615
616#pragma pack(pop)
617
618/*
619 *
620 * Parsed structs for internal use
621 *
622 */
623
625{
626 // the k coeffecients of the distortion
627 float k[CATMULL_COEFFICIENTS];
628 float max_r;
629 float meters_per_tan_angle_at_center;
630 float chromatic_abberation[CHROMATIC_ABBERATION_COEFFEICENT_COUNT];
631};
632
634{
635 // the version of the lens distortion data
636 uint16_t distortion_version;
637 // eye relief setting, in meters from surface of lens
638 float eye_relief;
639
640 union {
641 struct rift_catmull_rom_distortion_data lcsv_catmull_rom_10;
642 } data;
643};
644
646{
647 struct xrt_vec2 scale;
648 struct xrt_vec2 offset;
649};
650
652{
653 float up_tan;
654 float down_tan;
655 float left_tan;
656 float right_tan;
657};
658
660{
661 // gap left between the two eyes
662 float screen_gap_meters;
663 // the diameter of the lenses, may need to be extended to an array
664 float lens_diameter_meters;
665 // ipd of the headset
666 float icd;
667
668 // the fov of the headset
669 struct rift_viewport_fov_tan fov;
670 // mapping from tan-angle space to target NDC space
671 struct rift_scale_and_offset eye_to_source_ndc;
672 struct rift_scale_and_offset eye_to_source_uv;
673};
674
676{
677 struct xrt_vec3 gyro_offset;
678 struct xrt_vec3 accel_offset;
679 struct xrt_matrix_3x3 gyro_matrix;
680 struct xrt_matrix_3x3 accel_matrix;
681 float temperature;
682};
683
684enum rift_touch_controller_input
685{
686 // left
687 RIFT_TOUCH_CONTROLLER_INPUT_X_CLICK = 0,
688 RIFT_TOUCH_CONTROLLER_INPUT_X_TOUCH = 1,
689 RIFT_TOUCH_CONTROLLER_INPUT_Y_CLICK = 2,
690 RIFT_TOUCH_CONTROLLER_INPUT_Y_TOUCH = 3,
691 RIFT_TOUCH_CONTROLLER_INPUT_SYSTEM_CLICK = 4,
692 // right
693 RIFT_TOUCH_CONTROLLER_INPUT_A_CLICK = 0,
694 RIFT_TOUCH_CONTROLLER_INPUT_A_TOUCH = 1,
695 RIFT_TOUCH_CONTROLLER_INPUT_B_CLICK = 2,
696 RIFT_TOUCH_CONTROLLER_INPUT_B_TOUCH = 3,
697 RIFT_TOUCH_CONTROLLER_INPUT_MENU_CLICK = 4,
698 // both
699 RIFT_TOUCH_CONTROLLER_INPUT_SQUEEZE_VALUE = 5,
700 RIFT_TOUCH_CONTROLLER_INPUT_TRIGGER_TOUCH = 6,
701 RIFT_TOUCH_CONTROLLER_INPUT_TRIGGER_VALUE = 7,
702 RIFT_TOUCH_CONTROLLER_INPUT_THUMBSTICK_CLICK = 8,
703 RIFT_TOUCH_CONTROLLER_INPUT_THUMBSTICK_TOUCH = 9,
704 RIFT_TOUCH_CONTROLLER_INPUT_THUMBSTICK = 10,
705 RIFT_TOUCH_CONTROLLER_INPUT_THUMBREST_TOUCH = 11,
706 RIFT_TOUCH_CONTROLLER_INPUT_GRIP_POSE = 12,
707 RIFT_TOUCH_CONTROLLER_INPUT_AIM_POSE = 13,
708 RIFT_TOUCH_CONTROLLER_INPUT_TRIGGER_PROXIMITY = 14,
709 RIFT_TOUCH_CONTROLLER_INPUT_THUMB_PROXIMITY = 15,
710 RIFT_TOUCH_CONTROLLER_INPUT_COUNT = 16,
711};
712
714{
715 struct xrt_vec3 position;
716 struct xrt_vec3 normal;
717 struct xrt_vec3 angles;
718};
719
721{
722 uint16_t joy_x_range[2];
723 uint16_t joy_x_dead[2];
724 uint16_t joy_y_range[2];
725 uint16_t joy_y_dead[2];
726
727 // min - mid - max
728 uint16_t trigger_range[3];
729
730 // min - mid - max
731 uint16_t middle_range[3];
732 bool middle_flipped;
733
734 uint16_t cap_sense_min[8];
735 uint16_t cap_sense_touch[8];
736
737 float gyro_calibration[3][3];
738 struct xrt_vec3 gyro_offset;
739 float accel_calibration[3][3];
740 struct xrt_vec3 accel_offset;
741
742 struct xrt_vec3 imu_position;
743
744 size_t num_leds;
745 struct rift_touch_controller_led *leds;
746};
747
749{
750 uint8_t buttons;
751 float trigger;
752 float grip;
753 struct xrt_vec2 stick;
754 uint8_t haptic_counter;
755 float cap_stick;
756 float cap_b_y;
757 float cap_a_x;
758 float cap_trigger;
759 float cap_thumbrest;
760};
761
762/*!
763 * A Rift Touch controller device.
764 *
765 * @implements xrt_device
766 */
768{
769 struct xrt_device base;
770 struct xrt_frame_node node;
771
772 struct rift_hmd *hmd;
773
774 enum rift_radio_device_type device_type;
775
776 struct
777 {
778 bool mutex_created;
779 struct os_mutex mutex;
780
782
783 xrt_atomic_s32_t battery_status;
784
785 uint32_t last_device_remote_us;
786 timepoint_ns device_remote_ns;
787 timepoint_ns device_local_ns;
788
789 struct imu_fusion *imu_fusion;
790 struct xrt_imu_sample last_imu_sample;
791
792 struct m_clock_windowed_skew_tracker *clock_tracker;
793
794 bool calibration_read;
795 struct rift_touch_controller_calibration calibration;
796
797 struct
798 {
799 timepoint_ns end_time_ns;
800 bool high_freq;
801 float amplitude;
802
803 bool set_enabled;
804 float set_amplitude;
805 bool set_high_freq;
806 } haptic;
807 } input;
808
809 //! Locked by radio_state.thread
810 struct
811 {
812 bool serial_valid;
813
814 uint8_t calibration_hash[CALIBRATION_HASH_BYTE_LENGTH];
815
816 uint8_t calibration_data_buffer[CALIBRATION_BODY_BYTE_CHUNK_LENGTH];
817
818 uint8_t *calibration_body_json;
819 uint16_t calibration_body_json_length;
820
822};
823
824enum rift_remote_inputs
825{
826 RIFT_REMOTE_INPUT_DPAD_UP,
827 RIFT_REMOTE_INPUT_DPAD_DOWN,
828 RIFT_REMOTE_INPUT_DPAD_LEFT,
829 RIFT_REMOTE_INPUT_DPAD_RIGHT,
830 RIFT_REMOTE_INPUT_SELECT,
831 RIFT_REMOTE_INPUT_VOLUME_UP,
832 RIFT_REMOTE_INPUT_VOLUME_DOWN,
833 RIFT_REMOTE_INPUT_BACK,
834 RIFT_REMOTE_INPUT_OCULUS,
835 RIFT_REMOTE_INPUT_COUNT,
836};
837
838/*!
839 * A Rift Remote device.
840 *
841 * @implements xrt_device
842 */
844{
845 struct xrt_device base;
846 struct xrt_frame_node node;
847
848 //! The button state of the remote, stored as an atomic to avoid needing a mutex.
849 xrt_atomic_s32_t buttons;
850
851 //! Locked by radio_state.thread
853};
854
855enum rift_radio_command
856{
857 RIFT_RADIO_COMMAND_NONE = 0,
858 RIFT_RADIO_COMMAND_READ_SERIAL,
859 RIFT_RADIO_COMMAND_READ_FLASH,
860 RIFT_RADIO_COMMAND_SEND_HAPTICS,
861};
862
864{
865 //! A pointer to store the serial string. Must contain at least SERIAL_NUMBER_LENGTH bytes.
866 char *serial;
867 //! A pointer to store when reading the serial was successful.
869};
870
871typedef int (*flash_read_callback_t)(void *user_data, uint16_t address, uint16_t length);
872
874{
875 void *user_data;
876
877 uint16_t address;
878 uint16_t length;
879
880 uint8_t *buffer;
881
882 flash_read_callback_t read_callback;
883};
884
886 struct rift_radio_command_data_read_serial read_serial;
887 struct rift_radio_command_data_read_flash read_flash;
888};
889
890//! How many past exposures a frame can be matched against. At ~60 Hz this is a little over a quarter second.
891#define RIFT_EXPOSURE_HISTORY_SIZE 16
892
893//! One camera exposure the HMD told us about, held so that late frames can still find the exposure they belong to.
895{
896 //! The value of rift_hmd::exposure_counter at this exposure.
897 uint32_t sequence;
898 //! When the exposure started, in local monotonic time. This is what frames matched to it are timestamped with.
900 /*!
901 * When the IN report announcing this exposure arrived, in local monotonic time.
902 *
903 * Frames are matched against this rather than against @ref timestamp_ns. Both the report and the frame have
904 * travelled over USB before we see them, so their arrival times share most of that delay and land near each
905 * other; the exposure instant on the HMD's own clock is a good deal earlier than either.
906 */
908};
909
910/*!
911 * A rift HMD device.
912 *
913 * @implements xrt_device
914 * @implements t_constellation_tracker_device
915 * @implements t_constellation_tracker_tracking_source
916 */
918{
919 struct xrt_device base;
920 struct xrt_frame_node node;
921
922 struct xrt_frame_context *xfctx;
923
924 enum u_logging_level log_level;
925
926 // has built-in mutex so thread safe
927 struct m_relation_history *relation_hist;
928
929 bool use_constellation_poses;
930
931 struct os_hid_device *hmd_dev;
932 struct os_hid_device *radio_dev;
933
934 struct os_thread_helper sensor_thread;
935
936 uint32_t last_remote_sample_time_us;
937 timepoint_ns last_remote_sample_time_ns;
938 timepoint_ns last_sample_local_timestamp_ns;
939
940 uint32_t last_remote_exposure_time_us;
941 //! The time of the last exposure in remote time, only accessed from the sensor thread, not locked.
943 //! The time of the last exposure, locked by sensor_thread.
945 //! A total counter for how many exposures have occurred
947 uint16_t last_tracking_count;
948
949 //! The most recent exposures, newest at `(exposure_history_pushed - 1) % RIFT_EXPOSURE_HISTORY_SIZE`, locked by
950 //! sensor_thread.
952 //! How many exposures have ever been pushed into the history, locked by sensor_thread.
954
955 struct m_imu_3dof fusion;
956 struct m_clock_windowed_skew_tracker *clock_tracker;
957
958 timepoint_ns last_keepalive_time;
959 enum rift_variant variant;
960 struct rift_config_report config;
962
963 struct t_timing_event_sink *timing_event_sink;
964 struct t_timing_event_source *timing_event_source;
965
966 struct rift_tracking_report tracking;
967
968 const struct rift_lens_distortion *lens_distortions;
969 uint16_t num_lens_distortions;
970 uint16_t distortion_in_use;
971
972 struct rift_extra_display_info extra_display_info;
973 float icd_override_m;
974
975 bool presence;
976
977 bool imu_needs_calibration;
978 struct rift_imu_calibration imu_calibration;
979
980 uint8_t radio_address[5];
981
982 //! Mutex to protect access to the device array, device count == -1 means uninitialized
984
985 int device_count;
986 int added_devices;
987 struct xrt_device *devices[4]; // left touch, right touch, tracked object, remote
988
989 struct t_constellation_tracker *constellation_tracker;
990 struct t_constellation_tracker_device constellation_device;
991 struct t_constellation_tracker_tracking_source constellation_tracking_source;
992 t_constellation_device_id_t constellation_device_id;
993
994 struct m_ff_vec3_f32 *gyro_ff;
995 struct m_ff_vec3_f32 *accel_ff;
996 struct m_relation_history *raw_constellation_relation_hist;
997 timepoint_ns last_ff_timestamp_ns;
998 struct m_ff_f64 *gravity_correction;
999 timepoint_ns latest_constellation_ts;
1000
1001 struct t_constellation_tracker_led_model led_model;
1002 struct xrt_pose T_imu_device;
1003 struct xrt_pose T_device_imu;
1004
1005 //! Generic state for the radio state machine
1006 struct
1007 {
1008 struct os_thread_helper thread;
1009
1010 struct rift_touch_controller *touch_controllers[3];
1011 struct rift_remote *remote;
1012
1013 enum rift_radio_command current_command;
1014 union rift_radio_command_data command_data;
1016};
1017
1018//! Casting helper function from xrt_device->rift_hmd
1019static inline struct rift_hmd *
1021{
1022 return (struct rift_hmd *)xdev;
1023}
1024
1025static inline struct rift_hmd *
1026rift_hmd_from_node(struct xrt_frame_node *node)
1027{
1028 return (struct rift_hmd *)container_of(node, struct rift_hmd, node);
1029}
1030
1031static inline struct rift_touch_controller *
1033{
1034 return (struct rift_touch_controller *)xdev;
1035}
1036
1037static inline struct rift_touch_controller *
1038rift_touch_controller_from_node(struct xrt_frame_node *node)
1039{
1040 return (struct rift_touch_controller *)container_of(node, struct rift_touch_controller, node);
1041}
1042
1043static inline struct rift_remote *
1044rift_remote(struct xrt_device *xdev)
1045{
1046 return (struct rift_remote *)xdev;
1047}
1048
1049static inline struct rift_remote *
1050rift_remote_from_node(struct xrt_frame_node *node)
1051{
1052 return (struct rift_remote *)container_of(node, struct rift_remote, node);
1053}
1054
1055static inline size_t
1056rift_radio_device_type_to_touch_index(enum rift_radio_device_type device_type)
1057{
1058 switch (device_type) {
1059 case RIFT_RADIO_DEVICE_LEFT_TOUCH: return 0;
1060 case RIFT_RADIO_DEVICE_RIGHT_TOUCH: return 1;
1061 case RIFT_RADIO_DEVICE_TRACKED_OBJECT: return 2;
1062 default: assert(false);
1063 }
1064
1065 return -1;
1066}
1067
1068static inline enum rift_radio_device_type
1069rift_radio_touch_index_to_device_type(size_t index)
1070{
1071 switch (index) {
1072 case 0: return RIFT_RADIO_DEVICE_LEFT_TOUCH;
1073 case 1: return RIFT_RADIO_DEVICE_RIGHT_TOUCH;
1074 case 2: return RIFT_RADIO_DEVICE_TRACKED_OBJECT;
1075 default: assert(false);
1076 }
1077
1078 return (enum rift_radio_device_type)0;
1079}
1080
1081static inline float
1082rift_min_mid_max_cap(struct rift_touch_controller_calibration *calibration, size_t index, float value)
1083{
1084 return (value - calibration->cap_sense_min[index]) /
1085 (calibration->cap_sense_touch[index] - calibration->cap_sense_min[index]);
1086}
1087
1088static inline float
1089rift_min_mid_max_range_to_float(uint16_t range[3], uint16_t value)
1090{
1091 if (value < range[1]) {
1092 return 1.0f - ((float)value - range[0]) / (range[1] - range[0]) * 0.5f;
1093 } else {
1094 return 0.5f - ((float)value - range[1]) / (range[2] - range[1]) * 0.5f;
1095 }
1096}
1097
1098bool
1099rift_touch_calibration_parse(const char *calibration_data,
1100 size_t calibration_size,
1101 struct rift_touch_controller_calibration *out_calibration);
1102
1103#ifdef __cplusplus
1104} // extern "C"
1105#endif
u_logging_level
Logging level enum.
Definition u_logging.h:45
int64_t timepoint_ns
Integer timestamp type.
Definition u_time.h:77
#define container_of(ptr, type, field)
Get the holder from a pointer to a field.
Definition xrt_compiler.h:298
C interface to math library.
Helpers to estimate offsets between clocks.
A fifo that also lets you dynamically filter.
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.
Interface to Oculus Rift driver code.
#define RIFT_EXPOSURE_HISTORY_SIZE
How many past exposures a frame can be matched against. At ~60 Hz this is a little over a quarter sec...
Definition rift_internal.h:891
Definition oh_device.c:483
Definition rift_internal.h:411
Definition m_space.cpp:87
Definition t_imu.cpp:25
Definition m_clock_tracking.c:35
Definition m_filter_fifo.c:198
Definition m_filter_fifo.c:23
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
A wrapper around a native mutex.
Definition os_threading.h:69
All in one helper that handles locking, waiting for change and starting a thread.
Definition os_threading.h:499
Definition rift_internal.h:625
Definition rift_internal.h:211
Definition rift_internal.h:174
Definition rift_internal.h:294
Definition rift_internal.h:399
Definition rift_internal.h:186
Definition rift_internal.h:345
Definition rift_internal.h:310
Definition rift_internal.h:382
Definition rift_internal.h:375
Definition rift_internal.h:390
Definition rift_internal.h:433
One camera exposure the HMD told us about, held so that late frames can still find the exposure they ...
Definition rift_internal.h:895
timepoint_ns timestamp_ns
When the exposure started, in local monotonic time. This is what frames matched to it are timestamped...
Definition rift_internal.h:899
uint32_t sequence
The value of rift_hmd::exposure_counter at this exposure.
Definition rift_internal.h:897
timepoint_ns recv_timestamp_ns
When the IN report announcing this exposure arrived, in local monotonic time.
Definition rift_internal.h:907
Definition rift_internal.h:660
A rift HMD device.
Definition rift_internal.h:918
struct rift_hmd::@179 radio_state
Generic state for the radio state machine.
timepoint_ns last_local_exposure_time_ns
The time of the last exposure, locked by sensor_thread.
Definition rift_internal.h:944
struct rift_exposure_event exposure_history[16]
The most recent exposures, newest at (exposure_history_pushed - 1) % RIFT_EXPOSURE_HISTORY_SIZE,...
Definition rift_internal.h:951
struct os_mutex device_mutex
Mutex to protect access to the device array, device count == -1 means uninitialized.
Definition rift_internal.h:983
timepoint_ns last_remote_exposure_time_ns
The time of the last exposure in remote time, only accessed from the sensor thread,...
Definition rift_internal.h:942
uint32_t exposure_counter
A total counter for how many exposures have occurred.
Definition rift_internal.h:946
uint64_t exposure_history_pushed
How many exposures have ever been pushed into the history, locked by sensor_thread.
Definition rift_internal.h:953
Definition rift_internal.h:442
Definition rift_internal.h:676
Definition rift_internal.h:225
Definition rift_internal.h:634
Definition rift_internal.h:264
Definition rift_internal.h:485
Definition rift_internal.h:458
Definition rift_internal.h:874
Definition rift_internal.h:864
char * serial
A pointer to store the serial string. Must contain at least SERIAL_NUMBER_LENGTH bytes.
Definition rift_internal.h:866
bool * serial_valid
A pointer to store when reading the serial was successful.
Definition rift_internal.h:868
Definition rift_internal.h:468
Definition rift_internal.h:478
Definition rift_internal.h:561
Definition rift_internal.h:506
Definition rift_internal.h:539
Definition rift_internal.h:574
A Rift Remote device.
Definition rift_internal.h:844
xrt_atomic_s32_t buttons
The button state of the remote, stored as an atomic to avoid needing a mutex.
Definition rift_internal.h:849
bool serial_valid
Locked by radio_state.thread.
Definition rift_internal.h:852
Definition rift_internal.h:646
Definition rift_internal.h:721
Definition rift_internal.h:749
Definition rift_internal.h:714
A Rift Touch controller device.
Definition rift_internal.h:768
struct rift_touch_controller::@177 radio_data
Locked by radio_state.thread.
Definition rift_internal.h:596
Definition rift_internal.h:652
A constellation tracker device is a device that the constellation tracker will attempt to track in 6d...
Definition t_constellation.h:339
The LED model is a series of points which define the real-world positions of all LEDs.
Definition t_constellation.h:266
A constellation tracker tracking source is an arbitrary source of tracking data for the constellation...
Definition t_constellation.h:221
A time sync sink is a component that receives timing events from a stable timing source,...
Definition t_time_sync.h:69
A time sync source is a component that generates timing events for an t_timing_event_sink to consume.
Definition t_time_sync.h:102
Definition u_worker.c:38
A single HMD or input device.
Definition xrt_device.h:341
Object used to track all sinks and frame producers in a graph.
Definition xrt_frame.h:108
A interface object used for destroying a frame graph.
Definition xrt_frame.h:87
IMU Sample.
Definition xrt_tracking.h:134
A tightly packed 3x3 matrix of floats.
Definition xrt_defines.h:559
A pose composed of a position and orientation.
Definition xrt_defines.h:492
A 2 element vector with single floats.
Definition xrt_defines.h:268
A 3 element vector with single floats.
Definition xrt_defines.h:289
Header defining the tracking system integration in Monado.
C interface to basic IMU fusion.
Header defining interfaces for time synchronization in Monado.
Misc helpers for device drivers.
Basic logging functionality.
Definition rift_internal.h:885
Endian-specific byte order defines.