Linux那些事儿之我是USB
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人
 6.我是一棵树

6.我是一棵树

“我是一棵树,静静地站在田野里,风儿吹过,我不知它的去向,人儿走过,我不知谁会为我停留。”

如图1.6.1所示,USB子系统的拓扑也是一棵树,它并不以总线的方式来部署。

图1.6.1 USB子系统的树形结构

我曾经指着路边一棵奇形怪状的树问朋友:“这是什么树?”朋友的回答让我很晕:“大树。”那图1.6.1指的是什么树?自然也是大树了,不过却是USB的大树。这棵大树主要包括USB连接、USB Host Controller(USB主机控制器)和USB设备三个部分。而USB设备还包括了Hub和功能设备(也就是图1.6.1中的Func)。

什么是USB主机控制器?控制器,顾名思义,用于控制。控制什么?控制所有的USB设备的通信。通常,计算机的CPU并不是直接和USB设备打交道,而是和控制器打交道。它要对设备做什么,它会告诉控制器,而不是直接把指令发给设备。然后控制器再去负责处理这件事情,它会去指挥设备执行命令,而CPU就不用管剩下的事情。控制器替它去完成剩下的事情,事情办完了再通知CPU。否则,让CPU去盯着每一个设备做每一件事情,那是不现实的。

那么Hub是什么?在大学里,有的宿舍里网口有限,所以会有网口不够用的情况出现,于是有人会使用Hub,让多个人共用一个网口,这是以太网上的Hub。而USB的世界里同样有Hub,其实原理是一样的,任何支持USB的计算机不会只允许你只能一个时刻使用一个USB设备,比如,你插入了U盘,同样还可以插入USB键盘,然后再插一个USB鼠标,因为你会发现你的计算机里并不只是一个USB接口。这些接口实际上就是所谓的Hub口。

而现实中经常是一个USB控制器和一个Hub绑定在一起,专业一点称为“集成”,而这个Hub也被称做Root Hub。换而言之,和USB控制器绑定在一起的Hub就是系统中最根本的Hub,其他的Hub可以连接到它这里,然后可以延伸出去,外接别的设备,当然也可以不用别的Hub,让USB设备直接接到Root Hub上。

而USB连接指的就是连接USB设备和主机(或Hub)的四线电缆。电缆中包括VBUS(电源线)、GND(地线)和两根信号线。USB系统就是通过VBUS和GND向USB设备提供电源的。主机对连接的USB设备提供电源供其使用,而每个USB设备也能够有自己的电源,如图1.6.2所示。

现在,如图1.6.3所示的USB大树里只有Compound Device还没有说。那么,Compound Device又是什么样的设备?其实,在USB的世界里,不仅仅有Compound Device,还有Composite Device,简单的中文名字已经无法形象地表达它们的区别。正如图1.6.3所示,Compound Device是将Hub和连在Hub上的设备封装在一起所组成的设备。而Composite Device则是包含彼此独立的多个接口的设备。从主机的角度看,一个Compound Device和单独的一个Hub,然后连接了多个USB设备是一样的,它里面包含的Hub和各个设备都会有自己独立的地址,而一个Composite Device里不管有多少接口,它都只有一个地址。

图1.6.2 USB四线电缆

USB大树要想茁壮成长,离不开USB协议。USB总线是一种轮询式总线。协议规定所有的数据传输都必须由主机发起,由主机控制器初始化所有的数据传输,各种设备紧紧围绕在主机周围。

USB通信最基本的形式是通过USB设备中一个叫Endpoint(端点)的东西,而主机和端点之间的数据传输是通过Pipe(管道)。

端点就是通信的发送点或者接收点,要发送数据,只需把数据发送到正确的端点就可以了。而管道,实际上只是为了让我们能够找到端点,就相当于我们日常说的邮编地址。

图1.6.3 Compound Device

比如一个国家,为了通信,我们必须给各个地方取名,然后给各条大大小小的路取名字。严格来说,管道的另一端应该是USB主机,USB协议也是这么说的,协议说管道代表着在主机和设备上的端点之间移动数据的能力。

端点不但是有方向的,而且这个方向还是确定的,要么是in,要么是out,没有既是in又是out的,都是生来就注定的。

有没有特殊的端点呢?看你怎么去理解0号端点了,协议规定了,所有的USB设备必须具有端点0,它可以作为in端点,也可以作为out端点。USB系统软件利用它来实现默认的控制管道,从而控制设备。

端点也是限量供应的,不是想要多少就有多少,除了端点0,低速设备最多只能拥有两个端点,高速设备也最多只能拥有15个in端点和15个out端点。这些端点在设备内部都有唯一的端点号,这个端点号是在设备设计时就已经指定的。

为什么端点0就特殊呢?这还是有内在原因的。管道的通信方式其实有两种:一种是stream的,一种是message的。message管道要求从它那儿过的数据必须具有一定的格式,不是随便传的,因为它主要就是用于主机向设备请求信息的,必须得让设备明白请求的是什么。而stream管道就没这么苛刻,随和多了,对数据没有特殊的要求。协议中规定,message管道必须对应两个相同号码的端点:一个用来in,一个用来out,默认管道就是message管道。当然,与默认管道对应的端点0就必须是两个具有同样端点号0的端点。

USB端点有四种类型,分别对应了四种不同的数据传输方式。它们是控制传输(Control Transfers)、中断传输(Interrupt Data Transfers)、批量传输(Bulk Data Transfers)和等时传输(Isochronous Data Transfers)。

● 控制传输用来控制对USB设备不同部分的访问,通常用于配置设备,获取设备信息,发送命令到设备,或者获取设备的状态报告。总之,就是用来传送控制信息的,每个USB设备都会有一个名为“端点0”的控制端点,内核中的USB Core使用它在设备插入时进行设备的配置。

● 中断传输用来以一个固定的速率传送少量的数据,USB键盘和USB鼠标使用的就是这种方式,USB的触摸屏也是使用这种方式,传输的数据包含了坐标信息。

● 批量传输用来传输大量的数据,确保没有数据丢失,但不保证在特定的时间内完成。U盘使用的就是批量传输,用它备份数据时需要确保数据不能丢,而且也不能指望它能在一个固定的比较快的时间内复制完。

● 等时传输同样用来传输大量的数据,但并不保证数据是否到达,以稳定的速率发送和接收实时的信息,对传送延迟非常敏感,显然是用于音频和视频一类的设备。这类设备期望能够有一个比较稳定的数据流,比如在用QQ视频聊天时,肯定希望每分钟传输的图像/声音速率是比较稳定的,不能说这一分钟前对方看到你在向她或向你深情表白,可是下一分钟却看见画面停滞在那里,只能看到你在那里一动不动,这不是浪费感情吗?

如图1.6.1所示的树形结构描述的是实实在在的物理拓扑,对于内核中的实现来说,没有这么复杂,所有的Hub和设备都被看做是一个个的逻辑设备(Logical Device),如图1.6.4所示,好像它们本来就直接连接在Root Hub上一样。

如图1.6.5所示,一个USB逻辑设备就是一系列端点的集合,它与主机之间的通信发生在主机上的一个缓冲区和设备上的一个端点之间,通过管道来传输数据。也就是说,管道的一端是主机上的一个缓冲区,一端是设备上的端点。

那么图1.6.5中的接口又是指什么?简单地说,USB端点被捆绑为接口(Interface),一个接口代表一个基本功能。有的设备具有多个接口,像USB扬声器就包括一个键盘接口和一个音频流接口。在内核中,一个接口要对应一个驱动程序,USB扬声器在Linux里就需要两个不同的驱动程序。到目前为止,一个设备可以包括多个接口,一个接口可以具有多个端点,当然以后我们会发现并不仅仅止于此。

图1.6.4 USB逻辑拓扑结构

图1.6.5 USB数据通信