How to use the UVC gadget driver in Linux

From RidgeRun Developer Wiki



UVC Gadget

UVC or USB Video Class is a USB specification created by the USB Implementers Forum (USB-IF) and it is intended to standardize the video streaming functionality on the USB, that is, if you want to create a USB embedded device capable of sending video over the USB port and compatible with most operating systems and applications, then you need to implement the UVC specification.

Linux-based operating systems as well as others, have support for UVC based devices such as webcams, acting as a host for the device. In the case of the device side, also known as the gadget, the driver support is usually proprietary depending on the manufacturer. The Linux kernel has added an implementation of a UVC gadget driver to its mainline in order to help developers to create Linux based devices with UVC support. Besides those efforts, the current UVC driver does not implement all the UVC specifications and it is quite hard to configure and use, depending heavily on a userspace application in order to complete the enumeration process and start the video streaming.

This wiki page shows you how to configure and use the Linux UVC gadget driver. The user has 2 ways of configuring a UVC gadget: using the g_webcam kernel module and through configfs. Following you will find the instructions for both methods.

Using kernel g_webcam module

The Webcam Gadget acts as a composite USB Audio and Video Class device. It provides a userspace API to process UVC control requests and stream video data to the host. In order to enable the module, make sure the CONFIG_USB_G_WEBCAM module is selected in kernel configuration:

Symbol: USB_G_WEBCAM [=m]
Type  : tristate
Prompt: USB Webcam Gadget
  Location:
    -> Device Drivers
      -> USB support (USB_SUPPORT [=y])
        -> USB Gadget Support (USB_GADGET [=m])
          -> USB Gadget precomposed configurations (<choice> [=m])
  Defined at drivers/usb/gadget/legacy/Kconfig:480
  Depends on: <choice> && VIDEO_DEV [=m]
  Selects: USB_LIBCOMPOSITE [=m] && VIDEOBUF2_VMALLOC [=n] && \
USB_F_UVC [=n]

After the module has been enabled and built, in order to use it you have to load it as follows:

modprobe g_webcam

After this, a new /dev/videoXdevice will be created that will be used by the user space application.

Using configfs

Configfs allow Userspace-driven kernel object configuration. Configfs is a ram-based filesystem that provides the converse of sysfs's functionality. Where sysfs is a filesystem-based view of kernel objects, configfs is a filesystem-based manager of kernel objects, or config_items.

A configfs config_item is created via an explicit userspace operation: mkdir. It is destroyed via rmdir. The attributes appear at mkdir time, and can be read or modified via reading and writing. Unlike sysfs, the lifetime of the representation is completely driven by userspace. The kernel modules backing the items must respond to this.

Enabling configfs

First, you have to make sure that configfs is enabled:

Symbol: USB_CONFIGFS [=m]
Type  : tristate
Prompt: USB Gadget functions configurable through configfs
  Location:
    -> Device Drivers
      -> USB support (USB_SUPPORT [=y])
        -> USB Gadget Support (USB_GADGET [=m])
  Defined at drivers/usb/gadget/Kconfig:220
  Depends on: USB_SUPPORT [=y] && USB_GADGET [=m]
  Selects: USB_LIBCOMPOSITE [=m]

Then, make sure the UVC function is also selected:

Symbol: USB_CONFIGFS_F_UVC [=y]
Type  : boolean
Prompt: USB Webcam function
  Location:
    -> Device Drivers
      -> USB support (USB_SUPPORT [=y])
        -> USB Gadget Support (USB_GADGET [=m])
          -> USB Gadget functions configurable through configfs (USB_CONFIGFS [=m])
  Defined at drivers/usb/gadget/Kconfig:445
  Depends on: USB_SUPPORT [=y] && USB_GADGET [=m] && \
USB_CONFIGFS [=m] && VIDEO_V4L2 [=m] && VIDEO_DEV [=m]

You can take a look at instructions on how to verify and mount configs.

Configuring UVC function

First, make sure the libcomposite module is loaded:

modprobe libcomposite


Then, in order to identify the configfs folder location you can run:

mount | grep configfs
configfs on /sys/kernel/config type configfs (rw,relatime)

Now let's set up some information for the device:

UDC=`ls /sys/class/udc`
UDC_ROLE=/sys/devices/platform/soc/78d9000.usb/ci_hdrc.0/role
CONFIGFS="/sys/kernel/config"
GADGET="$CONFIGFS/usb_gadget"
VID="0x0525"
PID="0x0102"
SERIAL="0123456789"
MANUF=$(hostname)
PRODUCT="UVC Gadget"

Let's start creating the device:

1. Create the gadget

mkdir -p $GADGET/g1

you will get the following:

ls /sys/kernel/config/usb_gadget/g1/
UDC  bDeviceClass  bDeviceProtocol  bDeviceSubClass  bMaxPacketSize0  bcdDevice  bcdUSB  configs  functions  idProduct	idVendor  os_desc  strings

2. Set vendor and product ID

cd $GADGET/g1
echo $VID > idVendor
echo $PID > idProduct

3. Create English string

mkdir -p strings/0x409

You will get the following contect:

ls strings/0x409/
manufacturer  product  serialnumber

4. Add manufacturer, serial number, and product information

echo $SERIAL > strings/0x409/serialnumber
echo $MANUF > strings/0x409/manufacturer
echo $PRODUCT > strings/0x409/product

5. Create configuration

mkdir configs/c.1

You will get the following:

ls configs/c.1/
MaxPower  bmAttributes	strings

6. Create English string for configuration

mkdir configs/c.1/strings/0x409

you will get the following:

ls configs/c.1/strings/0x409/
configuration

7. Create UVC gadget function

CONFIG="configs/c.1"
FUNCTION="uvc.0"
mkdir functions/$FUNCTION

You will get the following:

ls functions/uvc.0/
control  streaming  streaming_interval	streaming_maxburst  streaming_maxpacket

8. Add resolutions

mkdir -p functions/$FUNCTION/streaming/uncompressed/u/360p

you will get:

ls functions/uvc.0/streaming/
class  color_matching  header  mjpeg  uncompressed
ls functions/uvc.0/streaming/uncompressed/u/
360p  bAspectRatioX  bAspectRatioY  bBitsPerPixel  bDefaultFrameIndex  bmInterfaceFlags  bmaControls  guidFormat
ls functions/uvc.0/streaming/uncompressed/u/360p/
bmCapabilities	dwDefaultFrameInterval	dwFrameInterval  dwMaxBitRate  dwMaxVideoFrameBufferSize  dwMinBitRate	wHeight  wWidth

9. Add frame intervals to resolution

cat <<EOF > functions/$FUNCTION/streaming/uncompressed/u/360p/dwFrameInterval
666666
1000000
5000000
EOF

You will get:

cat functions/uvc.0/streaming/uncompressed/u/360p/dwFrameInterval 
666666
1000000
5000000

10. Create header

mkdir functions/$FUNCTION/streaming/header/h
cd functions/$FUNCTION/streaming/header/h
ln -s ../../uncompressed/u
cd ../../class/fs
ln -s ../../header/h
cd ../../class/hs
ln -s ../../header/h
cd ../../class/ss
ln -s ../../header/h
cd ../../../control
mkdir -p header/h
ln -s header/h class/fs
ln -s header/h class/ss
cd ../../../

11. Configure max packet size

echo 2048 > functions/$FUNCTION/streaming_maxpacket

12. Assign configuration to function

ln -s functions/$FUNCTION configs/c.1

13. Bind USB Device Controller (UDC)

echo $UDC > UDC

After this, a new /dev/videX device will be created that can be used by the user space application.

In order to disable the Gadget just do:

echo "" > UDC
echo peripheral > $UDC_ROLE

In case of OpenQ 410 for example, this is done by HW so this step is not needed. It can be checked as follows:

cat /sys/devices/platform/soc/78d9000.usb/ci_hdrc.0/role
gadget


For direct inquiries, please refer to the contact information available on our Contact page. Alternatively, you may complete and submit the form provided at the same link. We will respond to your request at our earliest opportunity.


Links to RidgeRun Resources and RidgeRun Artificial Intelligence Solutions can be found in the footer below.