Linux UVC 小工具驱动程序

发布于:2025-02-11 ⋅ 阅读:(53) ⋅ 点赞:(0)

概述

UVC Gadget 驱动程序是用于USB 连接设备端硬件的驱动程序。它旨在在具有 USB 设备端硬件(例如带有 OTG 端口的主板)的 Linux 系统上运行。

在设备系统上,一旦驱动程序被绑定,它就会显示为具有输出功能的 V4L2 设备。

在主机端(通过 USB 电缆连接后),运行 UVC Gadget 驱动程序并由适当的用户空间程序控制的设备应显示为符合 UVC 规范的相机,并可与任何设计用于处理它们的程序配合使用。设备系统上运行的用户空间程序可以将来自各种来源的图像缓冲区排队,以通过 USB 连接进行传输。通常,这意味着从相机传感器外围设备转发缓冲区,但缓冲区的来源完全取决于用户空间配套程序。

配置设备内核

USB_CONFIGFS、USB_LIBCOMPOSITE、USB_CONFIGFS_F_UVC 和 USB_F_UVC 才能启用对 UVC 小工具的支持。

通过 configfs 配置小工具

UVC Gadget 需要使用 UVC 功能通过 configfs 进行配置。这提供了相当大的灵活性,因为许多 UVC 设备的设置都可以通过这种方式控制。

假设

本节假设您已在/sys/kernel/config处挂载 configfs并创建了小工具作为/sys/kernel/config/usb_gadget/g1。

UVC 功能

第一步是创建 UVC 功能:

# These variables will be assumed throughout the rest of the document
CONFIGFS="/sys/kernel/config"
GADGET="$CONFIGFS/usb_gadget/g1"
FUNCTION="$GADGET/functions/uvc.0"

mkdir -p $FUNCTION

格式和框架

您必须配置小工具,告诉它您支持哪些格式,以及每种格式支持的帧大小和帧间隔。在当前实现中,小工具无法拒绝设置主机指示其设置的格式,因此准确完成此步骤非常重要,以确保主机永远不会请求无法提供的格式。

格式是在 streaming/uncompressed 和 streaming/mjpeg configfs 组下创建的,其中帧大小是在以下结构的格式下创建的:

uvc.0 +
      |
      + streaming +
                  |
                  + mjpeg +
                  |       |
                  |       + mjpeg +
                  |            |
                  |            + 720p
                  |            |
                  |            + 1080p
                  |
                  + uncompressed +
                                 |
                                 + yuyv +
                                        |
                                        + 720p
                                        |
                                  

然后,可以为每帧配置宽度和高度,以及存储单个帧所需的最大缓冲区大小,最后为该格式和帧大小配置支持的帧间隔。宽度和高度以像素为单位枚举,帧间隔以 100ns 为单位。例如,要为每个帧大小创建具有 2、15 和 100 fps 帧间隔的上述结构,您可以执行以下操作:

create_frame() {
        # Example usage:
        # create_frame <width> <height> <group> <format name>

        WIDTH=$1
        HEIGHT=$2
        FORMAT=$3
        NAME=$4

        wdir=$FUNCTION/streaming/$FORMAT/$NAME/${HEIGHT}p

        mkdir -p $wdir
        echo $WIDTH > $wdir/wWidth
        echo $HEIGHT > $wdir/wHeight
        echo $(( $WIDTH * $HEIGHT * 2 )) > $wdir/dwMaxVideoFrameBufferSize
        cat <<EOF > $wdir/dwFrameInterval
666666
100000
5000000
EOF
}

create_frame 1280 720 mjpeg mjpeg
create_frame 1920 1080 mjpeg mjpeg
create_frame 1280 720 uncompressed yuyv
create_frame 1920 1080 uncompressed yuyv

目前支持的唯一未压缩格式是 YUYV。

颜色匹配描述符

您可以为您创建的每种格式指定一些色度测定信息。此步骤是可选的,如果跳过此步骤,将包含默认信息;这些默认值遵循 UVC 规范的颜色匹配描述符部分中定义的值。

要创建颜色匹配描述符,请创建一个 configfs 项并将其三个属性设置为所需的设置,然后从您希望与之关联的格式链接到它:

# Create a new Color Matching Descriptor

mkdir $FUNCTION/streaming/color_matching/yuyv
pushd $FUNCTION/streaming/color_matching/yuyv

echo 1 > bColorPrimaries
echo 1 > bTransferCharacteristics
echo 4 > bMatrixCoefficients

popd

# Create a symlink to the Color Matching Descriptor from the format's config item
ln -s $FUNCTION/streaming/color_matching/yuyv $FUNCTION/streaming/uncompressed/yuyv

有关有效值的详细信息,请参阅 UVC 规范。请注意,存在默认颜色匹配描述符,任何未链接到其他颜色匹配描述符的格式都会使用该描述符。可以更改默认描述符的属性设置,因此请记住,如果您这样做,则会更改任何未链接到其他格式的默认设置。

标头链接

UVC 规范要求格式和帧描述符前面必须有标头,详细说明后面不同格式描述符的数量和累计大小等信息。此操作和类似操作在 configfs 中通过链接表示标头的 configfs 项和表示其他描述符的配置项来实现,方式如下:

mkdir $FUNCTION/streaming/header/h

# This section links the format descriptors and their associated frames
# to the header
cd $FUNCTION/streaming/header/h
ln -s ../../uncompressed/yuyv
ln -s ../../mjpeg/mjpeg

# This section ensures that the header will be transmitted for each
# speed's set of descriptors. If support for a particular speed is not
# needed then it can be skipped here.
cd ../../class/fs
ln -s ../../header/h
cd ../../class/hs
ln -s ../../header/h
cd ../../class/ss
ln -s ../../header/h
cd ../../../control
mkdir header/h
ln -s header/h class/fs
ln -s header/h class/ss

扩展单元支持

UVC 扩展单元 (XU) 基本上提供了一个独特的单元,可以向其发送控制设置和获取请求。这些控制请求的含义完全取决于实现,但可用于控制 UVC 规范之外的设置(例如启用或禁用视频效果)。XU 可以插入 UVC 单元链中,也可以自由悬挂。

配置扩展单元涉及在适当的目录中创建条目并适当地设置其属性,如下所示:

mkdir $FUNCTION/control/extensions/xu.0
pushd $FUNCTION/control/extensions/xu.0

# Set the bUnitID of the Processing Unit as the source for this
# Extension Unit
echo 2 > baSourceID

# Set this XU as the source of the default output terminal. This inserts
# the XU into the UVC chain between the PU and OT such that the final
# chain is IT > PU > XU.0 > OT
cat bUnitID > ../../terminal/output/default/baSourceID

# Flag some controls as being available for use. The bmControl field is
# a bitmap with each bit denoting the availability of a particular
# control. For example to flag the 0th, 2nd and 3rd controls available:
echo 0x0d > bmControls

# Set the GUID; this is a vendor-specific code identifying the XU.
echo -e -n "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" > guidExtensionCode

popd

bmControls 属性和 baSourceID 属性是多值属性。这意味着您可以向它们写入多个以换行符分隔的值。例如,要将第 1、2、9 和 10 个控件标记为可用,您需要向 bmControls 写入两个值,如下所示:

cat << EOF > bmControls
0x03
0x03
EOF

baSourceID 属性的多值性质掩盖了 XU 可以多输入的事实,但请注意,这目前没有显著的影响。

bControlSize 属性反映 bmControls 属性的大小,类似地,bNrInPins 反映 baSourceID 属性的大小。设置 bmControls 和 baSourceID 时,这两个属性都会自动增加/减少。也可以手动增加或减少 bControlSize,这会导致将条目截断为新大小,或用 0x00 填充条目,例如:

$ cat bmControls
0x03
0x05

$ cat bControlSize
2

$ echo 1 > bControlSize
$ cat bmControls
0x03

$ echo 2 > bControlSize
$ cat bmControls
0x03
0x00

bNrInPins 和 baSourceID 功能相同。

配置摄像机终端和处理单元支持的控件

UVC 链中的相机终端和处理单元还具有 bmControls 属性,其功能与扩展单元中的相同字段类似。然而,与 XU 不同的是,这些单元的位标志的含义是在 UVC 规范中定义的;您应该查阅“相机终端描述符”和“处理单元描述符”部分以了解标志的枚举。

# Set the Processing Unit's bmControls, flagging Brightness, Contrast
# and Hue as available controls:
echo 0x05 > $FUNCTION/control/processing/default/bmControls

# Set the Camera Terminal's bmControls, flagging Focus Absolute and
# Focus Relative as available controls:
echo 0x60 > $FUNCTION/control/terminal/camera/default/bmControls

如果您不设置这些字段,则默认情况下,相机终端的自动曝光模式控制和处理单元的亮度控制将被标记为可用;如果它们不受支持,您应该将字段设置为 0x00。

请注意,摄像头终端或处理单元的 bmControls 字段的大小由 UVC 规范固定,因此 bControlSize 属性在此处是只读的。

自定义字符串支持

可以在 USB configfs 中的通常位置定义字符串描述符,为 USB 设备的各个部分提供文本描述,然后可以从 UVC 函数根或扩展单元目录链接到该字符串描述符,以将这些字符串分配为描述符:

# Create a string descriptor in us-EN and link to it from the function
# root. The name of the link is significant here, as it declares this
# descriptor to be intended for the Interface Association Descriptor.
# Other significant link names at function root are vs0_desc and vs1_desc
# For the VideoStreaming Interface 0/1 Descriptors.

mkdir -p $GADGET/strings/0x409/iad_desc
echo -n "Interface Associaton Descriptor" > $GADGET/strings/0x409/iad_desc/s
ln -s $GADGET/strings/0x409/iad_desc $FUNCTION/iad_desc

# Because the link to a String Descriptor from an Extension Unit clearly
# associates the two, the name of this link is not significant and may
# be set freely.

mkdir -p $GADGET/strings/0x409/xu.0
echo -n "A Very Useful Extension Unit" > $GADGET/strings/0x409/xu.0/s
ln -s $GADGET/strings/0x409/xu.0 $FUNCTION/control/extensions/xu.0

中断端点

VideoControl 接口有一个可选的中断端点,默认情况下处于禁用状态。这旨在支持 UVC 的延迟响应控制集请求(应通过中断端点响应,而不是绑定端点 0)。目前不支持通过此端点发送数据,因此它处于禁用状态以避免混淆。如果您希望启用它,可以通过 configfs 属性进行启用:

echo 1 > $FUNCTION/control/enable_interrupt_ep

带宽配置

有三个属性可控制 USB 连接的带宽。这些属性位于函数根中,可在限制内设置:

# streaming_interval sets bInterval. Values range from 1..255
echo 1 > $FUNCTION/streaming_interval

# streaming_maxpacket sets wMaxPacketSize. Valid values are 1024/2048/3072
echo 3072 > $FUNCTION/streaming_maxpacket

# streaming_maxburst sets bMaxBurst. Valid values are 1..15
echo 1 > $FUNCTION/streaming_maxburst

此处传递的值将根据 UVC 规范限制为有效值(取决于 USB 连接的速度)。要了解设置如何影响带宽,您应该查阅 UVC 规范,但经验法则是增加 streaming_maxpacket 设置将提高带宽(从而提高最大可能的帧速率),而如果 USB 连接以超高速运行,则 streaming_maxburst 也是如此。增加 streaming_interval 将降低带宽和帧速率。

用户空间应用程序

UVC Gadget 驱动程序本身无法执行任何特别有趣的操作。它必须与一个用户空间程序配对,该程序响应 UVC 控制请求并填充缓冲区以排队到驱动程序创建的 V4L2 设备。如何实现这些功能取决于实现,超出了本文档的范围。


网站公告

今日签到

点亮在社区的每一天
去签到