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