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