The open source OpenXR runtime
0
fork

Configure Feed

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

d/blubur_s1: Add skeleton driver for Blubur S1

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

authored by

Beyley Cardellio and committed by
Marge Bot
de6c4bff 366df8fd

+329
+3
CMakeLists.txt
··· 322 322 # Drivers to build (sorted) 323 323 option_with_deps(XRT_BUILD_DRIVER_ANDROID "Enable Android sensors driver" DEPENDS ANDROID) 324 324 option_with_deps(XRT_BUILD_DRIVER_ARDUINO "Enable Arduino input device with BLE" DEPENDS XRT_HAVE_DBUS) 325 + option_with_deps(XRT_BUILD_DRIVER_BLUBUR_S1 "Enable 3Glasses Blubur S1 device driver" DEPENDS XRT_HAVE_INTERNAL_HID) 325 326 option_with_deps(XRT_BUILD_DRIVER_DAYDREAM "Enable the Google Daydream View controller driver (BLE)" DEPENDS XRT_HAVE_DBUS) 326 327 option_with_deps(XRT_BUILD_DRIVER_DEPTHAI "DepthAI" DEPENDS depthai_FOUND) 327 328 option_with_deps(XRT_BUILD_DRIVER_EUROC "Enable EuRoC dataset driver for SLAM evaluation" DEPENDS XRT_HAVE_OPENCV "NOT MSVC") ··· 424 425 AVAILABLE_DRIVERS 425 426 "ANDROID" 426 427 "ARDUINO" 428 + "BLUBUR_S1" 427 429 "DAYDREAM" 428 430 "SIMULATED" 429 431 "HANDTRACKING" ··· 658 660 message(STATUS "#") 659 661 message(STATUS "# DRIVER_ANDROID: ${XRT_BUILD_DRIVER_ANDROID}") 660 662 message(STATUS "# DRIVER_ARDUINO: ${XRT_BUILD_DRIVER_ARDUINO}") 663 + message(STATUS "# DRIVER_BLUBUR_S1: ${XRT_BUILD_DRIVER_BLUBUR_S1}") 661 664 message(STATUS "# DRIVER_DAYDREAM: ${XRT_BUILD_DRIVER_DAYDREAM}") 662 665 message(STATUS "# DRIVER_DEPTHAI: ${XRT_BUILD_DRIVER_DEPTHAI}") 663 666 message(STATUS "# DRIVER_EUROC: ${XRT_BUILD_DRIVER_EUROC}")
+9
src/xrt/drivers/CMakeLists.txt
··· 21 21 target_link_libraries(drv_cemu PRIVATE xrt-interfaces aux_generated_bindings_helpers aux_util) 22 22 list(APPEND ENABLED_HEADSET_DRIVERS drv_cemu) 23 23 24 + if(XRT_BUILD_DRIVER_BLUBUR_S1) 25 + add_library( 26 + drv_blubur_s1 STATIC blubur_s1/blubur_s1_hmd.c blubur_s1/blubur_s1_interface.h 27 + blubur_s1/blubur_s1_prober.c 28 + ) 29 + target_link_libraries(drv_blubur_s1 PRIVATE xrt-interfaces aux_util aux_os) 30 + list(APPEND ENABLED_DRIVERS blubur_s1) 31 + endif() 32 + 24 33 if(XRT_BUILD_DRIVER_DAYDREAM) 25 34 add_library( 26 35 drv_daydream STATIC daydream/daydream_device.c daydream/daydream_device.h
+189
src/xrt/drivers/blubur_s1/blubur_s1_hmd.c
··· 1 + // Copyright 2025, Beyley Cardellio 2 + // SPDX-License-Identifier: BSL-1.0 3 + /*! 4 + * @file 5 + * @brief Implementation of Blubur S1 HMD driver. 6 + * @author Beyley Cardellio <ep1cm1n10n123@gmail.com> 7 + * @ingroup drv_blubur_s1 8 + */ 9 + 10 + #include "math/m_api.h" 11 + #include "math/m_mathinclude.h" 12 + 13 + #include "util/u_device.h" 14 + #include "util/u_distortion_mesh.h" 15 + #include "util/u_misc.h" 16 + #include "util/u_time.h" 17 + 18 + #include "blubur_s1_interface.h" 19 + #include "blubur_s1_internal.h" 20 + 21 + 22 + static struct blubur_s1_hmd * 23 + blubur_s1_hmd(struct xrt_device *xdev) 24 + { 25 + return (struct blubur_s1_hmd *)xdev; 26 + } 27 + 28 + static void 29 + blubur_s1_hmd_destroy(struct xrt_device *xdev) 30 + { 31 + struct blubur_s1_hmd *hmd = blubur_s1_hmd(xdev); 32 + free(hmd); 33 + } 34 + 35 + static xrt_result_t 36 + blubur_s1_hmd_compute_distortion( 37 + struct xrt_device *xdev, uint32_t view, float u, float v, struct xrt_uv_triplet *out_result) 38 + { 39 + float x = u * 2.0f - 1.0f; 40 + float y = v * 2.0f - 1.0f; 41 + 42 + float r2 = x * x + y * y; 43 + float r = sqrtf(r2); 44 + float r3 = r2 * r; 45 + float r4 = r2 * r2; 46 + float r5 = r4 * r; 47 + 48 + float radial = (0.5978f * r5) - (0.7257f * r4) + (0.504f * r3) - (0.0833f * r2) + (0.709f * r) - 0.00006f; 49 + 50 + struct xrt_vec2 result = { 51 + .x = (x * radial) / 2.0f + 0.5f, 52 + .y = (y * radial) / 2.0f + 0.5f, 53 + }; 54 + out_result->r = result; 55 + out_result->g = result; 56 + out_result->b = result; 57 + 58 + return XRT_SUCCESS; 59 + } 60 + 61 + static xrt_result_t 62 + blubur_s1_hmd_update_inputs(struct xrt_device *xdev) 63 + { 64 + return XRT_SUCCESS; 65 + } 66 + 67 + static xrt_result_t 68 + blubur_s1_hmd_get_tracked_pose(struct xrt_device *xdev, 69 + enum xrt_input_name name, 70 + int64_t at_timestamp_ns, 71 + struct xrt_space_relation *out_relation) 72 + { 73 + if (name != XRT_INPUT_GENERIC_HEAD_POSE) { 74 + return XRT_ERROR_INPUT_UNSUPPORTED; 75 + } 76 + 77 + // TODO: track pose 78 + *out_relation = (struct xrt_space_relation){ 79 + .relation_flags = 0, 80 + }; 81 + 82 + return XRT_SUCCESS; 83 + } 84 + 85 + static xrt_result_t 86 + blubur_s1_hmd_get_presence(struct xrt_device *xdev, bool *presence) 87 + { 88 + // TODO: read the presence sensor from the device 89 + *presence = true; 90 + 91 + return XRT_SUCCESS; 92 + } 93 + 94 + static xrt_result_t 95 + blubur_s1_get_view_poses(struct xrt_device *xdev, 96 + const struct xrt_vec3 *default_eye_relation, 97 + int64_t at_timestamp_ns, 98 + uint32_t view_count, 99 + struct xrt_space_relation *out_head_relation, 100 + struct xrt_fov *out_fovs, 101 + struct xrt_pose *out_poses) 102 + { 103 + return u_device_get_view_poses(xdev, default_eye_relation, at_timestamp_ns, view_count, out_head_relation, 104 + out_fovs, out_poses); 105 + } 106 + 107 + struct blubur_s1_hmd * 108 + blubur_s1_hmd_create(struct os_hid_device *dev, const char *serial) 109 + { 110 + struct blubur_s1_hmd *hmd = 111 + U_DEVICE_ALLOCATE(struct blubur_s1_hmd, U_DEVICE_ALLOC_HMD | U_DEVICE_ALLOC_TRACKING_NONE, 1, 0); 112 + if (hmd == NULL) { 113 + return NULL; 114 + } 115 + 116 + hmd->base.destroy = blubur_s1_hmd_destroy; 117 + hmd->base.name = XRT_DEVICE_GENERIC_HMD; 118 + hmd->base.device_type = XRT_DEVICE_TYPE_HMD; 119 + 120 + const int view_size = 1440; 121 + 122 + hmd->base.hmd->screens[0].w_pixels = view_size * 2; 123 + hmd->base.hmd->screens[0].h_pixels = view_size; 124 + hmd->base.hmd->screens[0].nominal_frame_interval_ns = 1000000000LLU / 120; // 120hz 125 + 126 + hmd->base.hmd->view_count = 2; 127 + hmd->base.hmd->views[0] = (struct xrt_view){ 128 + .viewport = 129 + { 130 + .x_pixels = 0, 131 + .y_pixels = 0, 132 + .w_pixels = view_size, 133 + .h_pixels = view_size, 134 + }, 135 + .display = 136 + { 137 + .w_pixels = view_size, 138 + .h_pixels = view_size, 139 + }, 140 + .rot = u_device_rotation_ident, 141 + }; 142 + hmd->base.hmd->views[1] = (struct xrt_view){ 143 + .viewport = 144 + { 145 + .x_pixels = view_size, 146 + .y_pixels = 0, 147 + .w_pixels = view_size, 148 + .h_pixels = view_size, 149 + }, 150 + .display = 151 + { 152 + .w_pixels = view_size, 153 + .h_pixels = view_size, 154 + }, 155 + .rot = u_device_rotation_ident, 156 + }; 157 + 158 + hmd->base.hmd->blend_modes[0] = XRT_BLEND_MODE_OPAQUE; 159 + hmd->base.hmd->blend_mode_count = 1; 160 + 161 + // TODO: what's the real FOV? 162 + hmd->base.hmd->distortion.fov[0] = (struct xrt_fov){ 163 + .angle_left = 45.0f * (M_PI / 180.0f), 164 + .angle_right = 45.0f * (M_PI / 180.0f), 165 + .angle_up = 45.0f * (M_PI / 180.0f), 166 + .angle_down = 45.0f * (M_PI / 180.0f), 167 + }; 168 + hmd->base.hmd->distortion.fov[1] = hmd->base.hmd->distortion.fov[0]; 169 + 170 + hmd->base.hmd->distortion.models = XRT_DISTORTION_MODEL_COMPUTE; 171 + hmd->base.hmd->distortion.preferred = XRT_DISTORTION_MODEL_COMPUTE; 172 + hmd->base.compute_distortion = blubur_s1_hmd_compute_distortion; 173 + u_distortion_mesh_fill_in_compute(&hmd->base); 174 + 175 + snprintf(hmd->base.str, XRT_DEVICE_NAME_LEN, "Blubur S1"); 176 + snprintf(hmd->base.serial, XRT_DEVICE_NAME_LEN, "%s", serial); 177 + 178 + hmd->base.supported.position_tracking = true; 179 + hmd->base.supported.presence = true; 180 + 181 + hmd->base.inputs[0].name = XRT_INPUT_GENERIC_HEAD_POSE; 182 + 183 + hmd->base.update_inputs = blubur_s1_hmd_update_inputs; 184 + hmd->base.get_tracked_pose = blubur_s1_hmd_get_tracked_pose; 185 + hmd->base.get_presence = blubur_s1_hmd_get_presence; 186 + hmd->base.get_view_poses = blubur_s1_get_view_poses; 187 + 188 + return hmd; 189 + }
+56
src/xrt/drivers/blubur_s1/blubur_s1_interface.h
··· 1 + // Copyright 2025, Beyley Cardellio 2 + // SPDX-License-Identifier: BSL-1.0 3 + /*! 4 + * @file 5 + * @brief Interface to Blubur S1 driver code. 6 + * @author Beyley Cardellio <ep1cm1n10n123@gmail.com> 7 + * @ingroup drv_blubur_s1 8 + */ 9 + 10 + #pragma once 11 + 12 + #include "xrt/xrt_device.h" 13 + #include "xrt/xrt_prober.h" 14 + 15 + #ifdef __cplusplus 16 + extern "C" { 17 + #endif 18 + 19 + 20 + #define BLUBUR_S1_VID 0x2b1c 21 + #define BLUBUR_S1_PID 0x0001 22 + 23 + struct blubur_s1_hmd; 24 + 25 + /*! 26 + * Probing function for Blubur S1 devices. 27 + * 28 + * @ingroup drv_blubur_s1 29 + * @see xrt_prober_found_func_t 30 + */ 31 + int 32 + blubur_s1_found(struct xrt_prober *xp, 33 + struct xrt_prober_device **devices, 34 + size_t device_count, 35 + size_t index, 36 + cJSON *attached_data, 37 + struct xrt_device **out_xdev); 38 + 39 + /*! 40 + * Creates a Blubur S1 HMD device from an opened HID handle. 41 + * 42 + * @ingroup drv_blubur_s1 43 + */ 44 + struct blubur_s1_hmd * 45 + blubur_s1_hmd_create(struct os_hid_device *dev, const char *serial); 46 + 47 + 48 + /*! 49 + * @dir drivers/blubur_s1 50 + * 51 + * @brief @ref drv_blubur_s1 files. 52 + */ 53 + 54 + #ifdef __cplusplus 55 + } 56 + #endif
+18
src/xrt/drivers/blubur_s1/blubur_s1_internal.h
··· 1 + // Copyright 2025, Beyley Cardellio 2 + // SPDX-License-Identifier: BSL-1.0 3 + /*! 4 + * @file 5 + * @brief Internal Blubur S1 driver definitions. 6 + * @author Beyley Cardellio <ep1cm1n10n123@gmail.com> 7 + * @ingroup drv_blubur_s1 8 + */ 9 + 10 + #pragma once 11 + 12 + #include "blubur_s1_interface.h" 13 + 14 + 15 + struct blubur_s1_hmd 16 + { 17 + struct xrt_device base; 18 + };
+42
src/xrt/drivers/blubur_s1/blubur_s1_prober.c
··· 1 + // Copyright 2025, Beyley Cardellio 2 + // SPDX-License-Identifier: BSL-1.0 3 + /*! 4 + * @file 5 + * @brief Implementation of Blubur S1 prober code. 6 + * @author Beyley Cardellio <ep1cm1n10n123@gmail.com> 7 + * @ingroup drv_blubur_s1 8 + */ 9 + 10 + #include "blubur_s1_interface.h" 11 + #include "blubur_s1_internal.h" 12 + 13 + 14 + int 15 + blubur_s1_found(struct xrt_prober *xp, 16 + struct xrt_prober_device **devices, 17 + size_t device_count, 18 + size_t index, 19 + cJSON *attached_data, 20 + struct xrt_device **out_xdev) 21 + { 22 + struct xrt_prober_device *dev = devices[index]; 23 + 24 + struct os_hid_device *hid = NULL; 25 + int result = xrt_prober_open_hid_interface(xp, dev, 0, &hid); 26 + if (result != 0) { 27 + return -1; 28 + } 29 + 30 + // TODO: figure out how to get the actual serial number of the device, since the official driver has multiple 31 + // methods, and the string descriptor doesn't work on the unit used for development. 32 + char serial[32] = {0}; 33 + snprintf(serial, sizeof(serial), "%04x:%04x", dev->vendor_id, dev->product_id); 34 + 35 + struct blubur_s1_hmd *hmd = blubur_s1_hmd_create(hid, serial); 36 + if (hmd == NULL) { 37 + return -1; 38 + } 39 + *out_xdev = &hmd->base; 40 + 41 + return 1; 42 + }
+4
src/xrt/targets/common/CMakeLists.txt
··· 72 72 target_link_libraries(target_lists PRIVATE drv_arduino) 73 73 endif() 74 74 75 + if(XRT_BUILD_DRIVER_BLUBUR_S1) 76 + target_link_libraries(target_lists PRIVATE drv_blubur_s1) 77 + endif() 78 + 75 79 target_link_libraries(target_lists PRIVATE drv_cemu) 76 80 77 81 if(XRT_BUILD_DRIVER_DAYDREAM)
+8
src/xrt/targets/common/target_lists.c
··· 16 16 #include "arduino/arduino_interface.h" 17 17 #endif 18 18 19 + #ifdef XRT_BUILD_DRIVER_BLUBUR_S1 20 + #include "blubur_s1/blubur_s1_interface.h" 21 + #endif 22 + 19 23 #ifdef XRT_BUILD_DRIVER_SIMULATED 20 24 #include "simulated/simulated_interface.h" 21 25 #endif ··· 191 195 #ifdef XRT_BUILD_DRIVER_RIFT 192 196 {OCULUS_VR_VID, OCULUS_DK2_PID, rift_found, "Rift (DK2)", "rift"}, 193 197 #endif // XRT_BUILD_DRIVER_RIFT 198 + 199 + #ifdef XRT_BUILD_DRIVER_BLUBUR_S1 200 + {BLUBUR_S1_VID, BLUBUR_S1_PID, blubur_s1_found, "Blubur S1", "blubur_s1"}, 201 + #endif // XRT_BUILD_DRIVER_BLUBUR_S1 194 202 195 203 #ifdef XRT_BUILD_DRIVER_ROKID 196 204 {ROKID_VID, ROKID_PID, rokid_found, "Rokid Air or Max", "rokid"},