3D visionTroubleshooting

UVC video patch stops silently: fix duplicate kernel headers

Depth corrupted, color fine, unknown-format GUIDs in dmesg: your uvcvideo patch script failed silently on duplicate kernel headers. Find and fix it.

LumaSpec Vision8 min read Share on LinkedIn

On this page 9 sections
  1. 01The dmesg evidence: unknown GUIDs mean the stock driver
  2. 02Why the patch script exits without an error
  3. 03Worked example: two header trees on the reported 4.4.8 machine
  4. 04Prove which module you actually loaded
  5. 05Fix it: pin the header path to the running kernel
  6. 06Verify the depth stream, not just the module
  7. 07When the patch is not the problem
  8. 08After the next kernel update, expect it again
  9. 09Questions

Clean color frames, garbage depth, and a dmesg tail full of uvcvideo: Unknown video format lines: on a USB depth camera that combination means the kernel module was never patched, even though the patch script printed nothing wrong. Anyone standing a depth camera up on a Linux bench hits this sooner or later. In the reported case, an update had left two kernel header sets installed side by side: one for 4.4 and one for 4.4.8. The script's globbed header path expanded into both, stopped quietly at a copy step, and the stock module loaded. By the end you can read that evidence, prove which module is loaded, pin the rebuild to the running kernel's exact headers, and confirm the fix before blaming the camera.

The dmesg evidence: unknown GUIDs mean the stock driver

The stock uvcvideo driver reads a camera's format descriptors at plug-in and registers only the formats it knows. Depth and infrared streams announce themselves with vendor-defined format GUIDs, so the stock driver drops each one and logs a line like these from the reported machine:

uvcvideo: Unknown video format 5a564e49-2d90-4a58-920b-773f1f2c556b
uvcvideo: Unknown video format 495a4e49-1a66-a242-9065-d01814a8ef8a

The reported log carries four such lines, one per dropped stream format. The patched module knows these GUIDs and registers the streams instead. So the log decodes simply: USB enumeration succeeded, the driver that claimed the camera lacks the depth formats, and the patch never landed. The device itself is fine.

Note the timing. The lines appear when the camera is plugged in, not when the module loads, because enumeration is when formats are discovered. Reading dmesg straight after modprobe tells you nothing; replug, then read the tail.

A version mismatch between the patched source tree and the running kernel is the cousin failure, and UVC patch kernel mismatch: match the source tree covers it. That one usually stops the build with a printed error. This one hides better, because nothing prints at all.

Why the patch script exits without an error

Scripts that patch uvcvideo for depth cameras locate the headers with a globbed path. The reported run carried these lines:

CONFIG_LOCATION=/usr/src/linux-headers-$RAW_TAG*-generic/
cp $CONFIG_LOCATION/.config .
cp $CONFIG_LOCATION/Module.symvers .

The star is unquoted, so the shell expands CONFIG_LOCATION when it is used, not when it is assigned. Every directory under /usr/src whose name starts with linux-headers-4.4 and ends with -generic matches. After the update moved the machine from the distribution's 4.4 kernel to 4.4.8-040408-generic, both header packages were still installed, so the copies received paths into two different header trees. The run stopped at exactly that copy step, nothing after it executed, and no error reached the terminal.

With no patched module built, modprobe loaded the stock in-tree driver. That driver enumerated the camera and dropped the depth formats, which is the dmesg section above playing out again.

Worked example: two header trees on the reported 4.4.8 machine

Inputs, and where each comes from:

  • Running kernel release: 4.4.8-040408-generic, from uname -r on the reported machine.
  • Header pattern: /usr/src/linux-headers-$RAW_TAG*-generic/ with RAW_TAG=4.4, as the script defines it.
  • Header directories present: two, the distribution's 4.4 package and the 4.4.8-040408 package, the reported cause.

The rule in words: an unquoted glob in a shell variable expands at use time, producing one path per matching directory in alphabetical order. Every build step that assumes a single header directory then receives two.

The arithmetic:

  • Matches for linux-headers-4.4*-generic: 2 directories.
  • Directories the script expects: 1.
  • Extra expansions: 2 - 1 = 1.
  • Modules built for 4.4.8-040408-generic by this run: 0.
  • Modules modprobe can load afterwards: 1, the stock in-tree driver.

Result: no patched module exists for the running kernel, so every modprobe answers with the stock driver and depth stays dead.

Decision, with its threshold: run ls -d /usr/src/linux-headers-$(uname -r). One exact match targets the running release and the script works as written. Zero matches means the headers for this release are not installed; install them before patching. Two or more matches on the shortened pattern is the silent-failure case: pin CONFIG_LOCATION to the exact directory, with no star, and run the remaining steps by hand.

Prove which module you actually loaded

Four checks establish which driver answered modprobe, and none of them touches the camera:

You run You see It means
uname -r 4.4.8-040408-generic the release the build must target
modinfo -F vermagic uvcvideo a release string first the release the on-disk module was built for; it must equal uname -r
sudo modprobe uvcvideo FATAL: Module uvcvideo not found no module file exists for the running release
replug, then read the last 50 dmesg lines Unknown video format GUIDs the stock driver dropped the depth formats

modinfo reads the same file modprobe would load, so a vermagic that disagrees with uname -r convicts the build before you unload anything. A module built against a near-miss release normally refuses to insert, and dmesg logs an invalid-module-format complaint. In the reported case it never got that far: the build produced nothing, and the stock module answered.

Fix it: pin the header path to the running kernel

  1. Unload the loaded module: sudo modprobe -r uvcvideo.
  2. Record the exact running release: uname -r. On the reported machine it is 4.4.8-040408-generic.
  3. Confirm the matching header directory exists: ls -d /usr/src/linux-headers-$(uname -r). If the path is missing, install the headers for exactly this release first; a near-miss build will not insert.
  4. Pin the header location without the star: CONFIG_LOCATION=/usr/src/linux-headers-$(uname -r)/, one directory, fully expanded.
  5. Execute the steps that follow the copies in your script against this single path. On the reported machine, running the remaining steps by hand completed the patch where the script had stopped.
  6. Rebuild the module dependency index: sudo depmod -a.
  7. Load and check: sudo modprobe uvcvideo, replug the camera, and read the dmesg tail. The Unknown video format lines must be gone, and your capture program must list the depth and infrared streams.

Verify the depth stream, not just the module

A clean dmesg proves the formats registered; the frames prove the camera works. Open your capture program and check both streams: the depth image should hold a coherent range map, and the infrared image should show the projector's pattern lit across the scene. The reported log carried four dropped formats; after the fix, all four enumerate as selectable streams.

Give the camera a SuperSpeed port. The reported log shows the camera enumerating on a USB 2.0 hub and a SuperSpeed bus at once: the control interface rides the USB 2 link, and the streams need the SuperSpeed one, so a hub or a USB 2 port starves them. If two depth cameras share one host and the interface claim fails, Two depth cameras USB busy: fix the interface claim error walks that error.

When the patch is not the problem

The single most useful fact in the reported thread is that the camera had worked on another computer. That moves suspicion to the host. Work the ladder:

A camera on CoaXPress or Camera Link sits outside this story entirely: acquisition runs through PCIe frame grabbers, so there is no UVC patch to fail. If a bench refresh is due anyway, moving the interface removes this class of failure.

After the next kernel update, expect it again

A kernel update installs a fresh /lib/modules tree holding the stock module, so the patched driver disappears on the first reboot into the new release. Re-run the pinned-path build against the new release's headers, then repeat the vermagic check from the table above. The duplicate-header trap also returns, because the old header package stays installed next to the new one and the glob matches both. Keeping exactly one header set that matches the running release is the whole prevention.

More depth-camera bring-up notes, from trigger wiring to SDK crashes, sit on the 3D topic page. If you are choosing hardware too, the 3D sensors range and its camera finder list current depth and profile models, and the accessories finder covers the capture-card side. If a dmesg tail keeps disagreeing with this page, send it with your kernel release through the contact page and we will read it with you.

Questions

Why does color work while depth fails on an unpatched kernel?

The color stream announces itself with a standard video format the stock driver already knows, so it registers and streams normally. The depth and infrared streams use vendor-defined GUIDs the stock driver does not recognize, so it drops them and logs an Unknown video format line for each. The camera looks half-alive: enumeration succeeds, color works, depth is absent.

Where does modprobe find uvcvideo after a manual rebuild?

modprobe resolves a module name through the dependency index that depmod builds. The in-tree file lives at /lib/modules/$(uname -r)/kernel/drivers/media/usb/uvc/uvcvideo.ko, so a hand-copied module belongs in that same tree for the running release. Run sudo depmod -a after copying, then sudo modprobe uvcvideo; without the depmod step, modprobe can keep serving the old file or report the module as not found.

Does a version-mismatched module fail loudly or silently?

Loudly: a module whose vermagic disagrees with the running kernel refuses to insert, and dmesg logs an invalid-module-format complaint. The silent case here is different: no patched module was ever built, so modprobe kept loading the stock one without any complaint. That is why the vermagic check is the reliable test, not the absence of errors.

What does FATAL: Module uvcvideo not found actually mean?

modprobe found no uvcvideo.ko for the running release. Two causes cover most cases: the rebuilt module landed in a different release's /lib/modules tree, or the running kernel has no matching module tree at all because headers, kernel and boot entry disagree. Compare uname -r with the directory names under /lib/modules before rebuilding anything.