免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1436 | 回复: 0
打印 上一主题 下一主题

usb 枚举 传输那些东东 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-02-18 20:22 |只看该作者 |倒序浏览
最近研究了一段时间usb,下面写些自己的心得吧。
关于usb的总结
1: usb 枚举过程
通俗的来说就是你插上去让主机知道你的一些基本信息,但是所有的usb设备都是被动的,都是要求主机向你发送命令,才作出反应。
这里所说的主机host端其实就是你电脑或者嵌入式设备里面的controller,你们可以在linux源码中看到 usb目录下有个叫做host子目录,里面就是这些controller的驱动 包括一些像ehci ohci whci 等等。
好了,我们来看看设备是怎么被动的让他们知道自己的信息的。
下面是通过分析仪抓到的枚举过程。
 
 
 
我们可以看到这里 controller发的第一个命令叫做 get_descriptor 就是拿到一些device的描述信息。
在传输之前说说什么叫做端点,整个usb传输的最底层就是一些usb数据包,这些数据包就是对端点进行的操作,向设备in数据或者out数据。一般一个设备会有很多端点,具体多少个要通过controller发命令拿到的描述,按照usb spec 里面的格式解析出来。但是每个设备必须都有一个control端点,枚举过程的操作都是对这个端点进行的。
好了,我们来分析下 整个get_descriptor 过程,我们叫做一个transfer。
可以看到 一个transfer 下面包括了三个transaction 其实很容易理解,controller要拿到设备的数据 必须经过三个步骤。
第一 告诉你我要拿你数据了,这个时候device开始准备了,但是他不会主动发你要的东西给你,一定要等controller再发个transaction过来往里面填,这里就可以体现了 device为啥喜欢被动了,一定要你发过来)
第二 第二个transaction
第三 controller发送一个transaction 表明我收到了数据了
这个transaction 也不是必须的 在那个set_address 里面就省略了这步。
下面来分析单个 transaction
里面会展开成三个packet 这个就是最底层的usb包了,结构大家可以看看usb spec。三个包为 命令,数据,握手。
其实枚举里面大部分都是这些过程,拿device的信息,设置它的address,为什么要设置他的地址,因为 controller出来就两根数据线d+ d- 两个线上面可能会挂好多设备。通过addr来发送到特定的设备,也可以看到最底层的包结构里面包括它了(ADDR)
上面是从协议里面分析了枚举过程。
 
下面从代码里面看看吧:
代码里面来分析下整个传输的过程吧。参考 linux kernel
usb_get_device_descriptor
  usb_control_msg()
   usb_submit_urb()
    ehci_urb_enqueue()
主要看看这个函数吧 ehci_urb_enqueue
主要的两个函数 qh_urb_transaction
               submit_async
qh_urb_transaction  整个意思就是,怎么把上层给我的请求(transfer)变成几个transaction
这里面怎么填写的就要参考ehci的协议了
每个qh(transfer)结构里面有个 qtd pointer就是指向那个transaction的,这些transaction自己又是链在一起的。然后硬件就开始干活的,执行完一个transaction后呢,就搬运下面一个transaction到自己的overlay(qh里面保存qtd的结构)来执行,执行完就按你软件设置的,控制要不要回中断,通知软件。
相应的软件也可以通过里面置一些位来控制,controller是否暂停该qtd,linux里面通过一个叫dummy的qtd来使得该qh暂停,这样做的方便之处是下一个还要用这个qh来传东西的时候,就不要重新去建立qh了,直接把要传的qtd和dummy去替换就ok了。
 
每个请求(例如:get_device_desriptor)就是一个qh ,如果qh一样呢,就把你变成的那些transaction接着链下去,上层呢不断的发请求下面就不断的链,硬件就不断的跑。
head ->qh->qh->qh->(指到head 环形链表)
controller就运行qh下面的qtd然后就跳到下一个qh的qtd去执行。注意不是把该qh下面所有的qtd执行完再去执行下一个qh。
 
枚举完成了,主机也知道了你是啥设备,你支持那些协议那些命令了,假设我们的usb设备是u盘,我们来分析一下数据是怎么读写的吧。
枚举的过程中我们知道了这个设备支持走那些协议,一般来说了U盘都是走bulkonly协议的。
什么是bulkonly协议呢。那肯定是bulk传输了,和前面的control传输不一样了,不一样之处就是走的端点不一样了。control传输走的是 ENDP 0(断点0),现在就是ENDP 1或者ENDP 2,其实就是一进一出,读数据写数据啦。
bulkonly协议呢,也分成三步其实思想都差不多。看看下面分析仪抓的包吧:
 

1:发31bytes告诉device我要干嘛,这里面肯定就是填些命令,什么命令呢就看device支持啥(我用的u盘就支持scsi命令),device收到好,就开始准备了。
2:要么是要device数据(例如usb读操作)要么就是给device数据(写操作)。
3:收13bytes 判断这次传输的状态,是好是坏。
一切传输都比较顺利的话,还是比较简单的,但是要考虑到里面很多出错处理,例如中断的丢失,要让整个系统运行起来还是比较烦的。
下次有空结合linux源码分析分析里面的传输,包括链链表,删链表,软件和硬件的握手,这里赞下linux的源码,写的确实牛。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP