惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
爱范儿
爱范儿
人人都是产品经理
人人都是产品经理
博客园 - 司徒正美
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
量子位
罗磊的独立博客
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
小众软件
小众软件
C
Cybersecurity and Infrastructure Security Agency CISA
Cyberwarzone
Cyberwarzone
大猫的无限游戏
大猫的无限游戏
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
雷峰网
雷峰网
Simon Willison's Weblog
Simon Willison's Weblog
The Cloudflare Blog
博客园 - 三生石上(FineUI控件)
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Cyber Attacks, Cyber Crime and Cyber Security
博客园_首页
博客园 - 叶小钗
V
Vulnerabilities – Threatpost
T
The Exploit Database - CXSecurity.com
T
Tailwind CSS Blog
IT之家
IT之家
博客园 - 聂微东
Spread Privacy
Spread Privacy
V2EX - 技术
V2EX - 技术
S
Security Affairs
宝玉的分享
宝玉的分享
V
V2EX
C
Cisco Blogs
博客园 - Franky
美团技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell
月光博客
月光博客
S
Securelist
J
Java Code Geeks
Webroot Blog
Webroot Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
P
Proofpoint News Feed
Last Week in AI
Last Week in AI
L
LINUX DO - 热门话题
NISL@THU
NISL@THU
WordPress大学
WordPress大学
W
WeLiveSecurity
T
Threatpost
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
腾讯CDC
阮一峰的网络日志
阮一峰的网络日志

博客园 - 蓝天上的云℡

事件编程之eventfd 事件驱动编程模式之EventLoop syslog日志查看器GUI图形界面,支持Windows/Linux/Macos开箱即用 ERRNO链条分析 ARM AMBA总线之AXI系 Linux Kernel Init Bootstrap 内核初始化启动 RK芯片平台GPIO控制 远程调试桥接-网络-ADB-GDB 斐讯N1盒子安装飞牛FNOS NAS 安卓以太网链路检测 安卓原生开发-Recovery使用minui绘制图形 蓝牙音频协议——安卓开发 RKxx系列的RK628摄像头配置影响HDMI出图 usb储存之BOT/UAS内核驱动 现代操作系统-音频处理技术1 Linux驱动底层 Linux驱动适配I2C/SPI例子 模块编译的pr_debug Linux内核/GKI内核主线更新-usb网卡名称变更引出的BUG 为Kernel代码生成VSCODE索引,快速跳转 安卓开机时间/性能优化 Linux/Golang/glibC系统调用 SGDMA与普通DMA Linux内核源码-存储驱动之 QSPI Flash golang数据转换技巧
Linux USB子系统之Gadget设备端驱动
蓝天上的云℡ · 2026-02-27 · via 博客园 - 蓝天上的云℡

源码路径:
usb/gadget/

USB层级例子
root -> port -> device -> 多个EP 端点

如以下这个设备的描述符树

    USB_Core -->|配置描述符| Config0
    Config0 --> Interface0(HID音量接口)
    Config0 --> Interface1(其他功能接口)

    Interface0 --> HID_Descriptor
    Interface0 --> EP1(IN端点1)

    Interface1 --> EP2(端点2)
    Interface1 --> EP3(端点3)
   
    HID_Descriptor --> Report_Descriptor

ps : usb控制器有带宽和端点的限制,所以device不能超过控制器端点数量限制,否则无法枚举完成。

层级

  • usb/gadget/configfs.c
  • usb/gadget/functions.c
  • usb/gadget/function/f_rndis.c

以下是device层级的

RNDIS驱动

例子:
RNDIS驱动,安卓手机接入电脑能作为USB网卡就用这个
usb/gadget/function/f_rndis.c

驱动注册:

DECLARE_USB_FUNCTION_INIT(rndis, rndis_alloc_inst, rndis_alloc);

宏的定义很简单
image

  • 驱动加载时调用usb function注册,卸载反之
  • 赋值两个行为函数指针
    • alloc_inst 这个是usb实例初始化注册
    • alloc_func 这个是usb功能注册,用于configfs,端点描述符等处理

image
图源:https://www.usbzh.com/article/detail-1062.html

UVC例子

usb/gadget/function/

内核选项:USB_CONFIGFS、USB_LIBCOMPOSITE、USB_CONFIGFS_F_UVC 和 USB_F_UVC
层级
f_uvc.c 适配层L2
uvc_v4l2.c 底层转换支持L1

usb/gadget/function/f_uvc.c
通过uvc->vdev私有数据管理下属v4l2虚拟设备

主要通过v4l2的api注册虚拟设备,其中的fops函数指针作为数据转换读写的通道。(吐槽一下,内核没有统一使用通道这种设计是有点捞了)

  • 注册
  • video_register_device
  • video_set_drvdata

usb/gadget/function/uvc_v4l2.c
关键ops函数,实现v4l2框架所需的接口即可

  • uvc_v4l2_fops
    image

  • uvc_v4l2_ioctl_ops
    image

端口排查

带宽工具,基于usbmon驱动
https://github.com/aguinet/usbtop

命令查看端点

cat /sys/kernel/debug/usb/devices
# cat /sys/kernel/debug/usb/devices

T:  Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=480  MxCh= 1
B:  Alloc=  0/800 us ( 0%), #Int=  0, #Iso=  0
D:  Ver= 2.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=1d6b ProdID=0002 Rev= 6.01
S:  Manufacturer=Linux 6.1.141 ehci_hcd
S:  Product=EHCI Host Controller
S:  SerialNumber=21480000.usb
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=  0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   4 Ivl=256ms

T:  Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12   MxCh= 1
B:  Alloc=  0/900 us ( 0%), #Int=  0, #Iso=  0
D:  Ver= 1.10 Cls=09(hub  ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=1d6b ProdID=0001 Rev= 6.01
S:  Manufacturer=Linux 6.1.141 ohci_hcd
S:  Product=Generic Platform OHCI controller
S:  SerialNumber=214c0000.usb
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=  0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   2 Ivl=255ms

B代表带宽,而且还需要留意Int+Iso的数量
控制器会有设备数限制和端点数限制
这里的端点数限制指周期端点,包括 int中断传输,isoc基于时间固定带宽传输两种
EP一般有IN/OUT,EP IN + EP OUT = 2个端点

关于alt,usb支持设备布局 https://learn.microsoft.com/zh-cn/windows-hardware/drivers/usbcon/usb-device-layout
image

驱动里面一般也有处理,当USB主机发送USB_REQ_SET_INTERFACE命令时,驱动会调用set_alt函数
例如uac2驱动的afunc_set_alt函数,会根据intf值来切换录制和播放设备类型