USB学习笔记——USB通信过程与枚举过程

Posted 一个月后又可以改名了!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了USB学习笔记——USB通信过程与枚举过程相关的知识,希望对你有一定的参考价值。

在网上看到一篇文章就是讲这个的,仔细阅读后获得了很多感触,整理总结如下。

一、USB接口

在USB的集线器端D-,D+都接了下拉电阻,而USB设备端的D-,D+接了上拉电阻,所以当USB设备插入时可以根据集线器端D-,D+上的电压变化来判断是否有USB设备接入。

检测到有设备接入后,可以根据D-,D+来判断USB设备的工作模式,是低速还是全速或者高速。所以D-,D+这两根线很重要。

二、 USB数据传输过程

主机与USB设备相互传输数据具体过程如下:

1、客户软件首先将传输的数据放入缓冲区,同时向USB总线驱动程序发出IRPS,请求数据传输。

2、USB驱动程序接收到程序接收请求,并对数据进行处理,转化为具有USB格式的事务处理

3、 USB主控制器驱动程序将这些事务处理建立成事物列表,同时要求不能超过USB的带宽。

4、USB主控制器读取到事务列表并将事务列表转化为信息包,发送到USB总线上。

5、USB设备收到这些信息后,将其解包后放入指定端点的接受缓冲区内,由芯片固件对其进行处理。

图解:

 三、USB枚举过程

枚举就是USB设备上电后,主机从设备上读取一些信息,知道设备是什么样的设备,如何进行通信,主机根据这些信息来加载合适的驱动程序

枚举的整体框架:供电、复位、获取Device Description前8个字节信息、复位(可选)、分配地址、获取Device Description、获取Configuration Description、获取string Description(可选)、配置。

以下是枚举的具体流程:

1、检测到电压变化,报告主机

USB设备上电后,被检测到后将信息反馈给主控制器,告知其有设备连接。

2、主机了解连接设备

主机在知道有设备接入后会发送一个Get_Port_Status请求(request)给hub以了解此次状态改变的确切含义。

3、检测接入的设备是高速/全速

通过检测USB空闲时差分线的高低电平来判断连接设备的速度类型。

4、复位设备

主机得知新设备已经连接上以后,等待100ms等电源工作稳定,然后主控器发请求复位刚插上的端口,复位就是将D-,D+拉低10ms以上。复位信号只会发给刚插上的USB设备。

5、主检测是全速还是高速

高速在初始时也是全速运行的,如果是高速设备则改为高速运行。

6、建立设备和主机之间运行的信息通道

主机判断设备是否复位成功,设备处于空闲状态,准备接收主机的请求,因为所有USB设备复位完后还没有分配地址,所以设备和主机通过默认地址0端口0来进行通信。

7、主机发送Get_Descriptor请求获取默认管道的最大包长度(获取Device Description)

默认端口在设备一端就是端点0,未分配地址的设备都是通过地址0来获取主机的请求,因为枚举过程中,一次枚举一个设备的方式进行,不会发生多个设备同时响应主机发来的请求。设备描述符的第8字节代表设备端点0的最大包大小。这次读取主要是为了获得最大包大小。当完成第一次的控制传输后,也就是完成控制传输的状态阶段,系统会要求hub对设备进行再一次的复位操作(可选操作)。

8、主机给设备分配一个地址

主机控制器通过Set_Address请求向设备分配一个唯一的地址。在完成这次传输之后,设备进入地址状态(Address state),之后就启用新地址继续与主机通信。这个地址对于设备来说是终生制的,设备在,地址在;设备消失(被拔出,复位,系统重启),地址被收回。同一个设备当再次被枚举后得到的地址不一定是上次那个了。

9、主机获取设备的信息

 主机发送 Get_Descriptor请求到新地址读取设备描述符,这次主机发送Get_Descriptor请求可算是诚心,它会认真解析设备描述符的内容。设备描述符内信息包括端点0的最大包长度,设备所支持的配置(Configuration)个数,设备类型,VID(Vendor ID,由USB-IF分配), PID(Product ID,由厂商自己定制)等信息。

    之后主机发送Get_Descriptor请求,读取配置描述符(Configuration Descriptor),字符串等,逐一了解设备更详细的信息。事实上,对于配置描述符的标准请求中,有时wLength一项会大于实际配置描述符的长度(9字节),比如255。这样的效果便是:主机发送了一个Get_Descriptor_Configuration 的请求,设备会把接口描述符,端点描述符等后续描述符一并回给主机,主机则根据描述符头部的标志判断送上来的具体是何种描述符。

      接下来,主机就会获取配置描述符。配置描述符总共为9字节。主机在获取到配置描述符后,根据里面的配置集合总长度,再获取配置集合。配置集合包括配置描述符,接口描述符,端点描符等等。

     如果有字符串描述符的话,还要获取字符串描述符。另外HID设备还有HID描述符等。

10、主机给设备挂载驱动

主机通过解析描述符后对设备有了足够的了解,会选择一个最合适的驱动给设备。最后调用设备模型提供的接口device_add将设备添加到 usb 总线的设备列表里,然后 usb总线会遍历驱动列表里的每个驱动,调用自己的 match(usb_device_match) 函数看它们和你的设备或接口是否匹配,匹配的话调用device_bind_driver函数,现在就将控制权交到设备驱动了。   

11、设备驱动选择一个配置

根据前面设备回复的信息,发送Set_Configuration请求来正式确定选择设备的哪个配置作为工作配置。至此,设备处于配置状态,当然,设备也应该使能它的各个接口。

四、总结

下一篇写详细的实现过程与一些需要了解的特性。

以上是关于USB学习笔记——USB通信过程与枚举过程的主要内容,如果未能解决你的问题,请参考以下文章

Android usb学习笔记:Android AOA协议设备端 流程总结

分析罗技USB鼠标的枚举过程

stm32f4 USB项目开发详解

usb枚举

Android usb学习笔记:Android AOA协议Android端 流程总结

USB枚举过程