Skip to content

Linux iso transfers crash Chromium with Invalid argument (22) — missing selectAlternateInterface after claimInterface #11

Description

@turbocrime

Summary

Camera.setMode({ depth: ... }) causes the Chromium USB utility process to crash on Linux. The same code works on macOS Chromium. Root cause is a missing dev.selectAlternateInterface(...) call after dev.claimInterface(...) in the camera worker.

Environment

  • OS: Fedora Asahi (Apple Silicon)
  • Browser: Chromium (Linux)
  • Device: Xbox 360 Kinect, vid 045e pid 02ae
  • @webnect/driver: 0.1.1
  • Host pre-reqs already in place: gspca_kinect blacklisted/unloaded, libfreenect-style udev rules granting user access to vid 045e. The device opens cleanly — no Access denied.

Symptom

chromium-browser.log excerpt at the moment Camera.setMode runs:

USB: usb_device_handle_usbfs.cc:168 Low-level transfer error: Invalid argument (22)
crashpad/snapshot/elf/elf_dynamic_array_reader.h:64 tag not found
crashpad/snapshot/elf/elf_dynamic_array_reader.h:64 tag not found
crashpad/snapshot/elf/elf_dynamic_array_reader.h:64 tag not found
crashpad/snapshot/elf/elf_dynamic_array_reader.h:64 tag not found

EINVAL from usbfs on URB submission, then crashpad fires ~25 ms later — the iso transfer takes down the USB process before the JS-side isochronousTransferIn() rejection can surface.

Same code paths on macOS Chromium stream depth frames without issue.

Root cause

In src/camera/worker/worker.ts, getDevice does:

if (!iface.claimed) {
  await dev.claimInterface(usbInterface);
}
return dev;

…and the caller goes straight into dev.isochronousTransferIn(...) via UnderlyingIsochronousTransferSource. Grep across src/ confirms there is zero selectAlternateInterface / alternateSetting usage anywhere in the driver.

macOS's IOUSBLib is permissive about this — it'll accept an iso transfer with the interface in its default alt setting. Linux's usbfs requires an explicit SET_INTERFACE ioctl to reserve iso bandwidth for the endpoint; without it the URB submission returns EINVAL and the Chromium USB utility process crashes (this isn't a graceful JS-level rejection on Linux — it kills the worker process).

Suggested fix

Add an explicit alt-setting selection after the claim:

if (!iface.claimed) {
  await dev.claimInterface(usbInterface);
}
await dev.selectAlternateInterface(usbInterface, 0);
return dev;

libfreenect src/cameras.c calls libusb_set_interface_alt_setting(udev->cam, 0, 0) for the camera interface, so alt 0 is the right starting point. Worth verifying against the device's USB descriptor in case the iso endpoints actually live on a different alt — if so, use that one.

Notes

macOS users won't observe a regression after this fix lands; it's a no-op on platforms that already tolerate the missing call.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions