If you are using the 5.15.136-tegra kernel, you can directly replace the uvcvideo.ko module without rebuilding the kernel:
- Locate the current
uvcvideo.komodule:modinfo uvcvideo | grep filename - Backup the existing module:
sudo cp /lib/modules/5.15.136-tegra/kernel/drivers/media/usb/uvc/uvcvideo.ko /lib/modules/5.15.136-tegra/kernel/drivers/media/usb/uvc/uvcvideo.ko.bak
- Replace it with the patched version:
sudo rmmod uvcvideo sudo cp path/to/new/uvcvideo.ko /lib/modules/$(uname -r)/kernel/drivers/media/usb/uvc/ sudo depmod -a sudo modprobe uvcvideo
Users often encounter errors like Not enough bandwidth for new device state or failures to initialize devices when running multiple USB cameras simultaneously on Linux. This issue persists even with compressed formats like MJPEG or low resolutions, preventing scaling up applications requiring multiple video streams.
- Shared Bandwidth: USB controllers have finite bandwidth shared among connected devices.
- Isochronous Transfers: Video streaming uses USB isochronous transfers, requiring guaranteed bandwidth.
- Peak Bandwidth Reservation: USB controllers reserve bandwidth based on the peak rate declared by the camera firmware, even if the actual data rate is lower.
- Problematic Firmware: Some cameras declare excessively high peak bandwidth requirements, saturating the USB controller's capacity.
- Check USB Topology: Use
lsusb -tto identify how cameras are connected. - Separate Devices: Connect cameras to different USB root hubs or controllers.
- Use Compression: Switch to compressed formats like MJPEG or H.264.
- Lower Resolution/Framerate: Request lower settings to reduce bandwidth.
- Use uvcvideo Quirks: Apply kernel module parameters like
quirks=....
To address the issue of excessive bandwidth reservation, a kernel patch was applied to modify the uvcvideo driver:
- Goal: Override the
dwMaxPayloadTransferSizeduring negotiation for compressed formats. - Patch Code:
// in the last part of function uvc_fixup_video_ctrl() if (format->flags & UVC_FMT_FLAG_COMPRESSED) { u32 bandwidth = 512 * 8; if (stream->dev->udev->speed == USB_SPEED_HIGH) bandwidth /= 8; ctrl->dwMaxPayloadTransferSize = bandwidth; }
- Build Process:
- Obtain kernel source matching the running kernel (
uname -r). - Modify
drivers/media/usb/uvc/uvc_video.cas shown above. - Update the
Makefileto ensureuvcvideois built as a module:obj-m += uvcvideo.o uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \ uvc_status.o uvc_isight.o uvc_debugfs.o uvc_metadata.o ifeq ($(CONFIG_MEDIA_CONTROLLER),y) uvcvideo-objs += uvc_entity.o endif obj-$(CONFIG_USB_VIDEO_CLASS) += uvcvideo.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
- Build the module:
make
- Install the module as described in the "Quick Start" section.
- Obtain kernel source matching the running kernel (
The patch bypasses the excessive bandwidth reservation, allowing multiple cameras to stream simultaneously. For example, 8 cameras (4 per USB controller) streaming 1280x720 MJPEG @ 30fps were successfully launched using GStreamer pipelines.
- This patch is specific to buggy camera firmware and affects all UVC devices using compressed formats.
- The fixed bandwidth value might be too low for other cameras or higher-quality streams.
- Kernel modifications require rebuilding/reinstalling the module after updates.
- This workaround bypasses standard USB bandwidth management and may cause instability if actual data rates exceed the forced low payload size.