1. 握手包:USB通信的“对讲机”
大家好,我是混迹USB驱动开发多年的老司机。今天咱们不聊那些虚头巴脑的概念,直接上干货,聊聊USB批量传输里那个看似不起眼、实则至关重要的角色——握手包。你可以把它想象成两个人用对讲机通话时的确认语。你说一句“收到请回复”,对方回一句“收到”,这才算一次完整的沟通。如果对方没吭声,或者回一句“没听清”,你就知道出问题了,得再说一遍。
在USB的世界里,握手包就是接收方(可能是主机,也可能是设备)给发送方的一个状态反馈。它本身不携带任何应用数据,只包含一个叫做PID(包标识符)的字段,用来告诉对方:“我这边现在是什么情况”。这个简单的机制,却是保证USB数据传输可靠、有序的基石。没有它,USB设备驱动开发就像在黑暗中摸索,数据丢了你都不知道。
为什么握手包在批量传输里特别关键?因为批量传输主打的就是一个“可靠”。像U盘拷贝文件、打印机发送文档这种场景,数据绝对不能出错,但快慢一点没关系。握手包就是确保“不出错”的关键监督员。它通过ACK、NAK、STALL这几种简单的“暗号”,构建了一套完整的错误检测和流量控制机制。我调试过不少设备,很多奇怪的传输失败、数据卡住的问题,追根溯源,最后往往都是握手包的交互逻辑没搞对。
2. 批量传输与IN事务:数据怎么“要”回来
2.1 批量传输的“三段式”结构
在深入握手包之前,咱们得先搞清楚批量传输是怎么组织的。USB通信是分层级的,最小单位是包,几个包组成一个事务,多个事务再组成一次完整的传输。
一次典型的批量传输事务,就像一次标准的对话流程,包含三个必不可少的阶段:
- 令牌阶段:主机发起,说“我要开始跟你说话了”。这个阶段主机发送一个令牌包,比如
IN令牌(表示我要从设备读数据)或OUT令牌(表示我要往设备写数据)。令牌包里指明了目标设备的地址和具体的端点号,精准定位到通信对象。 - 数据阶段:根据令牌的指示,进行实际的数据传递。如果是
IN事务,就由设备发送数据包给主机;如果是OUT事务,就由主机发送数据包给设备。 - 握手阶段:接收方根据数据接收的情况,给发送方一个明确的反馈。这就是握手包登场的时候了。这个反馈决定了整个事务是成功结束,还是需要重试,甚至是永久失败。
这个“令牌-数据-握手”的三段式结构,是批量传输事务的黄金法则。我刚开始接触时,总觉得握手包是多余的,直到在实战中遇到了数据覆盖、设备无响应这些坑,才明白它的不可或缺。
2.2 IN事务的完整流程拆解
今天咱们重点看IN事务,也就是主机从设备“要”数据的场景。这在实际开发中极其常见,比如主机从U盘读取文件内容。
一个成功的IN事务流程,用大白话讲是这样的:
- 主机喊话:主机在总线上广播:“地址是XX的设备,你的YY端点,有数据吗?有的话发给我!”(这就是
IN令牌包)。 - 设备回应:设备听到呼叫,检查自身状态。
- 有数据且准备好了:立刻把数据打包成一个数据包(比如
DATA0),发送给主机。 - 暂时没数据/没准备好:设备会回复一个
NAK握手包,意思是“我这会儿忙,手头没东西给你,你过会儿再问”。 - 端点出故障了:设备会回复一个
STALL握手包,这是严重错误,意思是“我这儿永久卡住了,你别再问了,赶紧叫人来修(报告给上层驱动)”。
- 有数据且准备好了:立刻把数据打包成一个数据包(比如
- 主机确认


955

被折叠的 条评论
为什么被折叠?



