ConfigFS 组装 Gadget 与 Android/UEVENT 扩展

ConfigFS 组装 Gadget 与 Android/UEVENT 扩展

1. 目录模型

挂载 configfs 后,/sys/kernel/config/usb_gadget/下每个子目录是一个 gadget:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
usb_gadget/g1/
├── idVendor / idProduct / bcdDevice / bcdUSB
├── bDeviceClass / bDeviceSubClass / bDeviceProtocol
├── max_speed
├── strings/0x409/{manufacturer,product,serialnumber}
├── functions/
│ ├── acm.usb0/ (mkdir 创建 usb_function_instance)
│ ├── mass_storage.0/lun.0/file
│ └── ffs.adb/
├── configs/c.1/
│ ├── MaxPower
│ ├── strings/0x409/configuration
│ └── acm.usb0 -> ../../functions/acm.usb0 (symlink 绑定)
└── UDC (写UDC名触发bind)

标准操作序列:

1
2
3
4
5
6
7
8
9
10
mount -t configfs none /sys/kernel/config
cd /sys/kernel/config/usb_gadget
mkdir g1 && cd g1
echo 0x2207 > idVendor; echo 0x0011 > idProduct
mkdir -p strings/0x409 configs/c.1/strings/0x409
echo "RK3588" > strings/0x409/product
mkdir functions/acm.usb0
ln -s functions/acm.usb0 configs/c.1/
echo fc000000.usb > UDC # 绑定并 soft-connect
echo "" > UDC # 解绑

2. 内核侧翻译

用户操作 内核入口
mkdir usb_gadget/g1 gadgets_make() 分配gadget_info并注册 configfs group
mkdir functions/acm.usb0 按”.”前缀查usb_function_driver,调用其alloc_inst()生成usb_function_instance
mkdir configs/c.1 创建config_usb_cfg
ln -s functions/... configs/c.1/ cfg_link把 instance 挂到该配置的 func_list
echo <udc> > UDC gadget_dev_desc_UDC_store() configfs.c:293

写 UDC 后:

1
2
3
4
5
6
7
8
gadget_dev_desc_UDC_store()               configfs.c:293
-> usb_gadget_register_driver_owner()
-> gadget_bind_driver()
-> configfs_composite_bind() configfs.c:1319
-> 校验有 config 且每个 config 有 function
-> 组装设备描述符/strings
-> 对每个 symlink: usb_get_function() + usb_add_function()
-> usb_gadget_connect()

解绑(写空串)走configfs_composite_unbind()(1519 行)。EP0 与断开分发使用configfs_composite_setup()(1590 行)和configfs_composite_disconnect()(1617 行)。

3. Function 命名约定

mkdir functions/<type>.<instance>中的<type>必须与DECLARE_USB_FUNCTION_INIT注册名一致:

名称 模块 备注
acm usb_f_acm /dev/ttyGS*
mass_storage usb_f_mass_storage lun.N 子目录
ffs usb_f_fs 实例名即 mount 时的 dev 名
uvc usb_f_uvc 需在 configfs 下构建 formats/streaming
uac1/uac2 usb_f_uac1/2 虚拟声卡
hid usb_f_hid report desc 经属性写入
ncm/ecm/rndis/eem u_ether 系 网络
bytrans usb_f_bytrans(本树自定义) /dev/msgtrans*
audio_raw usb_f_audio_raw(本树自定义) 原始音频字符设备

模块化 function 依赖ldisc式按名自动加载(unregister前需无实例)。自定义 function 只要正确DECLARE_USB_FUNCTION_INIT并加载模块,即可像内置 function 一样mkdir

4. Android UEVENT 扩展

本树启用CONFIG_USB_CONFIGFS_UEVENT(三份 Rockchip defconfig 均开)。该扩展在configfs.c中:

  • gadget 目录下多出android设备节点;
  • android_setup()configfs.c:1547)包装 EP0 setup,跟踪连接状态;
  • 状态变化通过 uevent 上报USB_STATE=CONNECTED/DISCONNECTED/CONFIGURED
  • 用户态(Android/Rockchip usb service)据此切换 ADB/MTP 等组合。

这是 AOSP 系补丁,上游内核没有;移植主线时注意此差异。

5. OS Descriptor 支持

os_desc子目录支持 Microsoft OS descriptors(WinUSB 自动安装等):useb_vendor_codeqw_sign属性,以及 function 级interface.<n>扩展属性。RNDIS 在 Windows 上通常依赖它选择正确驱动。

6. 典型多 Function 组合

1
2
3
4
configs/c.1/
├── ffs.adb (ADB)
├── mass_storage.0 (U盘)
└── acm.usb0 (串口)

注意事项:

  • 组合受 UDC 端点资源限制(DWC3 端点数有限);
  • RNDIS 与其它 function 组合时接口顺序影响 Windows 识别,常需 os_desc;
  • ffs实例必须等用户态 daemon 写完描述符后写 UDC 才能成功 bind(否则-ENODEV);
  • 更换 function 组合必须先解绑 UDC。

7. 权限与安全

  • ConfigFS 写权限即等于重定义整个 USB 身份,量产系统必须限 root 并由受控服务操作;
  • 锁屏/未授权状态不应暴露 ADB/网络/可写存储 function;
  • VID/PID 与 strings 应固定,避免被用户态随意伪装其它设备。

文章互动

阅读 --

留言

0 条留言

正在加载留言…