survive_plugins.unix.h: use .dylib extension and _NSGetExecutablePath()
on Apple. Also fixes a latent Linux bug where readlink() return value
was used as an array index without checking for error (-1).
CMakeLists.txt: find hidapi on Apple via pkg-config rather than
hardcoded Homebrew paths, which differ between Apple Silicon
(/opt/homebrew) and Intel (/usr/local).
cn_matrix.h: replace <malloc.h> with <stdlib.h> unconditionally, but
guard the re-inclusion of <malloc.h> with _WIN32. <malloc.h> does not
exist on macOS; <stdlib.h> provides malloc on all platforms. MSVC does
not declare alloca in <stdlib.h> — it lives in <malloc.h>.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SV_ERROR with SURVIVE_ERROR_HARWARE_FAULT crashes the process when an
unrecognised USB lightcap report ID is received. New tracker firmware
routinely emits report IDs that older libsurvive versions do not know;
crashing on an unrecognised ID makes libsurvive incompatible with any
firmware newer than it was built against.
The adjacent VIVE_REPORT_USB_TRACKER_LIGHTCAP_V1 case already uses
SV_INFO and ignores the packet. Apply the same treatment to the unknown
case: log a warning and continue so tracking on all known report types
is unaffected.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
A stalled USB endpoint must be cleared before resubmitting a transfer.
Without libusb_clear_halt(), libusb_submit_transfer() will return
LIBUSB_ERROR_PIPE (-9) on any endpoint left halted from a previous
session or failed transfer, causing the interface attachment to fail.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
MP_MAXITER (return code 5) means the solver exhausted its iteration
budget without converging. The current code treats this as success
(res <= 0 is false), so the unconverged — and potentially wrong —
lighthouse positions are written to disk via survive_recording and
the GSS result is accepted.
On the next launch those positions are loaded as the starting point
for calibration. If the unconverged solve is significantly wrong,
all subsequent tracking is corrupted and the only recovery is to
delete config.json.
Adding res == MP_MAXITER to the failure condition rejects unconverged
GSS solves the same way as explicit solver errors.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Cap dt at 0.05s (5x the normal ~8ms IMU interval) before computing the
power series. State prediction still uses the real dt; only uncertainty
growth (Q matrix) is bounded. Without this cap, a gap of ~1s yields
t^7 = 1.0 which inflates Q enough to cause NaN/Inf in the filter on the
next update (observed as a quatrotateabout assertion failure on cold start
or blackout recovery). This matches standard practice for discretised
continuous-time process noise models where large gaps should widen
uncertainty to a finite maximum rather than to infinity.
Fixes: tracker freezes after lighthouse occlusion / blackout recovery
(collabora/libsurvive#346)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
integration_variance[16] is stack-allocated but variance_tracker_calc()
may not write all elements when the tracker had zero observations
(counts == 0 or variance.size == 0). The uninitialized array is then
read by SV_VERBOSE via LINMATH_VEC7_EXPAND / LINMATH_VEC6_EXPAND.
Found by MSan when running test_replays.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
`off64_t` is not a language defined type and is not available everywhere. Instead
the function should use `z_off_t` which is defined by zlib (and is most likely
`off_t`)
As tested with a HTC Vive Pro Eye + Wand controllers, this removes
a warning about unknown headset name for the "T20" device.
More importantly it fixes input mappings of the Wand controllers
delivered with the HMD:
- Grip buttons now work. Before they were dead.
- Menu buttons now work. Before they were dead.
- Touching the touchpad correctly registers as touch instead of click.
Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>