You plug a USB camera into a machine that runs Windows and a Linux virtual machine, and the picture falls apart: the guest shows wrong or torn data, the serial control port disappears, and a popup asks which system should get the device every time you reconnect. None of that is a camera fault. It is USB ownership: a device belongs to exactly one host at a time, and a composite camera — a video interface plus a CDC serial interface — hands both to whoever wins. This guide walks the failure in the order you meet it: the popup, the missing serial port, the corrupt image, and the clean hand-over. It ends with the numbers that decide whether USB passthrough can carry your stream at all, and the case where you should not use it.
Why does the camera work on Windows but break inside the Linux VM?
Because USB passthrough moves the whole device to exactly one operating system, and Windows is still holding part of it: the guest then enumerates a half-open camera, the video interface streams garbage, and the CDC serial interface never binds to a driver.
A USB device answers to one host controller. The hypervisor's arbitration service detaches it from Windows and reattaches it to the guest's virtual controller — that is the whole mechanism, and its whole limit. This class of camera is a composite device: one USB device declaring a UVC video streaming interface and a CDC-ACM communications interface, the channel your control and debug traffic rides on. Passthrough moves the device, not the drivers. If a host-side viewer or serial utility still has an interface open, the handover is partial, and partial is exactly the wrong state you are seeing.
The same one-owner rule bites when two programs on one PC fight over a camera — read failed to claim USB interface: one client owns a USB3 Vision camera. Here is the quick map of the symptoms:
| Symptom in the guest | Most likely cause | Test | Fix |
|---|---|---|---|
| Popup on every plug-in | Arbiter has no rule for the device | — | Add a device filter, attach to the guest |
| Camera missing from lsusb | Windows still owns the device | lsusb | Close host software, re-attach |
| Image torn, streaked, garbled | Link fell back to USB 2 speed | lsusb -t | xHCI controller, USB 3 port |
| /dev/ttyACM0 never appears | CDC interface on host, or cdc_acm not bound | lsmod | Detach from host, modprobe cdc_acm |
| Stream drops mid-run | Host re-claims after resume or replug | dmesg | One owner per session, or move to GigE |
On the guest side the camera still needs its class drivers to bind, and a minimal guest image may lack them — start with UVC-compliant USB cameras on embedded Linux: skip the driver rebuild.
Why does Windows show a popup asking which system gets the camera?
That popup is the hypervisor's USB arbiter asking for an owner at hot-plug, because a USB device attaches to exactly one machine at a time — the host or the guest, never both at once.
Choosing the host in that dialog keeps every interface on Windows, and your guest sees nothing. Choosing the guest detaches it from Windows first, then enumerates it inside the VM. Each OS switch you make is a full detach and reattach cycle, so the wrong state after switching is simply the previous owner still holding claims that were never released.
You have two ways to stop answering the question by hand:
- Answer it once with a rule. Desktop hypervisors let you add a USB device filter, keyed on the camera's vendor and product ID, so every hot-plug routes straight to the guest with no dialog.
- Own the timing. Attach and detach from the VM's USB menu deliberately, and never while the other OS is mid-capture.
Why did the CDC serial port vanish when both systems are running?
Because the CDC interface stayed on the Windows side, or the guest never bound cdc_acm to it: check ownership first with lsusb, then binding with lsmod, and each test takes seconds.
Run these in order in the guest:
-
lsusb— the camera must be listed. If it is not, the host owns it and nothing downstream helps; detach from Windows first. -
lsmod | grep cdc_acm— no output means the module is not loaded. Load it withsudo modprobe cdc_acm. -
dmesg | grep ttyACM— after a successful bind you get a line readingttyACM0: USB ACM device. -
ls /dev/ttyACM*— the node your control software opens.
Most distributions autoload cdc_acm through udev the moment a CDC-ACM interface appears; a minimal guest image may ship without it. To confirm the device declares ACM at all, read its entry under /sys/kernel/debug/usb/devices and check the interface class. If lsusb lists the camera but no /dev/video* node appears, that is the same binding question on the video side — see camera shows in lsusb but no video device: check the USB class.
How do you hand the camera to the VM cleanly?
Close every host-side program that touches the camera, then attach it once with a permanent filter and confirm both interfaces bound in the guest — four steps, done in five minutes, and the set-up survives reboots.
- On the Windows host, close the camera vendor's viewer, any driver utility, and every program that auto-opens USB serial ports. Unplug the camera once and plug it back so Windows fully releases its claim.
- In the VM's USB settings, add a device filter for the camera, keyed on its vendor and product ID, so hot-plug no longer raises the popup.
- With the guest running, attach the camera from the VM's USB menu. Let it finish enumerating — both
uvcvideoandcdc_acmshould announce themselves indmesg. - Confirm the three artifacts before starting your software: the camera in
lsusb, a/dev/video*node, and/dev/ttyACM0. One missing artifact is one missing channel, and acquisition will hang on open.
Keep the physical link boring while you are at it. A 3 m USB3.0 high-flex cable such as the LS-CBL-0219 is built for the replugging a bench like this gets; a worn or unshielded cable produces the same torn frames and is the cheapest thing to rule out.
Why is the image data torn, streaked or garbled after passthrough?
Because the guest is carrying a USB 3 stream over a USB 2 path: 480 Mbit/s is about 40 MB/s of usable payload, and a 12 MP camera at 30 fps needs 360 MB/s — nine times what that link can move.
Check the negotiated speed, not the port label: lsusb -t prints the speed at the end of the camera's line. 5000M is SuperSpeed and the stream is viable; 480M is high speed and the stream cannot be right at full resolution. When a passthrough lands on a 2.0 virtual controller, enable the xHCI (USB 3) controller in the VM's USB settings, reattach, and read the line again. The identical failure on physical hardware — a camera on a USB 3 port falling back to 2.0 — is covered in camera enumerates as USB 2.0 on a USB 3.0 port: fix the link.
The arithmetic, with a real camera. The LS-CMR-0166 is a 12 MP USB3 area scan camera that outputs 4000 × 3000 pixels at 30 fps.
At USB 2 speed the wire carries 480 Mbit/s ÷ 8 = 60 MB/s raw, and protocol overhead leaves roughly 40 MB/s usable. 360 MB/s against 40 MB/s is 9× oversubscribed; the frame rate that link actually supports is 40 ÷ 12 MB per frame ≈ 3 fps. At USB 3 speed, 5 Gbit/s ÷ 8 = 625 MB/s raw and roughly 400 MB/s usable through a virtual controller — 360 MB/s fits with about 10 percent headroom, but there is little slack for scheduling jitter, so expect to drop the frame rate or crop the ROI if the guest is busy. Decision: at 480M the image cannot be correct at full resolution; fix the link, do not tune the camera.
- Sensor format
- 1/1.7"
- Interface
- USB3
- Resolution
- 12 MP
- Shutter
- Rolling
Is USB passthrough the right way to run a camera in a VM at all?
For bench bring-up, yes; for anything that runs unattended, no — put a GigE camera on a bridged network adapter instead, because Ethernet reaches the guest natively with no arbiter, no popup and no ownership fight.
A GigE camera is a node on the network, not a device on the host controller. Bridge the physical NIC into the guest, set the subnet, open the camera by IP — the addressing sequence is in GigE camera on a link-local address: open it by IP from Linux. The ceiling changes: 1000BASE-T carries 1 Gbit/s = 125 MB/s raw, about 100 MB/s usable after packet overhead, so a 12 MB frame tops out near 100 ÷ 12 ≈ 8 fps. The LS-CMR-0053 is that same IMX226 sensor behind a GigE interface at 9 fps. Same sensor, two interfaces:
| Specification | LS-CMR-0166 | LS-CMR-0053 |
|---|---|---|
| Sensor model | Sony IMX226 | IMX 226 |
| Resolution | 4000 × 3000 (12MP) | 4000 px x 3000 px |
| Max. frame rate | 30 fps | 9 fps |
| Pixel size | 1.85 μm | 1.85 μm x 1.85 μm |
| Shutter | rolling shutter | Rolling Shutter |
| Data interface | USB 3.0 | GigE |
| Pixel bit depth | 10-bit | 8 / 10 / 12 bits |
| Price | $560.00 | $560.00 |
All 2 share: Sensor size 1/1.7". Values as printed in each product's data sheet; open a part for its drawing and full specifications.
If the VM must host high-resolution streaming, 5GBASE-T and 10GigE cameras raise that ceiling and still need no passthrough — the trade-offs are in 5GBASE-T camera interface: bandwidth, cables and distance, and the wider interface decision is covered in the most reliable camera interface: GigE, USB3, Camera Link or CoaXPress. USB smart cameras and code readers hit the same ownership wall; their Ethernet-connected models publish results to any OS on the subnet and never touch a USB endpoint in the guest.
What should you check before every capture session?
Run a five-point check after each passthrough: one owner, two drivers bound, SuperSpeed negotiated, payload inside the link, and a clean dmesg — about two minutes from plug-in to first frame.
-
One owner.
lsusbin the guest lists the camera and the host shows it detached; every other check depends on this state. -
Both interfaces bound. A
/dev/video*node fromuvcvideoand/dev/ttyACM0fromcdc_acm; a missing node is a missing channel, and the tool hangs on open. -
SuperSpeed negotiated.
lsusb -tprints5000Mon the camera's line;480Mmeans the USB 2 ceiling applies. - Payload inside the link. Width × height × bytes × frame rate against the numbers above, for whichever speed the link negotiated.
- A clean dmesg. No disconnect or reset storm between attach and first frame; repeated reconnects mean the host is re-claiming the device and the filter is missing.
The decisions, case by case:
- Debugging a USB camera from a Linux guest: passthrough with a device filter, one owner, xHCI controller, payload under the link budget.
- Production capture inside a VM: a GigE camera on a bridged adapter; the host never owns anything.
- Serial control on Windows, video on Linux: not possible on one USB device — move both channels to the guest or use two devices.
To specify the whole station, the camera finder filters by interface, area scan cameras narrow to USB3 or GigE, cables by length and type, and the system configurator walks camera, lens, light and controller in order. If a link stays unstable after this checklist, send the lsusb, lsusb -t and dmesg output through the contact page and we will read it with you.
Questions
Can Windows and the Linux VM share one USB camera at the same time?
No. A USB device answers to one host controller, and the arbiter moves the whole device — it cannot split the video interface to the guest and the CDC serial interface to Windows. If your tooling needs the serial channel on Windows and the video on Linux, run both on the guest, or use two devices. A camera that takes serial control over the same USB interface it streams on removes the split entirely.
What speed should lsusb -t report for a USB 3 camera in the guest?
5000M on the camera's line. Anything reading 480M means the device negotiated high speed, which caps payload near 40 MB/s after overhead — enough for about a 5 MP stream at 8 fps, not a 12 MP stream at 30 fps. Fix the controller before touching exposure or frame-rate settings: enable the xHCI controller in the VM, reattach, and read the speed again.
Why does Windows find the serial port automatically when Linux needs cdc_acm?
Windows ships a class driver for USB CDC devices and loads it at enumeration without being asked. Linux splits the job: udev should autoload cdc_acm the moment a CDC interface appears, but on a minimal guest image the module or its udev rule can be missing, which leaves the interface driverless. That is why the fix is sudo modprobe cdc_acm plus a reattach, not a driver rebuild.
Does passing a camera through a hypervisor add latency to trigger-to-image time?
Yes, and jitter more than delay. Every isochronous and bulk transfer is scheduled twice — once by the guest stack and once by the host's real controller — so frame arrival wobbles in ways you cannot gate out in software. Free-run capture tolerates this; precise hardware triggering does not. If your inspection times exposure or strobe to the frame, keep the trigger physical: fire the camera from its controller rather than through the VM.
Which cameras avoid the passthrough problem entirely?
Anything that talks Ethernet. A GigE camera on a bridged adapter reaches the guest like any network device, with a payload ceiling near 100 MB/s on 1000BASE-T; 5GBASE-T and 10GigE models raise that ceiling in the same form factor. Ethernet smart cameras and code readers go further and send finished results over the subnet, so the guest never touches a USB endpoint at all. For a VM-hosted station, that is the sound default.

