From 8e838024d9ae6337cfcbdeb2c923030a182aa1f1 Mon Sep 17 00:00:00 2001 From: m-va Date: Mon, 17 Aug 2026 19:22:27 +0900 Subject: [PATCH] driver_vive: fix infinite loop when closing HIDAPI devices survive_vive_close() waits for every device to raise request_close, but the HIDAPI backend only ever sets that flag from HAPIReceiver() when hid_read() fails. survive_close_usb_device() closes the HID handles without setting it, so the wait loop never terminates. The libusb backend does not hit this because libusb_handle_events() drives the transfer-completion callbacks that raise the flag, and that call is compiled out under HIDAPI. Set the flag when the device is closed. This also lets survive_close() reach config_save(), so lighthouse calibration is persisted again instead of being lost on every run. Tested on Windows 11 x64 (MSVC, USE_HIDAPI=ON) with two Vive Trackers (2018) over USB and SteamVR 2.0 base stations: survive_simple_close() goes from never returning to completing immediately, and config.json gets its lighthouse0/1 entries so calibration survives a restart. Fixes #312 Assisted-by: Claude:claude-opus-5 --- src/driver_vive.hidapi.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/driver_vive.hidapi.h b/src/driver_vive.hidapi.h index 5d3d4a0d..ebcc491c 100644 --- a/src/driver_vive.hidapi.h +++ b/src/driver_vive.hidapi.h @@ -189,6 +189,15 @@ static inline void survive_close_usb_device(struct SurviveUSBInfo *usbInfo) { } free(usbInfo->handle); + usbInfo->handle = 0; + + // HIDAPI has no transfer-completion callback to raise request_close, + // this needs to be set manually to avoid hanging in survive_vive_close(). + for (size_t j = 0; j < usbInfo->interface_cnt; j++) { + usbInfo->interfaces[j].shutdown = 1; + usbInfo->interfaces[j].assoc_obj = 0; + } + usbInfo->request_close = true; #ifndef HID_NONBLOCKING for (int j = 0; j < MAX_INTERFACES_PER_DEVICE; j++) { OGJoinThread(sv->udev[i].interfaces->servicethread);