Linux支持usb主机驱动, 同时也支持从设备驱动。
其主要使用gadget api框架实现。 软件一般分为三个层次,
1. gadget function 对应于usb function, 即按照协议, usb设备需要实现的功能。(如HID, MSC, UVC等)
2. gadget api(framework) 即linux提供的usb gadget驱动框架
3. UDC Driver (即usb设备控制器驱动), 实现控制器相关驱动
关于usb gadget设备function驱动, 最新Linux提供了多种方式。
1. 使用usb_compositor_driver, 注册/实现该驱动即可。
2. 使用configfs进行配置, 用户态可以利用配置文件系统创建相应configuration, interface, endpoint等, 配合内核态的驱动, 即可实现某种功能的usb设备。
3. 使用functionfs进行配置, 最新的安卓相关usb驱动, 如adb, mtp, ptp就是采用这种方式实现。 即内核态提供功能文件系统, 内部可关联多种标准功能, 具体协议由应用层实现, 即所谓的用户态驱动。
此处暂且只讨论configfs配置相关.
1. 配置cdc ecm虚拟网卡驱动
1. make menuconfig 确保支持usb gadget驱动, configfs, 及libcomposite.ko等
请加载相关驱动模块, 我这里大部分为buildin的驱动。
2. 故操作如下:
insmod usb_f_ecm.ko // 加载cdc ecm function驱动
mount -t configfs none /sys/kernel/config // 挂载configfs
cd /sys/kernel/config/usb_gadget
// 目前里面是空的, 即没有 gadget设备
mkdir g_ecm // 创建ecm gadget设备
root@xxx:/sys/kernel/config/usb_gadget/g_ecm# ls -all
total 0
drwxr-xr-x 6 root root 0 Jun 10 14:46 .
drwxr-xr-x 3 root root 0 Jun 10 14:46 ..
-rw-r--r-- 1 root root 4096 Jun 10 14:46 UDC
-rw-r--r-- 1 root root 4096 Jun 10 14:46 bDeviceClass
-rw-r--r-- 1 root root 4096 Jun 10 14:46 bDeviceProtocol
-rw-r--r-- 1 root root 4096 Jun 10 14:46 bDeviceSubClass
-rw-r--r-- 1 root root 4096 Jun 10 14:46 bMaxPacketSize0
-rw-r--r-- 1 root root 4096 Jun 10 14:46 bcdDevice
-rw-r--r-- 1 root root 4096 Jun 10 14:46 bcdUSB
drwxr-xr-x 2 root root 0 Jun 10 14:46 configs
drwxr-xr-x 2 root root 0 Jun 10 14:46 functions
-rw-r--r-- 1 root root 4096 Jun 10 14:46 idProduct
-rw-r--r-- 1 root root 4096 Jun 10 14:46 idVendor
-rw-r--r-- 1 root root 4096 Jun 10 14:46 max_speed
drwxr-xr-x 2 root root 0 Jun 10 14:46 os_desc
drwxr-xr-x 2 root root 0 Jun 10 14:46 strings
此时, 内部会自动创建很多文件及文件夹, 从名称看, 基本就是对usb设备的一种抽象。
如 UDC - 设备控制器
bDeviceClass - 设备类型
bDeviceProtocol - 协议
bMaxPacketSize0 - 包的最大的size
bcdUSB - usb规范版本号
bcdDevice - 设备版本号
idProduct - 产品id
idVendor - 供应商id
strings - 字符串信息
max_speed - 最大速度
configs - 配置项
functions - 功能/接口
继续,
echo "64" > bMaxPacketSize0
echo "0x200" > bcdUSB // usb2.0
echo "0x100" > bcdDevice
echo "0x03FD" > idVendor
echo "0x0502" > idProduct
// 以上设置gadget设备一些基本信息
mkdir config/config1.1 // 创建配置项1, 有一定的命名规则
mkdir functions/ecm.0 // 创建一种ecm功能
ln -s functions/ecm.0 configs/config1.1 // 将ecm.0 功能放入配置项
ls config/config1.1/ecm.0/
root@xxx:/sys/kernel/config/usb_gadget/g_ecm/configs/config1.1/ecm.0# ls -all
total 0
drwxr-xr-x 2 root root 0 Jun 10 14:57 .
drwxr-xr-x 3 root root 0 Jun 10 14:56 ..
-rw-r--r-- 1 root root 4096 Jun 10 14:57 dev_addr
-rw-r--r-- 1 root root 4096 Jun 10 14:57 host_addr
-r--r--r-- 1 root root 4096 Jun 10 14:57 ifname
-rw-r--r-- 1 root root 4096 Jun 10 14:57 qmult
ok, usb ecm设备就通过gadget文件系统配置好了, 包含一些必要的描述信息(pid, vid, config, function等)
最后, 通过UDC控制器 启动该usb设备
echo "fe200000.dwc3" > UDC
"fe200000.dwc3" 为dwc3 控制器, 通过AMBA总线于cpu, ddr等相连接, 通过sysfs文件系统可以查看:
ls /sys/devices/platform/amba/ff9d0000.usb0/fe200000.dwc3
root@xxx:/sys/kernel/config/usb_gadget/g_ecm# echo "fe200000.dwc3" > UDC
[ 1172.683653] driver->udc_name: fe200000.dwc3
[ 1172.687848] begin to find udc(fe200000.dwc3)
[ 1172.692119] ret = 0
[ 1172.694209] udc_bind_to_driver...
[ 1172.697514] registering UDC driver [g_ecm]
[ 1172.701602] dwc3_gadget_set_speed
[ 1172.704926] dwc3_gadget_set_selfpowered
[ 1172.709167] usb0: HOST MAC ea:df:fe:4e:7e:10
[ 1172.713514] usb0: MAC c6:01:94:6e:04:4f
[ 1172.717379] dwc3_gadget_start
[ 1172.720847] dwc3_gadget_pullup
ifconfig后, usb0虚拟网卡出现!!
usb0 Link encap:Ethernet HWaddr C6:01:94:6E:04:4F
BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
后面就是配置ip地址, 网络掩码, 网关等操作。
2. 配置网卡
Linux主机端:
river@river-VirtualBox:~/linux_workspace/kernel/linux-source-5.0.0$ lsusb -t
/: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/6p, 5000M
|__ Port 1: Dev 3, If 0, Class=Communications, Driver=cdc_ether, 5000M
|__ Port 1: Dev 3, If 1, Class=CDC Data, Driver=cdc_ether, 5000M
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/8p, 480M
|__ Port 1: Dev 2, If 0, Class=Human Interface Device, Driver=, 12M
可以看到cdc_ether驱动已加载
[23783.203140] cdc_ether 2-1:1.0 enp0s12u1: renamed from usb0
river@river-VirtualBox:~/linux_workspace/kernel/linux-source-5.0.0$ ifconfig -a
enp0s12u1: flags=4099 mtu 1500
ether ea:df:fe:4e:7e:10 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
enp0s12u1即为usb0网卡, 已重命名。
ifconfig enp0s12u1 192.168.1.111 netmask 255.255.255.0
即可
===========================================================================================
设备端同理,
ifconfig usb0 192.168.1.222 netmask 255.255.255.0
之后就可以互相ping通
ECM USB虚拟网卡驱动配置完成。