USB

linux USB学习(四)

configfs用户层实现gadget驱动

Posted by 婷 on August 23, 2022 本文总阅读量

简介

这篇文章主要介绍如何通过configfs在应用层实现用户空间的gadget驱动

U盘配置过程

内核打开configfs以及usb存储设备相关选项

CONFIG_CONFIGFS_FS : 为用户空间提供访问配置内核驱动的configfs文件系统

image-20220820233130622

CONFIG_USB_LIBCOMPOSITE:提供usb gadget composite框架

image-20220822231747996

CONFIG_USB_CHIPIDEACONFIG_USB_CHIPIDEA_UDC:打开UDC(USB Device Controller)的配置,配置硬件控制器

image-20220822231432124

image-20220822231413515

CONFIG_USB_CONFIGFS_MASS_STORAGECONFIG_USB_F_MASS_STORAGE:对应于usb_f_mass_storage.ko驱动

image-20220820233043190

image-20220822232042475

其他相关的选项(不知道是不是需要勾选的,反正都勾选了)

image-20220820233139709

image-20220820233106139

然后编译内核以及驱动,更新设备的内核,加载相关驱动,挂载configfs

insmod configfs.ko
insmod libcomposite.ko
insmod usb_f_mass_storage.ko
mount -t configfs none /sys/kernel/config/

image-20220821002101262

创建g1实例

cd /sys/kernel/config/
ls
cd usb_gadget/
ls
mkdir g1
cd g1
ls

image-20220821002138940

设置USB版本,PID VID。(这里的PID VID的设置是我读取我的U盘 lsusb得到的,不过这个应该可以自己随便设置的)

echo 0x0200 > bcdUSB
echo "0x0781" > idVendor
echo "0x5151" > idProduct

image-20220821002229621

image-20220821002353061

创建并设置strings目录

mkdir strings/0x409
ls strings/0x409/
echo "12345678" > strings/0x409/serialnumber
echo "copyright" > strings/0x409/manufacturer
echo "moniupan" > strings/0x409/product

image-20220821002450532

image-20220821002646057

创建configuration和字符串,注意第三行的名字必须按照你加载的驱动后面的usb_f_*.ko来填写,比如我们加载的是usb_f_mass_storage.ko,那么这里的*就是mass_storage。如果不按照这样来的话,下一步创建funcitions会提示错误。

mkdir configs/c.1
mkdir configs/c.1/strings/0x409
echo "mass_storage" > configs/c.1/strings/0x409/configuration

image-20220821003144344

创建funcitions

root@copyright:/sys/kernel/config/usb_gadget/g1# mkdir functions/mass_storage.0
[  822.354698] Mass Storage Function, version: 2009/09/11
[  822.361138] LUN: removable file: (no medium)

image-20220821003153563

functionsconfiguration关联起来

root@copyright:/sys/kernel/config/usb_gadget/g1# ln -s functions/mass_storage.0 configs/c.1
[  986.215888] Number of LUNs=1
root@copyright:/sys/kernel/config/usb_gadget/g1#

image-20220821003415213

绑定到UDC,使能gadget

root@copyright:/sys/kernel/config/usb_gadget/g1# ls -l /sys/class/udc/
total 0
lrwxrwxrwx 1 root root 0 Jun 30 03:06 ci_hdrc.0 -> ../../devices/platform/soc/2100000.aips-bus/2184000.usb/ci_hdrc.0/udc/ci_hdrc.0
root@copyright:/sys/kernel/config/usb_gadget/g1# echo ci_hdrc.0 > UDC

image-20220821003527733

切记echo的时候不要加上绝对路径,只要把UDC的名字写入即可

image-20220821003700283

U盘验证过程

这时候板子链接我的电脑,Ubuntu系统,dmesg下的枚举信息如下,可以看到

image-20220821004250166

但是这个时候还没有找到分区信息,因为前面的时候还没配置U盘要使用的是哪个分区

我的板子弹出的内核打印

image-20220821010200459

添加U盘存储分区配置

不清楚自己板子上哪块分区可以拿来做实验,所以我的想法是,板子外接一个SD卡,拿SD卡的分区来做为模拟U盘的分区,板子插上SD卡显示的分区是/dev/sdb1

image-20220821004414322

image-20220821004423865

image-20220821004443053

U盘划分一个分区

这里介绍划分一个分区的做法,划分两个分区的做法可以参考链接一,输入如下命令配置

cd functions/mass_storage.0/
ls
echo /dev/sdb1 > lun.0/file
echo 1 > lun.0/removable
echo 0 > lun.0/nofua

image-20220821005651449

image-20220821005759442

添加分区后验证

添加分区后,我的Ubuntu系统,dmesg一下可以看到sdb分区的打印

image-20220821010218090

电脑上也识别到这个模拟U盘

image-20220822234429697

然后尝试接到我的Windows,貌似这两系统的驱动还不一样,反正Windows没识别出来,更新驱动也没用,先不管啦

image-20220821010754784

image-20220821010811357

CDC-NCM配置过程

相关的内核项打开,过程类似前面的U盘配置过程,这里就不赘述了

image-20220822220742575

image-20220822220828813

升级内核,加载驱动

insmod configfs.ko
insmod libcomposite.ko
insmod u_ether.ko
insmod usb_f_ncm.ko

image-20220822221444499

挂载configfs,创建g2实例

mount -t configfs none /sys/kernel/config/
cd /sys/kernel/config/
ls
cd usb_gadget/
mkdir g2
cd g2/
ls

image-20220822221553603

设置USB版本,PID VID。(这里的PID VID的设置我是根据内核的ncm.c中来的)

echo 0x0200 > bcdUSB
echo 0x0525 > idVendor
echo 0xa4a1 > idProduct

image-20220822221908730

image-20220822221730507

创建并设置strings目录

mkdir strings/0x409
echo "123456789" > strings/0x409/serialnumber
echo "copyright_manufacture" > strings/0x409/manufacturer
echo "copyright_product" > strings/0x409/product

image-20220822222226880

创建configuration和字符串,注意第三行的名字是ncm

mkdir configs/c.1
mkdir configs/c.1/strings/0x409
echo "ncm" > configs/c.1/strings/0x409/configuration

image-20220822223747292

创建funcitions

root@copyright:/sys/kernel/config/usb_gadget/g2# mkdir functions/ncm.0
[  260.395518] using random self ethernet address
[  260.400003] using random host ethernet address

image-20220822223840325

functionsconfiguration关联起来

ln -s functions/ncm.0 configs/c.1

image-20220822223928649

绑定到UDC,使能gadget

root@copyright:/sys/kernel/config/usb_gadget/g2# ls -l /sys/class/udc/
total 0
lrwxrwxrwx 1 root root 0 Jun 30 03:58 ci_hdrc.0 -> ../../devices/platform/soc/2100000.aips-bus/2184000.usb/ci_hdrc.0/udc/ci_hdrc.0
root@copyright:/sys/kernel/config/usb_gadget/g2# echo ci_hdrc.0 > UDC
[  193.443011] usb0: HOST MAC 56:1f:48:5f:28:9d
[  193.461533] usb0: MAC f6:d4:5f:72:f4:75
root@copyright:/sys/kernel/config/usb_gadget/g2# [  193.621532] IPv6: ADDRCONF(NETDEV_UP): usb0: link is not ready

image-20220822224802905

板子上查看发现usb0节点已经有了

root@copyright:/sys/kernel/config/usb_gadget/g2# ifconfig -a | grep usb
usb0      Link encap:Ethernet  HWaddr f6:d4:5f:72:f4:75
root@copyright:/sys/kernel/config/usb_gadget/g2# ifconfig usb0
usb0      Link encap:Ethernet  HWaddr f6:d4:5f:72:f4:75
          inet addr:192.168.7.2  Bcast:192.168.7.255  Mask:255.255.255.0
          UP 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)

image-20220822224845518

CDC-NCM验证过程

配置好后,将板子上的usb device接口接到我的PCUbuntu系统弹出的内核热插拔消息

[5034810.987491] usb 1-2: new high-speed USB device number 84 using xhci_hcd
[5034811.137990] usb 1-2: New USB device found, idVendor=0525, idProduct=a4a1, bcdDevice= 4.01
[5034811.137999] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[5034811.138004] usb 1-2: Product: copyright_product
[5034811.138008] usb 1-2: Manufacturer: copyright_manufacture
[5034811.138013] usb 1-2: SerialNumber: 123456789
[5034811.165335] cdc_ncm 1-2:1.0: MAC-Address: 56:1f:48:5f:28:9d
[5034811.165807] cdc_ncm 1-2:1.0 usb0: register 'cdc_ncm' at usb-0000:00:14.0-2, CDC NCM, 56:1f:48:5f:28:9d
[5034811.213378] cdc_ncm 1-2:1.0 enp0s20f0u2: renamed from usb0
[5034811.254119] cdc_ncm 1-2:1.0 enp0s20f0u2: 425 mbit/s downlink 425 mbit/s uplink
[5034811.318224] IPv6: ADDRCONF(NETDEV_CHANGE): enp0s20f0u2: link becomes ready

image-20220823220131373

可以看到enp0s20f0u2: renamed from usb0enp0s20f0u2: link becomes ready等关键打印,ifconfig命令查看,发现enp0s20f0u2节点已经有了

image-20220822225102372

设置IP(这里一定要设置子网掩码)

image-20220822225423896

我的PC设置好了后,板子这边的打印usb0 : link becomes ready

image-20220822224951525

板子这边ping我的PC

image-20220822225518923

我的PCping我的板子

image-20220822225559463

参考链接

其他问题

  • 参考链接一中有实现两个独立的U盘的方法,后续可以自己试试
  • 在测试的时候发现,不知道是不是我板子的问题,无论是配置成U盘还是NCM设备,时不时会自动断联又重联

  • drivers/usb/gadget目录下ko不是有两个目录嘛functionlegacy,之前不懂有什么差别,这次使用了configfs,大概知道了就是,function是放可以通过用户态配置的驱动,而legacy则是帮你都做好了的

    image-20220823221127313

  • chipidea不清楚是什么,是一种usb设计的规范?