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: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2780>
This commit is contained in:
Beyley Cardellio committed 2026-03-10 14:57:13 -04:00
1 parent 3b03be5f2b
commit 359d2d499e
4 files changed
+74 -46

No files matched your search

+64 -37
View File
@@ -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;
@@ -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);
@@ -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);
}
@@ -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);
}