linux usb gadget驱动详解(二)

        在上篇《linux usb gadget驱动详解(一)》中,我们了解到gadget的测试方法,但在最后,我们留下一个问题,就是怎样使用新的方法进行usb gadget驱动测试。

        我们发现linux的文档是宝库!

      这篇文章的测试方法主要是参考如下文档:

linux-4.4.19/Documentation/ABI/testing/configfs-usb-gadget
linux-4.4.19/Documentation/usb/gadget-testing.txt

如果对gadget感兴趣,除了阅读linux gadget源代码之外,也需要阅读linux自带的Documentation。它们时常给我们带来惊喜~~

在linux 2.6开始,linux内核加入了configfs文件系统,对应驱动加载为:

modprobe configfs

这个文件系统主要用于在用户态配置内核对象,这样用户态与内核态驱动的交互就可以更加简单和密切,具体可以参考内核相关文档及其源码。

我们还是使用BBB板进行测试,configfs开启gadget驱动测试前,需要加载必要的驱动程序:

modprobe musb_am335x
modprobe configfs
modprobe libcomposite
modprobe usb_f_mass_storage

其中libcomposite实现了通用的设备驱动api,我们在开发自己的gadget时,可以利用该api,并参考已有例子,如f_mass_storage.c、f_hid.c等

加载好上述驱动后,就可以在用户态配置U盘驱动了!

#挂载configfs文件系统
mount -t configfs none /sys/kernel/config
cd /sys/kernel/config/usb_gadget
mkdir gadget
cd gadget

#ls一下,含有如下文件和目录
// UDC              bMaxPacketSize0  functions        strings
// bDeviceClass     bcdDevice        idProduct
// bDeviceProtocol  bcdUSB           idVendor
// bDeviceSubClass  configs          os_desc

#设置USB协议版本
echo 0x0200  > bcdUSB

#定义产品的VendorID和ProductID
echo "0x0525"  > idVendor
echo "0xa4a5" > idProduct

#实例化"英语"ID:
mkdir strings/0x409
ls strings/0x409

//manufacturer    product    serialnumber

#将开发商、产品和序列号字符串写入内核:
echo "01234567" > strings/0x409/serialnumber
echo "mkelehk"  > strings/0x409/manufacturer
echo "upan"  > strings/0x409/product

#创建一个USB配置实例:
mkdir configs/config.1
ls configs/config.1

//MaxPower bmAttributes strings

echo 120 > configs/config.1/MaxPower

#定义配置描述符使用的字符串
mkdir configs/config.1/strings/0x409
ls configs/config.1/strings/0x409/

//configuration

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

#创建一个功能实例,需要注意的是,一个功能如果有多个实例的话,扩展名必须用数字编号:
mkdir functions/mass_storage.0

#配置U盘参数
echo "/var/sdcard/disk.img" > functions/mass_storage.0/lun.0/file
echo 1 > functions/mass_storage.0/lun.0/removable
echo 0 > functions/mass_storage.0/lun.0/nofua

#捆绑功能实例到配置config.1
ln -s functions/mass_storage.0 configs/config.1

#查找本机可获得的UDC实例
ls /sys/class/udc/

//musb-hdrc.1.auto

#将gadget驱动注册到UDC上,插上USB线到电脑上,电脑就会枚举USB设备。
echo "musb-hdrc.1.auto" > UDC

上述步骤写成脚本,即可加载u盘驱动,其中"/var/sdcard/disk.img"可按上篇文章创建。当echo "" > UDC时,相当于模拟U盘拔掉,PC磁盘符消失。

        这种方式比legacy方式要先进,USB设备属性修改(如序列号、PID/VID、interface等)、插拔模拟等等都很方便在用户态修改,你只需要在configfs文件系统下创建一下文件/文件夹或者使用echo命令修改文件内容即可。

       更重要的是,这种方法,很方便地实现“复合设备”。usb复合设备是只有一个设备描述符,一个配置描述符,同时有多个接口描述符(代表多种功能),譬如一个键鼠设备,既有键盘又有鼠标。

      下面我们创建一个复合键鼠设备。读者可以使用configfs尝试实现更多的复合设备进行测试。但USB的端点数量是有限的(usb2.0协议指定只用4bit表示端点号,而在FPGA实现的ip核中,端点则代表FIFO),所以最大端点数是16对IN/OUT端点(包含默认端点0)。端点资源有限,所以不可能复合任意多个设备。

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

#含有如下文件和目录
// UDC              bMaxPacketSize0  functions        strings
// bDeviceClass     bcdDevice        idProduct
// bDeviceProtocol  bcdUSB           idVendor
// bDeviceSubClass  configs          os_desc

#设置USB协议版本USB2.0
echo 0x0200  > bcdUSB

#定义产品的VendorID和ProductID
echo "0x0525"  > idVendor
echo "0xa4ac" > idProduct

#实例化"英语"ID:
mkdir strings/0x409
ls strings/0x409

//manufacturer    product    serialnumber

#将开发商、产品和序列号字符串写入内核:
echo "76543210" > strings/0x409/serialnumber
echo "mkelehk"  > strings/0x409/manufacturer
echo "keyboard_mouse"  > strings/0x409/product

#创建一个USB配置实例:
mkdir configs/config.1
ls configs/config.1

//MaxPower bmAttributes strings

echo 120 > configs/config.1/MaxPower

#定义配置描述符使用的字符串
mkdir configs/config.1/strings/0x409
ls configs/config.1/strings/0x409/

//configuration

echo "hid" >   configs/config.1/strings/0x409/configuration

#创建功能实例,需要注意的是,一个功能如果有多个实例的话,扩展名必须用数字编号:
mkdir functions/hid.0
mkdir functions/hid.1

#配置hid描述符(根据hid协议或者g_hid.ko对于的源码hid.c的说明)
echo 1 > functions/hid.0/subclass
echo 1 > functions/hid.0/protocol
echo 8 > functions/hid.0/report_length
echo -ne \\x5\\x1\\x9\\x2\\xa1.... > functions/hid.0/report_desc

echo 1 > functions/hid.1/subclass
echo 2 > functions/hid.1/protocol
echo 4 > functions/hid.1/report_length
echo -ne \\x5\\x1\\x9\\x2\\xa1.... > functions/hid.1/report_desc

#捆绑功能实例到配置config.1
ln -s functions/hid.0 configs/config.1
ln -s functions/hid.1 configs/config.1

#查找本机可获得的UDC实例
ls /sys/class/udc/

//musb-hdrc.1.auto

#将gadget驱动注册到UDC上,插上USB线到电脑上,电脑就会枚举USB设备。
echo "musb-hdrc.1.auto" > UDC

其中,echo -ne \\x5\\x1\\x9\\x2\\xa1.... > functions/hid.0/report_desc等为“HID的报告描述符”填写,我没有填写完整。这部分需要自行查阅HID class的相关文档,但我在另一篇文章《STM32F103C8T6的USB HID复合设备的实现要点》中有tips。或者参考linux-4.4.19/Documentation/usb/gadget_hid.txt里面有一个/* hid descriptor for a keyboard */的键盘HID报告描述符例子。

       说了这么多,也还停留在对gadget驱动程序的测试。接下来要对linux gadget进行源码分析了。

你可能感兴趣的:(Linux驱动,linux内核之USB)