The open source OpenXR runtime
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

d/rift: Add basic Rift DK2 driver

Only handles very basic init and display

Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2428>

+700
+3
CMakeLists.txt
··· 332 332 option_with_deps(XRT_BUILD_DRIVER_QWERTY "Enable Qwerty driver" DEPENDS XRT_HAVE_SDL2) 333 333 option_with_deps(XRT_BUILD_DRIVER_REALSENSE "Enable RealSense device driver" DEPENDS XRT_HAVE_REALSENSE) 334 334 option_with_deps(XRT_BUILD_DRIVER_REMOTE "Enable remote debugging driver" DEPENDS "XRT_HAVE_LINUX OR ANDROID OR WIN32") 335 + option_with_deps(XRT_BUILD_DRIVER_RIFT "Enable Oculus Rift (DK2) device driver") 335 336 option_with_deps(XRT_BUILD_DRIVER_RIFT_S "Enable Oculus Rift S device driver" DEPENDS XRT_HAVE_V4L2) 336 337 option_with_deps(XRT_BUILD_DRIVER_ROKID "Enable Rokid driver" DEPENDS "XRT_HAVE_LIBUSB") 337 338 option_with_deps(XRT_BUILD_DRIVER_STEAMVR_LIGHTHOUSE "Enable SteamVR Lighthouse driver" DEPENDS XRT_HAVE_LINUX XRT_MODULE_AUX_VIVE) ··· 427 428 "PSVR" 428 429 "REALSENSE" 429 430 "REMOTE" 431 + "RIFT" 430 432 "RIFT_S" 431 433 "ROKID" 432 434 "SURVIVE" ··· 659 661 message(STATUS "# DRIVER_QWERTY: ${XRT_BUILD_DRIVER_QWERTY}") 660 662 message(STATUS "# DRIVER_REALSENSE: ${XRT_BUILD_DRIVER_REALSENSE}") 661 663 message(STATUS "# DRIVER_REMOTE: ${XRT_BUILD_DRIVER_REMOTE}") 664 + message(STATUS "# DRIVER_RIFT: ${XRT_BUILD_DRIVER_RIFT}") 662 665 message(STATUS "# DRIVER_RIFT_S: ${XRT_BUILD_DRIVER_RIFT_S}") 663 666 message(STATUS "# DRIVER_ROKID: ${XRT_BUILD_DRIVER_ROKID}") 664 667 message(STATUS "# DRIVER_SIMULATED: ${XRT_BUILD_DRIVER_SIMULATED}")
+20
src/xrt/drivers/CMakeLists.txt
··· 240 240 list(APPEND ENABLED_HEADSET_DRIVERS rokid) 241 241 endif() 242 242 243 + if(XRT_BUILD_DRIVER_RIFT) 244 + add_library( 245 + drv_rift STATIC 246 + rift/rift_hmd.c 247 + rift/rift_prober.c 248 + ) 249 + target_include_directories(drv_rift SYSTEM PRIVATE) 250 + target_link_libraries( 251 + drv_rift 252 + PRIVATE 253 + xrt-interfaces 254 + aux_util 255 + aux_util_sink 256 + aux_math 257 + xrt-external-cjson 258 + xrt-external-tinyceres 259 + ) 260 + list(APPEND ENABLED_HEADSET_DRIVERS rift) 261 + endif() 262 + 243 263 if(XRT_BUILD_DRIVER_RIFT_S) 244 264 add_library( 245 265 drv_rift_s STATIC
+383
src/xrt/drivers/rift/rift_hmd.c
··· 1 + // Copyright 2020-2025, Collabora, Ltd. 2 + // Copyright 2025, Beyley Cardellio 3 + // SPDX-License-Identifier: BSL-1.0 4 + /*! 5 + * @file 6 + * @brief Driver for the Oculus Rift. 7 + * 8 + * Based largely on simulated_hmd.c, with reference to the DK1/DK2 firmware and OpenHMD's rift driver. 9 + * 10 + * @author Jakob Bornecrantz <jakob@collabora.com> 11 + * @author Rylie Pavlik <rylie.pavlik@collabora.com> 12 + * @author Beyley Cardellio <ep1cm1n10n123@gmail.com> 13 + * @ingroup drv_rift 14 + */ 15 + 16 + #include "os/os_time.h" 17 + #include "xrt/xrt_defines.h" 18 + #include "xrt/xrt_device.h" 19 + #include "rift_interface.h" 20 + 21 + #include "math/m_relation_history.h" 22 + #include "math/m_api.h" 23 + #include "math/m_mathinclude.h" // IWYU pragma: keep 24 + 25 + #include "util/u_debug.h" 26 + #include "util/u_device.h" 27 + #include "util/u_distortion_mesh.h" 28 + #include "util/u_logging.h" 29 + #include "util/u_misc.h" 30 + #include "util/u_time.h" 31 + #include "util/u_var.h" 32 + #include "util/u_visibility_mask.h" 33 + #include "xrt/xrt_results.h" 34 + 35 + #include <stdio.h> 36 + 37 + 38 + /* 39 + * 40 + * Structs and defines. 41 + * 42 + */ 43 + 44 + /// Casting helper function 45 + static inline struct rift_hmd * 46 + rift_hmd(struct xrt_device *xdev) 47 + { 48 + return (struct rift_hmd *)xdev; 49 + } 50 + 51 + DEBUG_GET_ONCE_LOG_OPTION(rift_log, "RIFT_LOG", U_LOGGING_WARN) 52 + 53 + #define HMD_TRACE(hmd, ...) U_LOG_XDEV_IFL_T(&hmd->base, hmd->log_level, __VA_ARGS__) 54 + #define HMD_DEBUG(hmd, ...) U_LOG_XDEV_IFL_D(&hmd->base, hmd->log_level, __VA_ARGS__) 55 + #define HMD_INFO(hmd, ...) U_LOG_XDEV_IFL_I(&hmd->base, hmd->log_level, __VA_ARGS__) 56 + #define HMD_ERROR(hmd, ...) U_LOG_XDEV_IFL_E(&hmd->base, hmd->log_level, __VA_ARGS__) 57 + 58 + /* 59 + * 60 + * Headset functions 61 + * 62 + */ 63 + 64 + static int 65 + rift_send_report(struct rift_hmd *hmd, uint8_t report_id, void *data, size_t data_length) 66 + { 67 + #define REPORT_WRITE_DATA(ptr, ptr_len) \ 68 + if (ptr_len > sizeof(buffer) - length) { \ 69 + HMD_ERROR(hmd, "Tried to fit %ld bytes into buffer with only %ld bytes left", ptr_len, \ 70 + sizeof(buffer) - length); \ 71 + return -1; \ 72 + } \ 73 + memcpy(buffer + length, ptr, ptr_len); \ 74 + length += ptr_len; 75 + 76 + #define REPORT_WRITE_VALUE(value) REPORT_WRITE_DATA(&value, sizeof(value)); 77 + 78 + int result; 79 + 80 + uint8_t buffer[REPORT_MAX_SIZE]; 81 + size_t length = 0; 82 + 83 + REPORT_WRITE_VALUE(report_id) 84 + REPORT_WRITE_DATA(data, data_length) 85 + 86 + result = os_hid_set_feature(hmd->hid_dev, buffer, length); 87 + if (result < 0) { 88 + return result; 89 + } 90 + 91 + return 0; 92 + } 93 + 94 + static int 95 + rift_get_report(struct rift_hmd *hmd, uint8_t report_id, uint8_t *out, size_t out_len) 96 + { 97 + return os_hid_get_feature(hmd->hid_dev, report_id, out, out_len); 98 + } 99 + 100 + static int 101 + rift_send_keepalive(struct rift_hmd *hmd) 102 + { 103 + struct dk2_report_keepalive_mux report = {0, IN_REPORT_DK2, 10000}; 104 + 105 + int result = 106 + rift_send_report(hmd, FEATURE_REPORT_KEEPALIVE_MUX, &report, sizeof(struct dk2_report_keepalive_mux)); 107 + 108 + if (result < 0) { 109 + return result; 110 + } 111 + 112 + hmd->last_keepalive_time = os_monotonic_get_ns(); 113 + 114 + return 0; 115 + } 116 + 117 + static int 118 + rift_get_config(struct rift_hmd *hmd, struct rift_config_report *config) 119 + { 120 + uint8_t buf[REPORT_MAX_SIZE] = {0}; 121 + 122 + int result = rift_get_report(hmd, FEATURE_REPORT_CONFIG, buf, sizeof(buf)); 123 + if (result < 0) { 124 + return result; 125 + } 126 + 127 + // FIXME: handle endian differences 128 + memcpy(config, buf + 1, sizeof(*config)); 129 + 130 + // this value is hardcoded in the DK1 and DK2 firmware 131 + if ((hmd->variant == RIFT_VARIANT_DK1 || hmd->variant == RIFT_VARIANT_DK2) && config->sample_rate != 1000) { 132 + HMD_ERROR(hmd, "Got invalid config from headset, got sample rate %d when expected %d", 133 + config->sample_rate, 1000); 134 + return -1; 135 + } 136 + 137 + return 0; 138 + } 139 + 140 + static int 141 + rift_get_display_info(struct rift_hmd *hmd, struct rift_display_info_report *display_info) 142 + { 143 + uint8_t buf[REPORT_MAX_SIZE] = {0}; 144 + 145 + int result = rift_get_report(hmd, FEATURE_REPORT_DISPLAY_INFO, buf, sizeof(buf)); 146 + if (result < 0) { 147 + return result; 148 + } 149 + 150 + // FIXME: handle endian differences 151 + memcpy(display_info, buf + 1, sizeof(*display_info)); 152 + 153 + return 0; 154 + } 155 + 156 + static int 157 + rift_set_config(struct rift_hmd *hmd, struct rift_config_report *config) 158 + { 159 + return rift_send_report(hmd, FEATURE_REPORT_CONFIG, &config, sizeof(*config)); 160 + } 161 + 162 + /* 163 + * 164 + * Driver functions 165 + * 166 + */ 167 + 168 + static void 169 + rift_hmd_destroy(struct xrt_device *xdev) 170 + { 171 + struct rift_hmd *hmd = rift_hmd(xdev); 172 + 173 + // Remove the variable tracking. 174 + u_var_remove_root(hmd); 175 + 176 + m_relation_history_destroy(&hmd->relation_hist); 177 + 178 + u_device_free(&hmd->base); 179 + } 180 + 181 + static xrt_result_t 182 + rift_hmd_get_tracked_pose(struct xrt_device *xdev, 183 + enum xrt_input_name name, 184 + int64_t at_timestamp_ns, 185 + struct xrt_space_relation *out_relation) 186 + { 187 + struct rift_hmd *hmd = rift_hmd(xdev); 188 + 189 + if (name != XRT_INPUT_GENERIC_HEAD_POSE) { 190 + U_LOG_XDEV_UNSUPPORTED_INPUT(&hmd->base, hmd->log_level, name); 191 + return XRT_ERROR_INPUT_UNSUPPORTED; 192 + } 193 + 194 + struct xrt_space_relation relation = XRT_SPACE_RELATION_ZERO; 195 + 196 + enum m_relation_history_result history_result = 197 + m_relation_history_get(hmd->relation_hist, at_timestamp_ns, &relation); 198 + if (history_result == M_RELATION_HISTORY_RESULT_INVALID) { 199 + // If you get in here, it means you did not push any poses into the relation history. 200 + // You may want to handle this differently. 201 + HMD_ERROR(hmd, "Internal error: no poses pushed?"); 202 + } 203 + 204 + if ((relation.relation_flags & XRT_SPACE_RELATION_ORIENTATION_VALID_BIT) != 0) { 205 + // If we provide an orientation, make sure that it is normalized. 206 + math_quat_normalize(&relation.pose.orientation); 207 + } 208 + 209 + *out_relation = relation; 210 + return XRT_SUCCESS; 211 + } 212 + 213 + static xrt_result_t 214 + rift_hmd_get_view_poses(struct xrt_device *xdev, 215 + const struct xrt_vec3 *default_eye_relation, 216 + int64_t at_timestamp_ns, 217 + uint32_t view_count, 218 + struct xrt_space_relation *out_head_relation, 219 + struct xrt_fov *out_fovs, 220 + struct xrt_pose *out_poses) 221 + { 222 + /* 223 + * For HMDs you can call this function or directly set 224 + * the `get_view_poses` function on the device to it. 225 + */ 226 + return u_device_get_view_poses( // 227 + xdev, // 228 + default_eye_relation, // 229 + at_timestamp_ns, // 230 + view_count, // 231 + out_head_relation, // 232 + out_fovs, // 233 + out_poses); // 234 + } 235 + 236 + static xrt_result_t 237 + rift_hmd_get_visibility_mask(struct xrt_device *xdev, 238 + enum xrt_visibility_mask_type type, 239 + uint32_t view_index, 240 + struct xrt_visibility_mask **out_mask) 241 + { 242 + struct xrt_fov fov = xdev->hmd->distortion.fov[view_index]; 243 + u_visibility_mask_get_default(type, &fov, out_mask); 244 + return XRT_SUCCESS; 245 + } 246 + 247 + static bool 248 + rift_hmd_compute_distortion(struct xrt_device *dev, uint32_t view, float u, float v, struct xrt_uv_triplet *out_result) 249 + { 250 + struct rift_hmd *hmd = rift_hmd(dev); 251 + 252 + return false; 253 + } 254 + 255 + struct rift_hmd * 256 + rift_hmd_create(struct os_hid_device *dev, enum rift_variant variant, char *device_name, char *serial_number) 257 + { 258 + int result; 259 + 260 + // This indicates you won't be using Monado's built-in tracking algorithms. 261 + enum u_device_alloc_flags flags = 262 + (enum u_device_alloc_flags)(U_DEVICE_ALLOC_HMD | U_DEVICE_ALLOC_TRACKING_NONE); 263 + 264 + struct rift_hmd *hmd = U_DEVICE_ALLOCATE(struct rift_hmd, flags, 1, 0); 265 + 266 + hmd->variant = variant; 267 + hmd->hid_dev = dev; 268 + 269 + result = rift_send_keepalive(hmd); 270 + if (result < 0) { 271 + HMD_ERROR(hmd, "Failed to send keepalive to spin up headset, reason %d", result); 272 + u_device_free(&hmd->base); 273 + return NULL; 274 + } 275 + 276 + result = rift_get_config(hmd, &hmd->config); 277 + if (result < 0) { 278 + HMD_ERROR(hmd, "Failed to get device config, reason %d", result); 279 + u_device_free(&hmd->base); 280 + return NULL; 281 + } 282 + HMD_INFO(hmd, "Got config from hmd, config flags: %X", hmd->config.config_flags); 283 + 284 + result = rift_get_display_info(hmd, &hmd->display_info); 285 + if (result < 0) { 286 + HMD_ERROR(hmd, "Failed to get device config, reason %d", result); 287 + u_device_free(&hmd->base); 288 + return NULL; 289 + } 290 + HMD_INFO(hmd, "Got display info from hmd, res: %dx%d", hmd->display_info.resolution_x, 291 + hmd->display_info.resolution_y); 292 + 293 + if (getenv("RIFT_POWER_OVERRIDE") != NULL) { 294 + hmd->config.config_flags |= RIFT_CONFIG_REPORT_OVERRIDE_POWER; 295 + HMD_INFO(hmd, "Force-enabling the override power config flag."); 296 + } 297 + 298 + // force enable calibration use and auto calibration 299 + // this is on by default according to the firmware on DK1 and DK2, 300 + // but OpenHMD forces them on, we should do the same, they probably had a reason 301 + hmd->config.config_flags |= RIFT_CONFIG_REPORT_USE_CALIBRATION; 302 + hmd->config.config_flags |= RIFT_CONFIG_REPORT_AUTO_CALIBRATION; 303 + 304 + // update the config 305 + result = rift_set_config(hmd, &hmd->config); 306 + if (result < 0) { 307 + HMD_ERROR(hmd, "Failed to enable the override power config flag, reason %d", result); 308 + u_device_free(&hmd->base); 309 + return NULL; 310 + } 311 + 312 + // This list should be ordered, most preferred first. 313 + size_t idx = 0; 314 + hmd->base.hmd->blend_modes[idx++] = XRT_BLEND_MODE_OPAQUE; 315 + hmd->base.hmd->blend_mode_count = idx; 316 + 317 + hmd->base.update_inputs = u_device_noop_update_inputs; 318 + hmd->base.get_tracked_pose = rift_hmd_get_tracked_pose; 319 + hmd->base.get_view_poses = rift_hmd_get_view_poses; 320 + hmd->base.get_visibility_mask = rift_hmd_get_visibility_mask; 321 + hmd->base.destroy = rift_hmd_destroy; 322 + 323 + // Distortion information, fills in xdev->compute_distortion(). 324 + u_distortion_mesh_set_none(&hmd->base); 325 + 326 + // populate this with something more complex if required 327 + // hmd->base.compute_distortion = rift_hmd_compute_distortion; 328 + 329 + hmd->pose = (struct xrt_pose)XRT_POSE_IDENTITY; 330 + hmd->log_level = debug_get_log_option_rift_log(); 331 + 332 + // Print name. 333 + strncpy(hmd->base.str, device_name, XRT_DEVICE_NAME_LEN); 334 + strncpy(hmd->base.serial, serial_number, XRT_DEVICE_NAME_LEN); 335 + 336 + m_relation_history_create(&hmd->relation_hist, NULL); 337 + 338 + // Setup input. 339 + hmd->base.name = XRT_DEVICE_GENERIC_HMD; 340 + hmd->base.device_type = XRT_DEVICE_TYPE_HMD; 341 + hmd->base.inputs[0].name = XRT_INPUT_GENERIC_HEAD_POSE; 342 + hmd->base.supported.orientation_tracking = true; 343 + hmd->base.supported.position_tracking = false; 344 + 345 + // Set up display details 346 + // refresh rate 347 + hmd->base.hmd->screens[0].nominal_frame_interval_ns = time_s_to_ns(1.0f / 75.0f); 348 + 349 + struct u_device_simple_info info; 350 + info.display.w_pixels = hmd->display_info.resolution_x; 351 + info.display.h_pixels = hmd->display_info.resolution_y; 352 + info.display.w_meters = (float)hmd->display_info.display_width / 1000000.0f; // micrometers -> meters 353 + info.display.h_meters = (float)hmd->display_info.display_height / 1000000.0f; 354 + 355 + info.lens_horizontal_separation_meters = (float)hmd->display_info.lens_separation / 1000000.0f; 356 + 357 + // TODO: this is per eye on the headset, but we're just taking the left eye for this, we should be using both 358 + // eyes, ideally 359 + info.lens_vertical_position_meters = (float)hmd->display_info.lens_distance_l / 1000000.0f; 360 + 361 + // TODO: calculate this 362 + info.fov[0] = (float)(93.0 * (M_PI / 180.0)); 363 + info.fov[1] = (float)(99.0 * (M_PI / 180.0)); 364 + 365 + if (!u_device_setup_split_side_by_side(&hmd->base, &info)) { 366 + HMD_ERROR(hmd, "Failed to setup basic device info"); 367 + rift_hmd_destroy(&hmd->base); 368 + return NULL; 369 + } 370 + 371 + // Just put an initial identity value in the tracker 372 + struct xrt_space_relation identity = XRT_SPACE_RELATION_ZERO; 373 + identity.relation_flags = (enum xrt_space_relation_flags)(XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT | 374 + XRT_SPACE_RELATION_ORIENTATION_VALID_BIT); 375 + uint64_t now = os_monotonic_get_ns(); 376 + m_relation_history_push(hmd->relation_hist, &identity, now); 377 + 378 + // Setup variable tracker: Optional but useful for debugging 379 + u_var_add_root(hmd, "Rift HMD", true); 380 + u_var_add_log_level(hmd, &hmd->log_level, "log_level"); 381 + 382 + return hmd; 383 + }
+199
src/xrt/drivers/rift/rift_interface.h
··· 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 Cardellion <ep1cm1n10n123@gmail.com> 7 + * @ingroup drv_rift 8 + */ 9 + 10 + #pragma once 11 + 12 + #include "xrt/xrt_device.h" 13 + #include "xrt/xrt_defines.h" 14 + #include "xrt/xrt_prober.h" 15 + 16 + #include "os/os_hid.h" 17 + 18 + #include "util/u_device.h" 19 + #include "util/u_logging.h" 20 + 21 + #include <stdlib.h> 22 + #include <stdio.h> 23 + 24 + #ifdef __cplusplus 25 + extern "C" { 26 + #endif 27 + 28 + #define REPORT_MAX_SIZE 69 // max size of a feature report (FEATURE_REPORT_CALIBRATE) 29 + 30 + enum rift_feature_reports 31 + { 32 + // DK1 33 + FEATURE_REPORT_CONFIG = 2, // get + set 34 + FEATURE_REPORT_CALIBRATE = 3, // get + set 35 + FEATURE_REPORT_RANGE = 4, // get + set 36 + FEATURE_REPORT_REGISTER = 5, // get + set 37 + FEATURE_REPORT_DFU = 6, // get + set 38 + FEATURE_REPORT_DK1_KEEP_ALIVE = 8, // get + set 39 + FEATURE_REPORT_DISPLAY_INFO = 9, // get + set 40 + FEATURE_REPORT_SERIAL = 10, // get + set 41 + // DK2 42 + FEATURE_REPORT_TRACKING = 12, // get + set 43 + FEATURE_REPORT_DISPLAY = 13, // get + set 44 + FEATURE_REPORT_MAG_CALIBRATION = 14, // get + set 45 + FEATURE_REPORT_POS_CALIBRATION = 15, // get + set 46 + FEATURE_REPORT_CUSTOM_PATTERN = 16, // get + set 47 + FEATURE_REPORT_KEEPALIVE_MUX = 17, // get + set 48 + FEATURE_REPORT_MANUFACTURING = 18, // get + set 49 + FEATURE_REPORT_UUID = 19, // get + set 50 + FEATURE_REPORT_TEMPERATURE = 20, // get + set 51 + FEATURE_REPORT_GYROOFFSET = 21, // get only 52 + FEATURE_REPORT_LENS_DISTORTION = 22, // get + set 53 + }; 54 + 55 + enum rift_config_report_flags 56 + { 57 + // output the sample data raw from the sensors without converting them to known units 58 + RIFT_CONFIG_REPORT_USE_RAW = 1, 59 + // internal test mode for calibrating zero rate drift on gyro 60 + RIFT_CONFIG_REPORT_INTERNAL_CALIBRATION = 1 << 1, 61 + // use the calibration parameters stored on the device 62 + RIFT_CONFIG_REPORT_USE_CALIBRATION = 1 << 2, 63 + // recalibrate the gyro zero rate offset when the device is stationary 64 + RIFT_CONFIG_REPORT_AUTO_CALIBRATION = 1 << 3, 65 + // stop sending IN reports when the device has stopped moving for Interval milliseconds 66 + RIFT_CONFIG_REPORT_MOTION_KEEP_ALIVE = 1 << 4, 67 + // stop sending IN reports when the device has stopped recieving feature reports for Interval milliseconds 68 + RIFT_CONFIG_REPORT_COMMAND_KEEP_ALIVE = 1 << 5, 69 + // output the IN report data in the coordinate system used by LibOVR relative to the tracker, otherwise, report 70 + // in the coordinate system of the device 71 + RIFT_CONFIG_REPORT_USE_SENSOR_COORDINATES = 1 << 6, 72 + // override the power state of the USB hub, forcing it to act as if the external power source is connected (DK2 73 + // only, does nothing on DK1) 74 + RIFT_CONFIG_REPORT_OVERRIDE_POWER = 1 << 7, 75 + }; 76 + 77 + enum rift_distortion_type 78 + { 79 + RIFT_DISTORTION_TYPE_DIMS = 1, 80 + RIFT_DISTORTION_TYPE_K = 2, 81 + }; 82 + 83 + /* 84 + * 85 + * Packed structs for USB communication (borrowed from Rokid driver) 86 + * 87 + */ 88 + 89 + #if defined(__GNUC__) 90 + #define RIFT_PACKED __attribute__((packed)) 91 + #else 92 + #define RIFT_PACKED 93 + #endif /* __GNUC__ */ 94 + 95 + #if defined(_MSC_VER) 96 + #pragma pack(push, 1) 97 + #endif 98 + 99 + struct rift_config_report 100 + { 101 + uint16_t command_id; 102 + uint8_t config_flags; 103 + uint8_t interval; 104 + uint16_t sample_rate; // always 1000hz on DK1/DK2 105 + } RIFT_PACKED; 106 + 107 + struct rift_display_info_report 108 + { 109 + uint16_t command_id; 110 + uint8_t distortion_type; 111 + // the horizontal resolution of the display, in pixels 112 + uint16_t resolution_x; 113 + // the vertical resolution of the display, in pixels 114 + uint16_t resolution_y; 115 + // width in micrometers 116 + uint32_t display_width; 117 + // height in micrometers 118 + uint32_t display_height; 119 + // the vertical center of the display, in micrometers 120 + uint32_t center_v; 121 + // the separation between the two lenses, in micrometers 122 + uint32_t lens_separation; 123 + uint32_t lens_distance_l; 124 + uint32_t lens_distance_r; 125 + float distortion[6]; 126 + } RIFT_PACKED; 127 + 128 + #define IN_REPORT_DK2 11 129 + struct dk2_report_keepalive_mux 130 + { 131 + uint16_t command; 132 + uint8_t in_report; 133 + uint16_t interval; 134 + } RIFT_PACKED; 135 + 136 + #if defined(_MSC_VER) 137 + #pragma pack(pop) 138 + #endif 139 + 140 + enum rift_variant 141 + { 142 + RIFT_VARIANT_DK1, 143 + RIFT_VARIANT_DK2, 144 + }; 145 + 146 + #define OCULUS_VR_VID 0x2833 147 + 148 + #define OCULUS_DK2_PID 0x0021 149 + 150 + /*! 151 + * Probing function for Oculus Rift devices. 152 + * 153 + * @ingroup drv_rift 154 + * @see xrt_prober_found_func_t 155 + */ 156 + int 157 + rift_found(struct xrt_prober *xp, 158 + struct xrt_prober_device **devices, 159 + size_t device_count, 160 + size_t index, 161 + cJSON *attached_data, 162 + struct xrt_device **out_xdev); 163 + 164 + /*! 165 + * A rift HMD device. 166 + * 167 + * @implements xrt_device 168 + */ 169 + struct rift_hmd 170 + { 171 + struct xrt_device base; 172 + 173 + struct xrt_pose pose; 174 + 175 + enum u_logging_level log_level; 176 + 177 + // has built-in mutex so thread safe 178 + struct m_relation_history *relation_hist; 179 + 180 + struct os_hid_device *hid_dev; 181 + 182 + int64_t last_keepalive_time; 183 + enum rift_variant variant; 184 + struct rift_config_report config; 185 + struct rift_display_info_report display_info; 186 + }; 187 + 188 + struct rift_hmd * 189 + rift_hmd_create(struct os_hid_device *dev, enum rift_variant variant, char *device_name, char *serial_number); 190 + 191 + /*! 192 + * @dir drivers/rift 193 + * 194 + * @brief @ref drv_rift files. 195 + */ 196 + 197 + #ifdef __cplusplus 198 + } 199 + #endif
+79
src/xrt/drivers/rift/rift_prober.c
··· 1 + // Copyright 2025, Beyley Cardellio 2 + // SPDX-License-Identifier: BSL-1.0 3 + /*! 4 + * @file 5 + * @brief Prober for finding an Oculus Rift device based on USB VID/PID. 6 + * @author Beyley Cardellio <ep1cm1n10n123@gmail.com> 7 + * @ingroup drv_rift 8 + */ 9 + 10 + #include "xrt/xrt_prober.h" 11 + 12 + #include "util/u_misc.h" 13 + 14 + #include "rift_interface.h" 15 + 16 + static const char DK2_PRODUCT_STRING[] = "Rift DK2"; 17 + 18 + int 19 + rift_found(struct xrt_prober *xp, 20 + struct xrt_prober_device **devices, 21 + size_t device_count, 22 + size_t index, 23 + cJSON *attached_data, 24 + struct xrt_device **out_xdev) 25 + { 26 + struct xrt_prober_device *dev = devices[index]; 27 + 28 + unsigned char manufacturer[128] = {0}; 29 + int result = xrt_prober_get_string_descriptor(xp, dev, XRT_PROBER_STRING_MANUFACTURER, manufacturer, 30 + sizeof(manufacturer)); 31 + if (result < 0) { 32 + return -1; 33 + } 34 + 35 + unsigned char product[128] = {0}; 36 + result = xrt_prober_get_string_descriptor(xp, dev, XRT_PROBER_STRING_PRODUCT, product, sizeof(product)); 37 + if (result < 0) { 38 + return -1; 39 + } 40 + 41 + unsigned char serial_number[21] = {0}; 42 + result = xrt_prober_get_string_descriptor(xp, dev, XRT_PROBER_STRING_SERIAL_NUMBER, serial_number, 43 + sizeof(serial_number)); 44 + if (result < 0) { 45 + return -1; 46 + } 47 + 48 + // Some non-oculus devices (VR-Tek HMDs) re-use the same USB IDs as the oculus headsets, so we should check the 49 + // manufacturer 50 + if (strncmp((const char *)manufacturer, "Oculus VR, Inc.", sizeof(manufacturer)) != 0) { 51 + return -1; 52 + } 53 + 54 + enum rift_variant variant; 55 + const char *name; 56 + switch (dev->product_id) { 57 + case OCULUS_DK2_PID: 58 + variant = RIFT_VARIANT_DK2; 59 + name = DK2_PRODUCT_STRING; 60 + break; 61 + default: return -1; break; 62 + } 63 + 64 + U_LOG_I("%s - Found at least the tracker of some Rift (%s) -- opening\n", __func__, name); 65 + 66 + struct os_hid_device *hid = NULL; 67 + result = xrt_prober_open_hid_interface(xp, dev, 0, &hid); 68 + if (result != 0) { 69 + return -1; 70 + } 71 + 72 + struct rift_hmd *hd = rift_hmd_create(hid, variant, (char *)product, (char *)serial_number); 73 + if (hd == NULL) { 74 + return -1; 75 + } 76 + *out_xdev = &hd->base; 77 + 78 + return 1; 79 + }
+8
src/xrt/targets/common/CMakeLists.txt
··· 24 24 target_sources(target_lists PRIVATE target_builder_rgb_tracking.c) 25 25 endif() 26 26 27 + if(XRT_BUILD_DRIVER_RIFT) 28 + target_sources(target_lists PRIVATE target_builder_rift.c) 29 + endif() 30 + 27 31 if(XRT_BUILD_DRIVER_RIFT_S) 28 32 target_sources(target_lists PRIVATE target_builder_rift_s.c) 29 33 endif() ··· 140 144 141 145 if(XRT_BUILD_DRIVER_REMOTE) 142 146 target_link_libraries(target_lists PRIVATE drv_remote) 147 + endif() 148 + 149 + if(XRT_BUILD_DRIVER_RIFT) 150 + target_link_libraries(target_lists PRIVATE drv_rift) 143 151 endif() 144 152 145 153 if(XRT_BUILD_DRIVER_RIFT_S)
src/xrt/targets/common/target_builder_rift.c

This is a binary file and will not be displayed.

+8
src/xrt/targets/common/target_lists.c
··· 40 40 #include "psvr/psvr_interface.h" 41 41 #endif 42 42 43 + #ifdef XRT_BUILD_DRIVER_RIFT 44 + #include "rift/rift_interface.h" 45 + #endif 46 + 43 47 #ifdef XRT_BUILD_DRIVER_RIFT_S 44 48 #include "rift_s/rift_s_interface.h" 45 49 #endif ··· 183 187 {PSSENSE_VID, PSSENSE_PID_LEFT, pssense_found, "PlayStation VR2 Sense Controller (L)", "pssense"}, 184 188 {PSSENSE_VID, PSSENSE_PID_RIGHT, pssense_found, "PlayStation VR2 Sense Controller (R)", "pssense"}, 185 189 #endif // XRT_BUILD_DRIVER_PSSENSE 190 + 191 + #ifdef XRT_BUILD_DRIVER_RIFT 192 + {OCULUS_VR_VID, OCULUS_DK2_PID, rift_found, "Rift (DK2)", "rift"}, 193 + #endif // XRT_BUILD_DRIVER_HDK 186 194 187 195 #ifdef XRT_BUILD_DRIVER_ROKID 188 196 {ROKID_VID, ROKID_PID, rokid_found, "Rokid Air or Max", "rokid"},