From 359d2d499eb5ef170d5ede27c2fce79c8e8d7eba Mon Sep 17 00:00:00 2001 From: Beyley Cardellio Date: Tue, 10 Mar 2026 12:35:10 -0400 Subject: [PATCH] d/rift_sensor: Handle destruction through a frame node This ties in lifetimes a lot better with the d/uvc instances it holds. Part-of: --- src/xrt/drivers/rift_sensor/rift_sensor.c | 101 +++++++++++------- .../rift_sensor/rift_sensor_interface.h | 3 - .../rift_sensor/rift_sensor_internal.h | 12 ++- src/xrt/targets/common/target_builder_rift.c | 4 - 4 files changed, 74 insertions(+), 46 deletions(-) diff --git a/src/xrt/drivers/rift_sensor/rift_sensor.c b/src/xrt/drivers/rift_sensor/rift_sensor.c index 9584153fd..6f8556bd6 100644 --- a/src/xrt/drivers/rift_sensor/rift_sensor.c +++ b/src/xrt/drivers/rift_sensor/rift_sensor.c @@ -38,6 +38,60 @@ DEBUG_GET_ONCE_LOG_OPTION(rift_sensor_log, "RIFT_SENSOR_LOG", U_LOGGING_WARN) * Internal functions */ +static void +rift_sensor_destroy(struct rift_sensor *sensor) +{ + if (sensor->hid_dev) { + libusb_close(sensor->hid_dev); + + libusb_unref_device(libusb_get_device(sensor->hid_dev)); + } + + // @note uvc_fs_destroy is called by the xrt_frame_node destroy callback, so we don't need to call it here +} + +static void +rift_sensor_context_destroy(struct rift_sensor_context *context) +{ + os_thread_helper_destroy(&context->usb_thread); + + u_var_remove_root(context); + + for (size_t i = 0; i < context->num_sensors; i++) { + rift_sensor_destroy(&context->sensors[i]); + } + + libusb_exit(context->usb_ctx); + + if (context->sensors != NULL) { + free(context->sensors); + } + + free(context); + + return; +} + +static void +rift_sensor_context_node_break_apart(struct xrt_frame_node *node) +{ + struct rift_sensor_context *context = rift_sensor_context(node); + + SENSOR_DEBUG(context, "Breaking apart Rift sensor context node"); + + os_thread_helper_stop_and_wait(&context->usb_thread); +} + +static void +rift_sensor_context_node_destroy(struct xrt_frame_node *node) +{ + struct rift_sensor_context *context = rift_sensor_context(node); + + SENSOR_DEBUG(context, "Destroying Rift sensor context node, destroying sensors and freeing context."); + + rift_sensor_context_destroy(context); +} + static bool rift_sensor_setup_stream_parameters_callback(uint16_t vid, uint16_t pid, @@ -215,6 +269,7 @@ rift_sensor_read_calibration(struct rift_sensor_context *context, static int rift_sensor_create(struct rift_sensor_context *context, + struct xrt_frame_context *xfctx, struct rift_sensor *sensor, libusb_device *device, const struct libusb_device_descriptor *desc) @@ -231,7 +286,7 @@ rift_sensor_create(struct rift_sensor_context *context, sensor->hid_dev = device_handle; ret = uvc_fs_create(context->usb_ctx, device_handle, desc, rift_sensor_setup_stream_parameters_callback, - rift_sensor_post_init_callback, context, context->xfctx, &sensor->frame_server); + rift_sensor_post_init_callback, context, xfctx, &sensor->frame_server); if (ret < 0) { libusb_close(device_handle); SENSOR_ERROR(context, "Failed to create UVC frameserver, reason %d", ret); @@ -310,52 +365,22 @@ rift_sensor_usb_thread_run(void *user_ptr) return NULL; } -static void -rift_sensor_destroy(struct rift_sensor *sensor) -{ - if (sensor->hid_dev) { - libusb_close(sensor->hid_dev); - - libusb_unref_device(libusb_get_device(sensor->hid_dev)); - } - - // @note uvc_fs_destroy is called by the xrt_frame_node destroy callback, so we don't need to call it here -} - /* * Exported functions */ -void -rift_sensor_context_destroy(struct rift_sensor_context *context) -{ - os_thread_helper_destroy(&context->usb_thread); - - u_var_remove_root(context); - - for (size_t i = 0; i < context->num_sensors; i++) { - rift_sensor_destroy(&context->sensors[i]); - } - - libusb_exit(context->usb_ctx); - - if (context->sensors != NULL) { - free(context->sensors); - } - - free(context); - - return; -} - int rift_sensor_context_create(struct rift_sensor_context **out_context, struct xrt_frame_context *xfctx) { int ret; struct rift_sensor_context *context = U_TYPED_CALLOC(struct rift_sensor_context); + context->node = (struct xrt_frame_node){ + .next = NULL, + .break_apart = rift_sensor_context_node_break_apart, + .destroy = rift_sensor_context_node_destroy, + }; context->log_level = debug_get_log_option_rift_sensor_log(); - context->xfctx = xfctx; u_var_add_root(context, "Rift Sensors", false); u_var_add_log_level(context, &context->log_level, "Log Level"); @@ -427,7 +452,7 @@ rift_sensor_context_create(struct rift_sensor_context **out_context, struct xrt_ case OCULUS_DK2_SENSOR_PID: { struct rift_sensor *sensor = &context->sensors[context->num_sensors]; - ret = rift_sensor_create(context, sensor, device, &desc); + ret = rift_sensor_create(context, xfctx, sensor, device, &desc); if (ret < 0) { SENSOR_ERROR(context, "Failed to create sensor for device %x:%x, reason %d, skipping.", desc.idVendor, desc.idProduct, ret); @@ -449,6 +474,8 @@ rift_sensor_context_create(struct rift_sensor_context **out_context, struct xrt_ libusb_free_device_list(devices, 1); + xrt_frame_context_add(xfctx, &context->node); + *out_context = context; return 0; diff --git a/src/xrt/drivers/rift_sensor/rift_sensor_interface.h b/src/xrt/drivers/rift_sensor/rift_sensor_interface.h index 173b75dd7..ed4d387c9 100644 --- a/src/xrt/drivers/rift_sensor/rift_sensor_interface.h +++ b/src/xrt/drivers/rift_sensor/rift_sensor_interface.h @@ -26,9 +26,6 @@ struct rift_sensor; struct rift_sensor_context; -void -rift_sensor_context_destroy(struct rift_sensor_context *context); - int rift_sensor_context_create(struct rift_sensor_context **out_context, struct xrt_frame_context *xfctx); diff --git a/src/xrt/drivers/rift_sensor/rift_sensor_internal.h b/src/xrt/drivers/rift_sensor/rift_sensor_internal.h index c1bc9017e..4f4ca2374 100644 --- a/src/xrt/drivers/rift_sensor/rift_sensor_internal.h +++ b/src/xrt/drivers/rift_sensor/rift_sensor_internal.h @@ -7,6 +7,8 @@ * @ingroup drv_rift_sensor */ +#include "xrt/xrt_frame.h" + #include "os/os_threading.h" #include "rift_sensor_interface.h" @@ -16,17 +18,17 @@ struct rift_sensor_context { + struct xrt_frame_node node; + enum u_logging_level log_level; struct libusb_context *usb_ctx; - struct xrt_frame_context *xfctx; struct rift_sensor *sensors; size_t num_sensors; struct os_thread_helper usb_thread; }; - struct rift_sensor { enum rift_variant variant; @@ -83,3 +85,9 @@ struct rift_sensor_cv1_calib SIZE_ASSERT(struct rift_sensor_cv1_calib, 128); #pragma pack(pop) + +static struct rift_sensor_context * +rift_sensor_context(struct xrt_frame_node *node) +{ + return container_of(node, struct rift_sensor_context, node); +} diff --git a/src/xrt/targets/common/target_builder_rift.c b/src/xrt/targets/common/target_builder_rift.c index e1eee5cb3..bfc8bb333 100644 --- a/src/xrt/targets/common/target_builder_rift.c +++ b/src/xrt/targets/common/target_builder_rift.c @@ -300,10 +300,6 @@ rift_destroy(struct xrt_builder *xb) struct rift_builder *rb = rift_builder(xb); #ifdef XRT_BUILD_DRIVER_RIFT_SENSOR - if (rb->sensor_context) { - rift_sensor_context_destroy(rb->sensor_context); - } - if (rb->sensors) { free(rb->sensors); }