USB传输标志有多种,我们今天主要看一下transfer_flags每个标志的意义
transfer_flags
/*
* urb->transfer_flags:
*
* Note: URB_DIR_IN/OUT is automatically set in usb_submit_urb().
*/
#define URB_SHORT_NOT_OK 0x0001 /* report short reads as errors */
#define URB_ISO_ASAP 0x0002 /* iso-only, urb->start_frame ignored */
#define URB_NO_TRANSFER_DMA_MAP 0x0004 /* urb->transfer_dma valid on submit */
#define URB_NO_SETUP_DMA_MAP 0x0008 /* urb->setup_dma valid on submit */
#define URB_NO_FSBR 0x0020 /* UHCI-specific */
#define URB_ZERO_PACKET 0x0040 /* Finish bulk OUT with short packet */
#define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt needed */
#define URB_FREE_BUFFER 0x0100 /* Free transfer buffer with the URB */
#define URB_DIR_IN 0x0200 /* Transfer from device to host */
#define URB_HCD_DRIVER_TEST 0xFFFF /* Do NOT hand back or free this URB */
#define URB_DIR_OUT 0
#define URB_DIR_MASK URB_DIR_IN
下面重点讲解以下几个标志
(1)URB_SHORT_NOT_OK
这个标记只对用来从IN 端点读取数据的urb 有效,意思就是说如果从一个IN 端点那里读取了一个比较短的数据包,就可以认为是错误的。那么这里的short 究竟short 到什么程度?之前说到端点的时候,就知道端点描述符里有一个叫wMaxPacketSize 这样的东东,指明了端点一次能够处理的最大字节数。
(2)URB_ISO_ASAP
这个标志只是为了方便等时传输用的。等时传输和中断传输在spec 里都被认为是periodic transfers,也就是周期传输,咱们都知道在usb 的世界里都是主机占主导地位,设备是没多少发言权的,但是对于等时传输和中断传输,端点可以对主机表达自己一种美好的期望,希望主机能够隔多长时间访问自己一次,这个期望的时间就是这里说的周期。
(3)URB_NO_TRANSFER_DMA_MAP & URB_NO_SETUP_DMA_MAP
这两个标志都是有关DMA 的,什么是DMA?就是外设,比如咱们的usb 摄像头,和内存之间直接进行数据交换。一般来说,都是驱动里提供了kmalloc 等分配的缓冲区,HCD 做一定的DMA 映射处理,DMA 映射是干吗的?外设和内存之间进行数据交换,总要互相认识吧,外设是通过各种总线连到主机里边儿的,使用的是总线地址,而内存使用的是虚拟地址,它们之间本来就是两条互不相交的平行线,要让它们中间产生连接点,必须得将一个地址转化为另一个地址,这样才能找得到对方,才能互通有无,而DMA 映射就是干这个的。
(4)URB_ZERO_PACKET
这个标志表示批量的OUT 传输必须使用一个short packet 来结束。批量传输的数据大于批量端点的wMaxPacketSize 时,需要分成多个Data 包来传输,最后一个data payload 的长度可能等于wMaxPacketSize,也可能小于,当等于wMaxPacketSize 时,如果同时设置了URB_ZERO_PACKET 标志,就需要再发送一个长度为0 的数据包来结束这次传输,如果小于wMaxPacketSize 就没必要多此一举了。
(5)URB_NO_INTERRUPT
这个标志用来告诉HCD,在URB 完成后,不要请求一个硬件中断,当然这就意味着你的结束处理函数可能不会在urb 完成后立即被调用,而是在之后的某个时间被调用,咱们的usb core 会保证为每个urb 调用一次结束处理函数。