本文基于rk3568 开发板 在之前文章基础上将探讨和学习UVC ,通过 Linux USB Gadget 配置系统 类配置linux 系统下如何配置UVC camera的配置, 欢迎技术和项目探讨。luoshanxuli2010@163.com。
一 USB 介绍
1.1 USB引脚定义
以USB 2.0的标准A型接口为例,它有4个引脚,从外到内分别是VCC(+5V电源)、D-(数据负)、D+(数据正)、GND(地)。其中D+和D-是一对差分信号线,用于数据传输。

OTG是USB 2.0引入的一项技术,允许设备在主机和从机之间动态切换。
ID接地(低电平)→(主机角色,Host)
ID悬空(高电平)→ (从机角色,Device)
1.2 USB 规范
OHCI: 全称为 Open Host Controller Interface
UHCI: 全称是 Universal Host Controller Interface, UHCI 是 Inter 主导的一个于 USB1.0/1.1 的标准,与 OHCI 不兼容
EHCI: 全称是 Enhanced Host Controller Interface,是 Inter 主导的一个用于 USB2.0 的 USB控制器标准
xHCI: 全称是 eXtensible Host Controller Interface,是目前最流行的 USB3.0 控制器标准,在速度、能效和虚拟化等方面比前三个都有较大的提高
USB Host:
通信的发起者和控制者。 它负责管理总线、检测设备的接入/移除、给设备供电(如果是 从总线取电)、发起所有通信请求、枚举设备 分配 地址。当手机连接电脑时,手机是 Device ,电脑是 Host。
USB Device :
通信的响应者和受控者。 它不能主动发起通信,只能被动地响应 主机的请求。它向主机 报告自己是什么设备(如键盘、U盘),并按照主机的指令进行数据传输。当手机连接U盘 通过OTG线)时,手机变成了 Host ,U盘是 Device
USB电气特性
USB 2.0定义了三种速度模式:低速(Low Speed)1.5Mbps、全速(Full Speed)12Mbps和高速(High Speed)480Mbps。
1.3 USB Gadget
USB Gadget 是让 Linux 设备充当 USB 外设(而不是主机)的机制。 Configfs 是一个基于 RAM 的虚拟文件系统,用于在运行时动态配置内核对象,无需重新编译内核。 手机连接电脑后,手机充当 U盘、摄像头、以太网卡。
Gadget 类型
|--------------|----------------|------------|------------|
| Gadget 类型 | 内核模块 | PC 识别为 | 用途 |
| Mass Storage | g_mass_storage | U 盘 | 文件传输 |
| Serial | g_serial | 串口 (COM) | 调试通信 |
| Ethernet | g_ether | 网卡 (RNDIS) | 网络共享 |
| UVC | g_webcam | 摄像头 | 视频传输 |
| HID | g_hid | 键盘/鼠标 | 输入设备 |
| ADB | functionfs | ADB 设备 | Android 调试 |
1.4 UVC 通信流程
Linux-4.19 UVC 通信流程V4L2 框架,实现与 UVC 应用程序进行 queue buf 和 dequeue buf 的操作。

USB DWC2 OTG 控制器调试接口
/sys/kernel/debug/[dwc2_controller_base_addr].usb

ep*in/out: 用于查询 Device 模式下,每个端点的状态信息;
fifo: 用于查询 DWC2 硬件FIFO的配置,如 RXFIFO Size,NPTXFIFO Size,每个端点的 TXFIFO Size; state: 用于查询 DWC2 控制器的中断 MASK寄存器,
Device 模式的控制和配置寄存器信息;
regdump: 打印 DWC2 控制器的所有寄存器状态信息;
testmode: 设置 USB 进入测试模式,主要用于 USB 眼图测试;
二. 硬件环境
2.1 RK3568 硬件
ATK-DLRK3568 提供 2 个原生的 USB2.0 HOST 接口,这两个 USB 接口都是支持高速模式,也就是 480Mbit/S。提供了 2 个 USB3.0 HOST 接口(OTG3.0+HOST3.0),其中一路用于连接 5G 模组,另外一路作为板载的 USB 3.0 接口。支持标准UVC Camera功能,最高支持4k预览(RK356X),支持USB复合设备稳定传输,支持智能电视或PC等多种终端设备预览。

2.2 USB3.0 HOST 接口
开发板的 1 路 USB3.0 HOST 接口, RK3568 有 2 个 USB3.0 HOST 接口,其中一路用于连接 5G 模组。这是另外一路,作为 USB3.0 HOST 接口,可以连接 USB 鼠标、键盘、 U 盘等设备
2.3 USB2.0 HOST 接口
开发板上两个 USB2.0 HOST 接口, RK3568 原生支持 2 路 USB2.0 HOST 外设,速度会比上面的 USB3.0 慢。可以通过这两个 USB2.0 HOST 接口连一些低速 USB 设备
2.3 电路图
ATKDL-RK3568 开发板上有一路 USB OTG 接口,使用的是 RK3568 的 USB3_OTG0 接口。此路 USB OTG 既可以作为主机(HOST),也可以作为从机(DEVICE),从而实现完整的 OTG功能

;
注意
-
DP/DM 必须分别串接 2.2 Ω 电阻,提⾼ DP/DM 的抗压/抗静电能⼒
-
如果要⽀持 USB Device 动态拔插检测和充电类型检测功能,则 VBUSDET 脚⼀定要连接到 USB Type-A 接口;
-
如果不需要⽀持 USB Device 动态拔插检测和充电类型检测功能,可以允许 VBUSDET 脚固 定拉⾼
-
USB3_OTG0_ID 未使⽤,悬空即可,芯⽚内部拉⾼到 1.8V
-
gpio-5 (vcc5v0-otg-regulator) out hi gpio-6 (vcc5v0-host-regulato) out hi
2.4 USB 子系统简介
在 Linux 系统中,提供了主机侧和设备侧视角的 USB 驱动框架及通用驱动程序。主机侧分为 USB Core、HOST 控制器驱动,HUB 驱动和各设备类驱动。设备侧分为 Gadget 框架、Devices 控制器驱动和各设备类 Function 驱动
从机(DEVICE)模式:
使用配套赠送的 USB Type-C 连接线连接 OTG 接口到 PC(电脑), USB Type-C 线会将 CC1 和 CC2 拉高,因此 USB3_OTG0_ID 线为高,表示 OTG 工作在从机模式
主机(HOST)模式:
如果要使用 OTG 的 HOST 功能,那么必须要使用到 Type-c OTG 先。Type-C OTG 线会将 CC1 和 CC2 拉低,因此 USB3_OTG0_ID 线为低,表示 OTG 工作在主机模式。 USB3_OTG0_ID 默认为低电平
三. RK3568 USB配置
3.1 RK3568 USB接口
RK3568 有两个 USB 2.0 PHY, USB 3.0 OTG 控制器和 USB 3.0 Host_1 的控制器分别使用 USB 2.0 Comb PHY_0 的 port0 和 port1; USB 2.0 Host_2 控制器和 USB 2.0 Host_3 控制器分别使用 USB 2.0 Comb PHY_1 的 port0 和 port1。
PHY 映射表
|----------------|------------|------|-----------------------------|------|
| 节点 | 地址 | 类型 | 速度 | 模式 |
| usb_host0_ehci | 0xfd800000 | EHCI | High Speed (480Mbps) | HOST |
| usb_host0_ohci | 0xfd840000 | OHCI | Full/Low Speed (12/1.5Mbps) | HOST |
| usb_host1_ehci | 0xfd880000 | EHCI | High Speed (480Mbps) | HOST |
| usb_host1_ohci | 0xfd8c0000 | OHCI | Full/Low Speed (12/1.5Mbps) | HOST |
|--------------------|-------|----------------|----------------------|
| PHY | Port | 控制器 | 接口类型 |
| USB 2.0 Comb PHY_0 | Port0 | DWC3 OTG | USB 3.0 OTG (Type-C) |
| | Port1 | USB 3.0 Host_1 | USB 3.0 HOST (5G模组) |
| USB 2.0 Comb PHY_1 | Port2 | USB 2.0 Host_2 | USB 2.0 HOST |
| | Port3 | USB 2.0 Host_3 | USB 2.0 HOST |
phy控制器映射地址
|----------|--------------|---------------------|-------------------|-------------------|
| PHY 节点 | PHY 子节点 | 对应控制器 | 地址 | 模式 |
| usb2phy0 | usbphy0_otg | usbdrd30 (DWC3) | 0xfcc00000 | OTG (Host/Device) |
| usb2phy1 | usbphy1_otg | usb_host0_ehci/ohci | 0xfd800000/840000 | Host Only |
| usb2phy1 | usbphy1_host | usb_host1_ehci/ohci | 0xfd880000/8c0000 | Host Only |
示意图

DTS 中的引用关系
/* USB 2.0 PHY 0 - 给 USB3 OTG 用 */
usb2phy0: usb2phy@fe8a0000 {
compatible = "rockchip,rk3568-usb2phy";
usb2phy0_otg: otg-port {
/* 连接到 usbdrd30 (DWC3) */
};
};
/* USB 2.0 PHY 1 - 给两个 USB2 Host 用 */
usb2phy1: usb2phy@fe8b0000 {
compatible = "rockchip,rk3568-usb2phy";
usb2phy1_otg: otg-port {
/* 连接到 usb_host0_ehci/ohci */
};
usb2phy1_host: host-port {
/* 连接到 usb_host1_ehci/ohci */
};
};
/* USB3 OTG 控制器 - UVC Gadget 用这个 */
usbdrd30: usbdrd@fcc00000 {
phys = <&usb2phy0_otg>; /* 引用 PHY */
};
|---------------------|-------------------------|---------------------|
| 用途 | 使用的 PHY | 使用的控制器 |
| UVC Gadget (Device) | usb2phy0 → usbphy0_otg | usbdrd30 (DWC3) |
| 接 USB 外设 | usb2phy1 → usbphy1_otg | usb_host0_ehci/ohci |
| 接 USB 外设 | usb2phy1 → usbphy1_host | usb_host1_ehci/ohci |

3.2 硬件连接

标准 Type-C 线,检测到 Rd,CC 上拉 USB3_OTG0_ID 为高电平,RK3568作为Device (连电脑)
Type-C OTG 线 检测到 Ra,CC 下拉 USB3_OTG0_ID 为低电平 , RK3568作为Host (连 U盘)
3.3 RK3568 UVC驱动
修改kernel 添加补丁
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi
b/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi
index 18d6115341cd..268f5d2b1c05 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi
@@ -1778,6 +1778,8 @@
&usbdrd_dwc3 {
dr_mode = "otg";
+ snps,tx-fifo-resize;
+ snps,dis-u1u2-quirk;
extcon = <&usb2phy0>;
status = "okay";
};
/* 在 DTS 中强制设为 Device 模式 */
&usbdrd_dwc3 {
dr_mode = "peripheral"; /* 强制 Device 模式 */
/* dr_mode = "host"; 强制 Host 模式 */
/* dr_mode = "otg"; 自动检测 (默认) */
};
配置menuconfig
DWC3 Mode Selection (Dual Role mode) --->
( ) Host only mode
( ) Gadget only mode # 可能不可选或不存在
(X) Dual Role mode
需要修改内核配置,确保以下选项都启用:
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_DUAL_ROLE=y
CONFIG_USB_GADGET=y
CONFIG_USB_CONFIGFS=y
CONFIG_USB_CONFIGFS_F_UVC=y # 如果需要 UVC gadget
CONFIG_USB_DWC3_GADGET = y
Device Drivers
└─► USB support
└─► USB Gadget Support
├─► USB Gadget functions configurable through configfs
│ └─► <*> USB Webcam function ← UVC Gadget 在这里
│
└─► USB Gadget precomposed configurations
└─► <M> Mass Storage Gadget
Device Drivers --->
\*\] USB support ---\> \[\*\] USB Gadget Support ---\> \[\*\] USB Gadget functions configurable through configfs ---\> \<\*\> USB Webcam function ---\>



进入后用 / 键搜索:
例如搜索关键字输入: USB_F_UVC
检查内核

3.4 gadget 设备安装
USB Device (设备)
├── Configuration 1 (配置1)
│ ├── Interface 1 → Function (串口)
│ └── Interface 2 → Function (UVC 摄像头)
└── Configuration 2 (配置2)
└── Interface 1 → Function (大容量存储)
打开"相机"应用或打开 VLC → 媒体 → 打开捕获设备
当前是 ADB 模式,需要切换到 UVC 模式:


VID: 2207 (Rockchip)
PID: 0006 (ADB Interface)
停止 USBdevice
/usr/bin/usbdevice stop
修改默认 USB 功能为 UVC 开启动为android adb interface
修改 /usr/bin/usbdevice 中的默认功能:
修改 /etc/profile.d/usbdevice.sh
找到这一行:
USB_FUNCS=${USB_FUNCS:-adb}
改为:
USB_FUNCS=${USB_FUNCS:-uvc}
3.5 配置调试方法
sudo ./uvc_config.sh
编译并将camera_uvc拷贝到/usr/bin目录下
sudo ./uvc_app 640 480 &
挂载 configfs
mount configfs /sys/kernel/config

解绑 UDC
echo "" > /sys/kernel/config/usb_gadget/rockchip/UDC
查看当前绑定的 function
ls -la /sys/kernel/config/usb_gadget/rockchip/configs/b.1/
移除 ADB function
rm /sys/kernel/config/usb_gadget/rockchip/configs/b.1/f-ffs.adb
重新绑定 UDC
echo "fcc00000.dwc3" > /sys/kernel/config/usb_gadget/rockchip/UDC
创建 UVC function
mkdir /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6

uvc_num_request: 配置 UVC 驱动与 USB 控制器驱动交互的 request 和 buffer 数量; streaming_maxpacket: 配置 USB 2.0 物理总线上每个微帧传输的数据包大小,最大为3072;
streaming_bulk:配置 UVC 使用 bulk 传输类型(默认使用 isoc 传输类型)
配置 信息
echo "0x2207 " > /sys/kernel/config/usb_gadget/my_gadget/idVendo
echo "0x0005 " > /sys/kernel/config/usb_gadget/my_gadget/idProduct
配置 control
mkdir -p /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/control/header/h
ln -s /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/control/header/h /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/control/class/fs/h
ln -s /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/control/header/h /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/control/class/ss/h
创建 streaming 目录
mkdir -p /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/streaming/uncompressed/u
mkdir -p /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/streaming/mjpeg/m
mkdir -p /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/streaming/header/h
配置 MJPEG 1280x720
mkdir /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/streaming/mjpeg/m/720p
cd /sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/streaming/mjpeg/m/720p
echo 1280 > wWidth
echo 720 > wHeight
echo 333333 > dwDefaultFrameInterval
echo 18432000 > dwMinBitRate
echo 18432000 > dwMaxBitRate
echo 1843200 > dwMaxVideoFrameBufferSize
echo -e "333333\n666666\n1000000\n2000000" > dwFrameInterval
四 RK Linux USB gadget demo
参考Rockchip 平台的 UVC 摄像头应用 /external/uvc_app 。目前这个dmeo 模拟camera 通过USB 链路输出彩色条纹图像。 Rockchip Linux SDK集成了librkuvc.so库,其源码位于 external/uvc_app 。
代码目录结构
├── build
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── cmake_install.cmake
│ ├── Makefile
│ └── uvc_app
├── camera_uvc.c
├── CMakeLists.txt
├── main.c
├── readme.md
├── uvc
│ ├── drm.c
│ ├── drm.h
│ ├── mpi_enc.c
│ ├── mpi_enc.h
│ ├── mpp_common.h
│ ├── rk_type.h
│ ├── uevent.c
│ ├── uevent.h
│ ├── uvc_control.c
│ ├── uvc_control.h
│ ├── uvc_encode.cpp
│ ├── uvc_encode.h
│ ├── uvc-gadget.c
│ ├── uvc-gadget.h
│ ├── uvc_video.cpp
│ ├── uvc_video.h
│ ├── yuv.c
│ └── yuv.h
└── uvc_config.sh
uvc_control.c UVC控制管理层,监听uevent,管理编码器
uvc_encode.cpp 视频编码封装(YUYV/MJPEG/H264)
uvc_video.cpp 双队列缓冲管理(write队列/read队列)
uvc-gadget.c UVC协议处理,响应Host请求
mpi_enc.c MPP编码器接口封装
编译运行
cd uvc_app/build

在运行程序
uvc_app 640 480 &
设备管理器中出现

问题汇总:
- 设备Windows 黄色感叹号
添加 MS OS Descriptors

usbdevice 脚本中 streaming class 链接先于格式链接(u、m)创建,导致 header/h 被锁定,导致链接创建失败。
PC电脑上测试
VLC 查看 UVC 摄像头画面

在 Windows 上打开"相机"应用
