分类: LINUX
2008-11-14 16:40:24
一个USB的端点(endpoint)只能够向一个方法传送数据。从主机到设备,或者是从设备到主机,可以将端点看作是条单行道,数据只能够单向”行驶”。单个USB设备最多支持31个端点,同一端点的输入输出端点号地址都是相同的,从1~15。
Endpoint分为四种类型:
1、CONTROL 传送少量的数据,一般作为设备的控制使用,例如:向设备发送控制命令,从设备得到当前的状态报告。每个USB设备都有一个endpoint 0 用来在USB插入时对设备进行配置。
2、INTERRUPT 负责传送少量的数据,在每次USB请求设备数据时以固定的速率发出,比如说USB的鼠标和USB键盘数据的传送。该端点是异步的,在指令传输错误的情况下可以重传。
3、BULK 发送大量的数据,但是不允许丢失数据。端点一般说来比INTERRUPT大,在数据过大无法一次性传输的情况下,将数据分成多个块传输到设备上或者主机上。可以用在U盘和电脑之间传输数据来理解。同样,BLUK是异步方式的。
4、ISOCHRONOUS 这是一个同步传输的端点,用来队数据进行同步传输,可以丢失部分数据,更多的依赖于保持持续的数据流,比如说USB音箱播放声音。
在/include/linux/usb_ch9.h中,可以看到端点的描述定义:
struct usb_endpoint_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bEndpointAddress;
__u8 bmAttributes;
__le16 wMaxPacketSize;
__u8 bInterval;
// NOTE: these two are _only_ in audio endpoints.
// use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof.
__u8 bRefresh;
__u8 bSynchAddress;
} __attribute__ ((packed));
可以发现,这些数据的定义并不符合Linux Kernel编码规范,因为这些成员直接对应于 USB 规范中的名子. USB 内核程序员认为使用规定的名子更重要, 以便在阅读规范时减少混乱, 不必使这些名子对 Linux 程序员看起来熟悉。
看到中间的4个部分bEndpointAddress、bmAttributes、wMaxPacketSize 、bInterval。在Linux Device Drivers上对这些成员是这么描述的:
bEndpointAddress
这是这个特定端点的USB 地址。还包含在这个8-位值的是端点的方向。位掩码 USB_DIR_OUT和USB_DIR_IN可用来和这个成员比对,来决定给这个端点的数据是到设备还是到主机。
bmAttributes
这是端点的类型。位掩码USB_ENDPOINT_XFERTYPE_MASK应当用来和这个值比对。来决定这个端点是否是USB_ENDPOINT_XFER_ISOC,USB_ENDPOINT_XFER_BULK,或者是类型USB_ENDPOINT_XFER_INT。相应地。这些宏定义了同步,块,和中断端点。
wMaxPacketSize
这是以字节计的这个端点可一次处理的最大大小。注意驱动可能发送大量的比这个值大的数据到端点,但是数据会在真正传送到设备时被分为wMaxPakcetSize的块。对于高速设备,这个成员可用来支持端点的一个高带宽模式,通过使用几个额外位在这个值的高位部分。关于如何完成的细节见 USB 规范。
bInterval
如果这个端点是中断类型的,这个值是为这个端点设置的间隔,即在请求端点的中断之间的时间,这个值以毫秒表示.。
其实,我们可以用网络上的一些知识来类比这些成员:
bEndpointAddress -- IP地址,同样的,两者都采用了 唯一标识来确认一个地址
bmAttributes –- TCP/IP协议或者其他。都是对当前的数据传输定义一个标准
wMaxPacketSize – MTU,对传输的包的大小进行限制。
bInterval – 延迟,从源到目的地传输一个单位量所花费的时间量。