usb-skeleton 学习遇到的困惑
最近想学习下usb驱动,刚好手头有《圈圈教你学usb》书和实验板,有一章自定义设备和 usb-skeleton 驱动大致吻合。实践出真知嘛,当然得搞一搞。固件程序大概改了下,只用了批量端点2,中断端点1代码全部干掉,简单起见,主机发数据,跑马灯;主机读取数据,用户按下键盘就返回8字节数据,当然抬起也会发(固件基本不需要改)。当然不按就不干活。skeleton驱动改了VENDOR_ID和PRODUCT_ID,基本就可以匹配了。测试环境:
$ cat /etc/issue
CentOS Linux release 6.0 (Final)
Kernel \r on an \m
$ cat /proc/version
Linux version 2.6.38 (linux@localhost.ada) (gcc version 4.4.4 20100726 (Red Hat 4.4.4-13) (GCC) ) #1 SMP Tue Sep 13 09:03:59 EDT 2011
用户执行操作:
# gcc skeleton_test_01.c
# ./a.out
Open /dev/skel0 success!
^C
# ./a.out
Open /dev/skel0 success!
read.len = -1. errno = 5
read: Input/output error
#
内核打印显示(只显示问题所在,其他见附件):
……
Mar1 21:29:17 localhost kernel: Now leave skel_read: rv = -512 //用户ctrl+c之后返回。(正常)
Mar1 21:29:17 localhost kernel: Now in skel_read_bulk_callback. //你怎么也返回了,哥没按键盘呀。
Mar1 21:29:17 localhost kernel: read_callback_times = 0 urb->status = -2 //提交urb的回调也执行了? 好快呀!而且还返回个错误(必须得,因为没按键盘)。
Mar1 21:29:17 localhost kernel: Now leave skel_read_bulk_callback.
Mar1 21:29:17 localhost kernel: Now in skel_release.
……
Mar1 21:29:19 localhost kernel: usb_skeleton: skel_do_read_io - failed submitting read urb, error -22//再次打开设备读,提交urb直接失败,不会吧
Mar1 21:29:19 localhost kernel: Now leave skel_do_read_io: rv = -5 //IO error.用户层返回 read: Input/output error.
……
调试中的问题:
processed_urb 这玩意没用上嘛,而且probe中也没初始化为1.导致第一次读直接挂死在wait_for_completion(&dev->bulk_in_completion)。
如果有兄弟知道这玩意有什么特殊用途,告知下!
重点疑问:
用户程序结束后只要有预读,则批量输入也直接结束,返回-2; 而且下次重新填充提交urb就会失败,返回-22。也就是说读一次失败,设备就没法工作了。当然也会返回-75,-5 之类。简单说下预读,驱动作者意图,假设缓存中有8字节,如果本次要求读8字节,够了读取8字节直接返回,不需要启动IO(在这里就是提交urb);如果读4字节,当然剩下4字节,也无需启动IO;如果用户要求读12字节,直接以8字节返回,并且开启IO(此时应该不管应用程序结束不结束,我都要读,和应用程序无关)。
测试写没有问题,中途干死,也可以继续流水灯。
测试读的时候,没有预读,程序一切正常,用户态阻塞,直到我按键。程序正常结束,也可以再次启动。一切完好(每次读8字节)。
如果有预读,则就是上面看到的结果,也可以改用户程序每次读取8个以上字节,关闭应用程序也能保证驱动有预读,同样下次再次开启失败。
所以不太明白,为什么有预读,用户程序结束了,提交的urb立马也返回出错了。退一步讲,即使这一次出错,下次再次填充,提交urb也不该提交不上呀。是否有兄弟对此有熟悉,指点一二。
附件:
你好!我也遇到了这个问题,在read时程序停在wait_for_completion(&dev->bulk_in_completion); 请问你的问题解决了吗?如果解决了是怎么解决的呢?麻烦你了,谢谢! 回复 2# oucsunjie
不清楚你的具体的问题,不知道你说的是不是这个:
调试中的问题:
processed_urb 这玩意没用上嘛,而且probe中也没初始化为1.导致第一次读直接挂死在wait_for_completion(&dev->bulk_in_completion)。
是的,就是你说的这个问题,在skel_read函数中,程序进入
if (!dev->processed_urb) {
/*
* the URB hasn't been processed
* do it now
*/
wait_for_completion(&dev->bulk_in_completion);
dev->bulk_in_copied = 0;
dev->processed_urb = 1;
}
然后就停在了wait_for_completion(&dev->bulk_in_completion);
回复 4# oucsunjie
调试中的问题:
processed_urb 这玩意没用上嘛,而且probe中也没初始化为1.导致第一次读直接挂死在wait_for_completion(&dev->bulk_in_completion)。
而且probe中也没初始化为1……
你在probe函数中processed_urb初始化为1了还是不行? 回复 5# azfa123
在probe中初始化processed_urb=1后不会再停在wait_for_completion(&dev->bulk_in_completion);
但是我遇到了另外一个问题,是这样:在skel_read_bulk_callback中打印了- nonzero write bulk status received:-75
-75代表着-EOVERFLOW,意思是端点接收了超过端点指定最大数据包尺寸的数据,我的usb host是1.1的,只能工作在全速模式下,所以端点接收的最大包长度为64字节,我传给usb设备2k字节的数据,为何出现溢出错误,请问你知道如何解决吗,谢谢了! 回复 6# oucsunjie
这个没测试过,期待你的解决答案。:lol: 楼主类似的该法,我也改自skeleton 我在测试读写时它停在rv = wait_for_completion_interruptible(&dev->bulk_in_completion);(是skel_read结构中的)函数处死了(该函数好像是等io中断的),问下怎么解决建议?
你上面说的预读是什么意思? 兄弟,,这问题解决了吗,,我试了,,问题也是这样 回复 9# zekezang
兄弟,看看最新的3.10的例子吧,内核已经去掉了processed_urb,processed_urb就是个bug。
页:
[1]