USB Gadget

来自Uotan Wiki · 刷机百科
BigfootACA讨论 | 贡献2024年3月20日 (三) 12:06的版本

Linux USB Gadget

概述

Linux在configfs中提供了usb_gadget用于支持USB设备模式。关于USB

准备configfs

在默认情况下,系统会自动挂载configfs,根据发行版不同,可能会挂在到不同的目录:

系统 目录
Android /config
GNU/Linux /sys/kernel/config

也可以通过以下命令来查看

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

如果没有挂载,也可以通过以下命令挂载

mount -t configfs configfs /sys/kernel/config

注:usb_gadget的configfs接口由模块libcomposite提供

创建gadget

简单的使用mkdir即可创建一个gadget。如要创建一个名为my_gadget:

mkdir /sys/kernel/config/usb_gadget/my_gadget

创建完成后,configfs会自动添加虚拟文件,以下是参照表

文件/文件夹名称 描述
bcdDevice 设备版本,使用带0x前缀的四个十六进制数字(0x1234,0x89AB)
bcdUSB USB的协议版本,使用带0x前缀的四个十六进制数字(0x0200,0x0301)
idProduct USB设备的产品ID,使用带0x前缀的四个十六进制数字(0x1234,0x89AB)
idVendor USB设备的制造商ID,使用带0x前缀的四个十六进制数字(0x1234,0x89AB)
bDeviceClass USB设备识别的设备类,使用带0x前缀的两个十六进制数字(0x34,0x9A)
bDeviceSubClass USB设备识别的设备子类,使用带0x前缀的两个十六进制数字(0x34,0x9A)
bDeviceProtocol USB设备识别的设备协议,使用带0x前缀的两个十六进制数字(0x34,0x9A)
bMaxPacketSize0 单次包最大传输大小
configs/ gadget的配置文件
functions/ gadget的子功能
strings/ 向主机上报的设备名称
max_speed 支持的最大速度
os_desc 向主机展示的操作系统相关的描述
UDC 使用的USB设备控制器,可以在/sys/class/udc中选择

Vendor ID、Product ID列表:http://www.linux-usb.org/usb.ids

Class、SubClass、Protocol列表:https://www.usb.org/defined-class-codes

填写设备ID

echo 0x05F9 > /sys/kernel/config/usb_gadget/my_gadget/idVendor
echo 0x1234 > /sys/kernel/config/usb_gadget/my_gadget/idProduct

填写设备字符串描述

参考: 语言ID

mkdir /sys/kernel/config/usb_gadget/my_gadget/strings/0x0409
echo "My Vendor" > /sys/kernel/config/usb_gadget/my_gadget/strings/0x0409/manufacturer
echo "My Product" > /sys/kernel/config/usb_gadget/my_gadget/strings/0x0409/product
echo "123456789" > /sys/kernel/config/usb_gadget/my_gadget/strings/0x0409/serialnumber

创建功能

gadget子系统支持非常多的usb功能,也可以使用用户空间的functionfs和主机进行通信。这里演示大容量存储和RNDIS网络

格式:

functions/%FUNC%.%NAME%
符号 描述
FUNC 要使用的功能名称
NAME 创建的自定义名字

创建并配置大容量存储

创建功能:

mkdir /sys/kernel/config/usb_gadget/my_gadget/functions/mass_storage.my_img

选择设备或者镜像

echo /mnt/a_virtual_disk.img > /sys/kernel/config/usb_gadget/my_gadget/functions/mass_storage.my_img/lun.0/file
echo 1 > /sys/kernel/config/usb_gadget/my_gadget/functions/mass_storage.my_img/lun.0/removable

Linux内核的mass_storage支持多个lun,默认会创建lun.0,也可以手动创建其它lun以映射多个设备(不推荐,多lun的大容量存储兼容性不好,建议可以使用多个大容量存储功能替代)

lun.X下有以下内容,可以根据情况填写

文件名 描述
cdrom 指示是否映射为虚拟光盘(0:普通磁盘,1:虚拟光盘)
file 映射的后端文件或设备绝对路径
forced_eject 写入这个文件将导致lun被强制分离
inquiry_string 设置显示在主机的设备名称
nofua 指示是否使用SCSI FUA标志
removable 指示是否可移除设备(0:不可移除设备,1:可移除设备)
ro 指示是否只读设备(0:可读写,1:只读)

创建并配置RNDIS

创建功能:

mkdir /sys/kernel/config/usb_gadget/my_gadget/functions/rndis.my_net

初始化成功后,将会创建一个usb0网卡,对端连接到主机

其它功能列表

功能 描述
mass_storage 大容量存储(BOT协议)
rndis RNDIS虚拟网卡
ffs FunctionFS 用户空间设备
acm CDC ACM虚拟串口
obex CDC OBEX对象交换
ecm CDC ECM虚拟网卡
eem CDC EEM虚拟网卡
ncm CDC NCM虚拟网卡
geth CDC Subset虚拟网卡
gser USB串口
hid HID 人类输入设备(鼠标/键盘等)
printer 模拟打印机
tcm SCSI目标映射大容量存储 (UASP协议)
uac1 USB音频1.0
uac2 USB音频2.0
uvc USB视频(摄像头)

使用前,可以使用modprobe usbfunc:功能来加载所需模块。如:

modprobe usbfunc:mass_storage

创建配置

创建完功能后,还需要将其链接到配置文件。默认不会创建任何配置文件,需要手动创建

创建一个配置

格式:configs/%NAME%.%INDEX%

符号 描述
NAME 创建的自定义名字
INDEX 配置文件的序号 必须大于1,且不能重复
mkdir /sys/kernel/config/usb_gadget/my_gadget/configs/a.1

链接功能到配置

ln -s /sys/kernel/config/usb_gadget/my_gadget/functions/mass_storage.my_img /sys/kernel/config/usb_gadget/my_gadget/configs/a.1/my_func.1
ln -s /sys/kernel/config/usb_gadget/my_gadget/functions/rndis.my_net /sys/kernel/config/usb_gadget/my_gadget/configs/a.1/my_func.2

填写字符串描述

参考: 语言ID

mkdir /sys/kernel/config/usb_gadget/my_gadget/configs/a.1/strings/0x0409
echo "MY MASS + RNDIS" > /sys/kernel/config/usb_gadget/my_gadget/configs/a.1/strings/0x0409/configuration

启动设备

/sys/class/udc中有可用的USB设备器列表,将其名字写入UDC即可启动gadget

查看可用

ls -l /sys/class/udc/
ffff0000.usb

启动gadget

echo ffff0000.usb > /sys/kernel/config/usb_gadget/my_gadget/UDC

此时,主机会成功发现设备

[12345.000000] usb 1-1.1: new high-speed USB device number 1 using xhci_hcd
[12345.000015] usb 1-1.1: New USB device found, idVendor=05f9, idProduct=1234, bcdDevice= 6.08
[12345.000030] usb 1-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[12345.000045] usb 1-1.1: Product: My Product
[12345.000060] usb 1-1.1: Manufacturer: My Vendor
[12345.000075] usb 1-1.1: SerialNumber: 123456789
[12345.000100] usb-storage 1-1.1:1.0: USB Mass Storage device detected
[12345.000115] scsi host0: usb-storage 1-1.1:1.0
[12345.000130] scsi 0:0:0:0: Direct-Access     Linux    UMS disk 0       ffff PQ: 0 ANSI: 2
[12345.000145] sd 0:0:0:0: Attached scsi generic sg0 type 0
[12345.000160] sd 0:0:0:0: [sda] 61071360 512-byte logical blocks: (31.3 GB/29.1 GiB)
[12345.000175] sd 0:0:0:0: [sda] Write Protect is off
[12345.000190] sd 0:0:0:0: [sda] Mode Sense: 0f 00 00 00
[12345.000205] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[12345.000220]  sda: sda1
[12345.000235] sd 0:0:0:0: [sda] Attached SCSI removable disk
[12345.000300] rndis_host 1-1.1:1.1 usb0: register 'rndis_host' at usb-0000:01:00.0-1.1, RNDIS device, 1a:2b:3c:4d:5e:6f
[12345.000315] rndis_host 1-1.1:1.1 enp1s0u1u1: renamed from usb0

停止gadget

如果想要停止gadget,则直接写空即可

echo > /sys/kernel/config/usb_gadget/my_gadget/UDC

附注:语言ID

ID 标识符 语言
0x0409 en-us 英语(美国)
0x0804 zh-cn 中文(中国)

关于语言ID: https://learn.microsoft.com/en-us/windows/win32/intl/language-identifiers