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