模拟XBOX手柄学了下USB协议,做点笔记,参考的USB资料链接如下,这个是站内讲的很好的大佬,我是按照我的思路再梳理一遍。
如果看到不懂的名词可以在这个文章里面找,我的文章主要是跟协议分析数据来理解。
USB协议详解

USB协议简化来说就三部分Host部分,Device部分,中间的传输部分,Host部分普通的键盘鼠标和我这种模拟Xbox手柄的项目都不用写驱动,所以暂时不用管,先看传输部分,也就是通信协议。基础的电气部分默认大家是了解的,D+D-差分一类。
在这里插入图片描述
通信协议分为几层,我直接照搬大佬文章描述,这个图先放出来做参考,后面一步步就可以理解了。
在这里插入图片描述
从底下到上面,依次是 域→包→事务→传输

虽然就四层,但是直接来看很懵,我的建议是,学一个协议最好的办法就是直接看协议分析仪拉出来的数据,我这里用到两个软件,一个是wireshark,一个是usbpv,wireshark按时间轴来看比较方便,看syslog之类,可以理解为不传输数据,用来detect设备的信号,usbpv是会把USB传输数据的包解析出来,做图形化拼到一起展示。我会把我抓到的协议文件贴出来,感兴趣可以自己下载这两个软件自己看。

1.上电

wireshark抓到的xbox手柄协议,直接来看刚开始上电的流程:
在这里插入图片描述
刚开始就是开始触发,上电一类的,然后第一个点是SE0,SE0就是复位总线,把D+D-都拉低一段时间,具体时间要求可以参考USB协议,然后看到Link state J,这个是Host用来Detect全速设备是否支持高速的,如果支持的话,高速设备会痴汉回复JK JK JK JK JK JK,很多个JK,全速设备就不会回复,看到几个Undefined,这个不用管,因为我也没查到,协议分析仪解析不出来的初学者都不用管。

下一个就是正式的SOF包,可以看到Protocol从Syslog变为了USBLL,这就是USB协议的正式包了,全称是Start of frame,也就是帧开始,全速设备的一帧是1ms,host每过1ms会敲一下device,类似打点计时器,有很多作用,比如防止设备睡着,最重要的是时间分割,定义一帧的时间就是1ms,一个包必须在一帧之内传完。
SOF会一直发,有数据的时候看不到SOF,是因为协议分析仪把SOF里面的信息解析并显示出来了,就不单独显示SOF包了,协议里面最左边一列的NO是协议分析仪编的帧号,USB传输的帧号可以点开SOF看。

SOF包双击打开如下:
在这里插入图片描述

上面的Frame 25,是指第25帧,什么时候发的,长度是多少,协议是什么,这些是USB协议分析仪的日志记录
下面的USB Link Layer是这一帧带了什么信息,我们打开的是SOF包,用这个为例解析一下包和域的概念
它数据分了三部分,原始数据在下面a5 9c 08
协议分析仪给分好了:
PID:Packet ID,这个Packet的编码,指示这个包的类型
Frame number:000 1001 1100,也就是USB传输的帧号
CRC5:5位CRC校验数据,防止数据错误

这三个部分,就是域,三个域,构成一个包。现在域到包的概念就有了。

不知道诸位发现没有,正常校验位应该是在最右边,在包的末尾,最后再发,图里显示却在高5位?
由此可以引出,USB协议是先发低位,再发高位的,把CRC5放在最高的5位,来达成最后发CRC的目标。

另外上电发SE0之后一直发SOF的目的是?
为了等待设备初始化,设备初始化需要一段时间, 初始化成功后再进行通信。

2.获取设备描述符

在这里插入图片描述
发一堆SOF等待设备初始化成功后,Host会尝试请求设备描述符(简单来讲就是设备是干嘛的,姓什么叫什么,干什么的,是男是女),如果设备此时准备好了,就会回一个ACK,没准备好的话回NAK,Host就等会儿再试。

这三行就是三个包,组成一个事务,包不能跨帧传输,但是就是三个包组成,所以能跨帧。包到事务的概念就有了

图里的SETUP,GET DESCRIPTOR Request DEVICE,ACK都是不同的包,好奇的话可以自己点开看,软件有自动解析数据,可以自己对比看元数据和解析出来的意义。
比较重要的一个Tips就是,不同的包结构不同,包的结构由PID决定,PID就是包的物种,是兔子后面就跟个兔子,是马后面就会跟一个马,至于兔子是白的黑的,就是包携带的信息。
包主要需要了解五种就行了,
SETUP,IN,OUT,设置,输入,输出,这是事务层的头,指示事务的类型,
然后是DATA0,DATA1,顾名思义,数据包0,数据包1,为什么要分0和1?→DATA0和1交替出现有利于数据传输稳定(Device收到0,回了ACK,然后下一个应该收DATA1,如果收到的还是DATA0,那就知道指定是有点什么问题了)

这三行的意思是:
1.告诉我接下来发的是SETUP类型的事务,包含设备地址信息(所以说事务也分几种,前面说了,SETUP,IN,OUT指示事务类型,所以事务就这三种)
2.协议分析仪解析出来的是GET DESCRIPTOR Request DEVICE,也就是请求控制设备描述符命令,这个实际上是一个DATA0包,显示的是包里面解析出来的内容。点开看USB Link Layer可以看到,Setup Data是解析Data 0里面包含数据的意义,也就是数据命令是什么
在这里插入图片描述

3.Device告诉Host,OK,我收到了

前面SETUP事务的意思是,Host让设备把设备描述符传给它,然后它就开始发IN包出来,希望Device能把数据传给它,但是此时Device没准备好,就会一直回NAK,Host就会一直尝试。
在这里插入图片描述
设备准备好了就会回DATA1,DATA1里面包含了Host需要的数据。
图里六行是两个事务,一个IN,一个OUT,设备接收到自己想要的数据,就会发一个空的OUT事务,来结束传输。

此时就引出了传输的概念,刚刚看到的一个SETUP,这里一个IN,一个OUT事务,三个事务组成了一次传输
在这里插入图片描述
这个传输就是一个很简单的,Host跟Device要设备描述符,Device回复设备描述符,然后Host输出OUT传输结束。
(这里面设备描述符只传了8字节,是因为设备只请求了8字节,完整的描述符要传好几次,也就是中间多一个IN包)

不同的事务不同的结构可以组成不同的传输,上面这个是控制传输,xbox手柄里面主要用于查描述符和控制外设状态,一个控制传输可以有一个或者多个事务,比如查描述符可能就是好多事务,控制外设状态只需要一个事务就好。
还有一个要用到的传输是中断传输,是手柄或者鼠标键盘一类上报自身状态用的。

两个用不到的专题,一个是批量传输一个是同步传输,批量传输一般用在U盘打印机传数据,同步传输一般用来传音频。

到这里有个容易混淆的点,IN OUT包和IN OUT事务,IN OUT包就是只传输一个包的具体行为,IN OUT事务,是传输一套数据的行为,IN传输是Host向Device传输,OUT是Host向Device传输。理解这个用usbpv看比较直观:
在这里插入图片描述
图示里面一个OUT传输由OUT包+DATA0+ACK组成,传输的数据内容就是 01 03 02,解析出来就是,Host跟Device说,01→我要控制你的LED,03→这个包长度是3,02→让LED1常亮
下面一个IN传输也是三段组成,Host查询Device状态,Device回复当前LED状态,01→以下是LED状态,03→这个包长度是3,0e→LED全部闪烁(也就是说初始化还没完成,前面的OUT包没发挥作用,控制指令失败,Host接收到这个之后,后面就会再发一次之前的OUT包控制LED)

中间夹的两个传输是SETUP包,注意看可以看到,SETUP包指向的ADDR是一样的,ENDP是不一样的,由此引出一个概念,SETUP传输到Endpoint 0,IN传输到Endpoint 1,OUT传输到Endpoint 2,每个不同的传输行为对应不同的端点。

写着写着写偏了,刚刚的截图是SET Address之后的,看到地址是3,初始化的时候获取设备描述符可以看到信息是发到Address 0 ,Endpoint 0,也就是地址0端点0,然后Host会对总线做一个SE0复位,再分配地址,分配地址流程如下。
在这里插入图片描述
有上面的基础,后面的流程就过一下,Host会请求配置描述符,里面有Endpoint的描述,Host就知道有几个端点了,后面驱动就会从这些端点里面传入传出数据。

EP0是SETUP传输的端点,开头的SETUP包指示需要获取什么数据,MCU的USB协议栈根据请求回复数据。
EP1是IN传输的端点,IN就是Device向Host发数据,手柄是发LED状态,电机状态,按键状态一类
EP2是OUT传输的端点,OUT就是Host向Device发送控制数据,比如LED状态,电机状态

上面这三个传输是最重要的概念,STM32的USB协议栈就是从这里分为不同的函数处理,有三个函数处理这三种传输,SETUP里面根据不同请求触发不同函数,用的最多的是获取描述符的函数,根据不同指令把描述符拼到一起发出去,IN/OUT传输传进来的参数有数据,和Endpoint地址(如果有多个IN/OUT Endpoint可以区分),根据指令把数据传出或控制外设。

给大家一个我总结的协议概念,通信协议像包菜一样,从里到外一层一层,最外层对应几层模型的最底下一层,通常是为了物理层通信稳定设计,中间一层主要是为了寻址和类型指示,上面一层才是数据。
数据在每一层里面,也是分为头,中间,尾,头指示类型,中间携带数据,尾指示数据传输结果(CRC/ACK/NAK),确保传输稳定。

后面再更新Device方面的概念和HAL库&协议栈之间的关系,学习的小技巧就是,找一个实际的真实的东西,结合协议抽象概念,一步步分析,哪里有问题可以问AI,但是也要结合官方文档分析,因为AI会出错,结合官方文档的过程也可以理解官方文档的结构,一举两得。

抓取的USB协议数据我放在主页资源了,自取。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐