对于USB Bulk通信发送0包的理解

写Device USB驱动的时候,当Bulk送信发送的数据长度恰好是wMaxPacketSize的整数倍时,是否应该发送0包的问题搞得我焦头烂额。查找了好多资料,有的说要加,这是USB协议的一部分;有的说要加,这是微软的霸王条款;也有的说不要加,因为协议里没写这一条,送信成功之后USB传输的任务就完成了。

今天终于给出了比较令自己满意的解释:
把“USB驱动”拆开理解。底层负责硬件的部分只管收发,确实不要求0包。但是Host确认数据接收完成并不是底层的动作,而是由Host驱动的Class部分决定的。不同的Class,对于USB数据有不同的要求,需要不同的“完成”标志。好多设备Class要求取到“0”为一个命令的结束。USB传输4字节对齐,不能被4整除的数据天然的后面就带“0”。而未满整包的受到长度制约,也可以读完。但如果收到的数据如果恰好等于包大小(USB2.0为512)的整数倍时,数据就正好没有“0”作为结尾。有点类似于C语言里找不到字符串结尾‘\0’的情况。这时就需要Device端通过发0字节包(Zero-length package,zlp)的形式为发送完成的数据补‘0’。
HID设备(鼠标键盘手柄等)大多是定长数据(当然人家用的是Interrupt通信,但同理),所以没必要通过0包识别;U盘不知为啥也不需要0包;打印机,SMART CARD则需要0包;我所对应的客户的设备也需要0包。不同的厂商当然也可以进行不同的定义。

所以在Device端开发的时候,不能把0包的逻辑加到底层,而应该在Class层相对的Function逻辑层进行判断并发送0包,底层只要支持0数据的发送就可以了。
当然底层驱动自己发0也没错,因为大多数设备收到单独的0跟没收一样。

已有1条评论

  1. 支持你的写作态度。

你好,新朋友。留言前请先填写昵称邮箱