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