usb-skeleton模块可以用来测试支持bulk传输端口的usb设备,如usb存储。它将用户空间的读写数据操作转换成bulk端口的数据传输,即将用户write的数据从bulk out端口发送,read的请求数据从bulk in端口接收。
一个简单的测试方法是通过usb-skeleton模块读取usb存储设备上第一个block的数据(一般为MBR或PBR数据块)。
如果用qemu测试,可参考qemu: usb存储设备仿真
根据usb mass storage class bulk-only传输协议,一次读数据传输流程为:
a. H->D : [bulk out] 31字节CBW(Command Block Wrapper)数据块
b. D->H : [bulk in ] n字节数据块
c. D->H : [bulk in ] 13字节CSW(Command Status Wrapper)数据快
其中CBW由标志 “USBC” 开始,包含15字节数据头和16字节实际命令(常用的为SCSI或UFI命令集)。CSW由标志 “USBS” 开始。
读数据块命令选择SCSI和UFI都支持的READ(10)命令。
编译
首先把模块绑定的设备信息修改为要测试的设备,比如绑定qemu虚拟的usb存储设备:
#define USB_SKEL_VENDOR_ID 0x46F4
#define USB_SKEL_PRODUCT_ID 0x0001
有一些编译错误如下:
fatal error: linux/config.h: No such file or directory
删除 #include <linux/config.h>
fatal error: linux/smp_lock.h: No such file or directory
与这头文件相关的是大内核锁机制,在新的内核已经移除,删除相关代码:
#include <linux/smp_lock.h>
lock_kernel();
unlock_kernel();
应改为使用细粒度锁,不过在这个简单测试里可以忽略竞态
error: implicit declaration of function ‘err’
error: implicit declaration of function ‘dbg’
error: implicit declaration of function ‘info’
自定义一下这几个函数:
#define err(fmt, arg...) printk(KERN_ERR fmt "\n" , ##arg)
#define info(fmt, arg...) printk(KERN_INFO fmt "\n" , ##arg)
#define dbg(fmt, arg...) printk(KERN_DEBUG fmt "\n" , ##arg)
warning: passing argument 5 of ‘usb_bulk_msg’ from incompatible pointer type [enabled by default]
&count, HZ*10);
note: expected ‘int *’ but argument is of type ‘size_t *’
在64位平台编译出现的参数类型不匹配警告,因为size_t是64位的,而int是32位的,修改如下:
static ssize_t skel_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
int actual_cnt;
...
retval = usb_bulk_msg(dev->udev,
...
&actual_cnt, HZ*10);
if (!retval) {
if (copy_to_user(buffer, dev->bulk_in_buffer, actual_cnt))
retval = -EFAULT;
else
retval = actual_cnt;
}
error: implicit declaration of function ‘usb_buffer_free’
error: implicit declaration of function ‘usb_buffer_alloc’
这两个函数已由 usb_free_coherent 和 usb_alloc_coherent 替代,参数不变。
warning: passing argument 6 of ‘usb_fill_bulk_urb’ from incompatible pointer type
callback函数参数发生了变化,修改为:
static void skel_write_bulk_callback(struct urb *urb)
error: unknown field ‘mode’ spe