📄 linux下usb.c源代码分析.txt
字号:
用于传输的数据结构和宏
Linux USB子系统只用一个数据传输结构名为USB Request Block(URB)。这个结构包含了用于启动任何USB传输类型的所有参数。所有的传输请求都被异步的发送给USB core而且通过回调函数告知回调完成。
URB 结构:
标记了“>”的是输入参数,M表示强制性的而且O表示可选择的。标记“<”的是返回值。标记了“T”的是临时参数(输入、输出)。所有非普通元素都用三列标记了它们代表控制,中断和同步传输。“X”表示这个元素与传输类型相关。
dev [mandatory input parameter]
这个元素指向usb_device结构
pipe [mandatory input parameter]
管道元素被用来对端点号和特征进行编码。以下的几个宏用来创建一个适当的管道值:
pipe=usb_sndctrlpipe(dev,endpoint)
pipe=usb_rcvctrlpipe(dev,endpoint)
为downstream或upstream控制与一个给定的端点进行传输创建一个管道。dev指向usb_device结构。endpoint通常为0。
pipe=usb_sndbulkpipe(dev,endpoint)
pipe=usb_rcvbulkpipe(dev,endpoint)
为downstream或upstream控制与一个给定的端点进行块传输创建一个管道。
1<=endpoint<=15(依赖于活动的端点描述符)
pipe=usb_sndintpipe(dev,endpoint)
pipe=usb_rcvintpipe(dev,endpoint)
为downstream或upstream控制与一个给定的端点进行中断传输创建一个管道。
1<=endpoint<=15(依赖于活动的端点描述符)
.transfer_buffer [mandatory input parameter]
这个元素指向传输缓冲区,该缓冲区包含了与设备进行传输的数据。这个缓冲区必须作为一个非页式的临近物理内存块来分配(用void *kmalloc(size_t,GFP_KERNEL)来实现)。
.transfer_buffer_length [mandatory input parameter]
这个元素指用字节指定了传输缓冲区的大小。对于中断和控制传输,缓冲区必须小于或等于相关端点数据包的最大值。数据包的大小可以在端点描述符中的wMaxPacketSize找到。
块传输比wMaxPacketSize大,wMaxPacketSize会自动的被分成更小的块。
.complete [optional input parameter]
以上的USB子系统处理请求是异步的。这个元素允许为调用者指定一处理函数,这个处理函数在请求完成后被调用。这个处理的目的是尽快完成调用者指定的请求,因为调用不受主机硬件中断处理器控制的。这意味着请求代码的其它约束都被中断控制器记录。
.context [optional input parameter]
.transfer_flags [optional input parameter and return value]
在处理传输请求过程时可以指定多个传输标志来改变处理动作。
.USB_DISABLE_SPD
这个标志禁止短小的数据包。如果一个upstream请求传输比端点最大数据包少的数据时就会发生短小的数据包。
USB_NO_FSBR
USB_ISO_ASAP
当安排同步请求时这个标志将告诉主机控制器尽快启动传输。如果没有指定USB_ISO_ASAP,就必须指定启动结构。如果同步传输不是必须与当前的结构数量同步,则推荐使用这个标志。当前的结构数量是11bit,它每毫秒就增加。
USB_ASYNC_UNLINK
取消URB时有可能是同步或异步的。用这个标志接通异步unlinking。
USB_TIMEOUT_KILLED
这个标志只在主机控制器标记URB由于超时被杀掉时设置。URB状态反映引起超时的错误。
USB_QUEUE_BULK
这个标志是用来允许块传输加入队列。一般情况下对于指定设备的一个端点只有一个块传输能加入队列。
.next [optional input parameter]
使用next指针可以在一条链中链接几个URBs。它允许你发送一个USB传输序列到USB内核。这个链必须被NULL指针终止或最后一个URB必须首先连接。这允许重复安排多个URBs传输连续的数据流。
.status [return value]
这个标志代表着一个正在进行或已经完成的请求的状态。在成功发送一个请求到USB内核后状态为-EINPROGRESS。成功完成一个请求后为0。
.actual_length [return value]
完成请求后这个元素记载着传输的字节数。保留的URB元素指定为传输类型。
.Bulk Transfers
不要指定额外的参数。
Control Transfers
setup_packet [mandatory input parameter]
第一步是启动数据包的downstream 传输。这个元素指向包含启动数据的缓冲区。这个缓冲区必须作为非页式的相邻物理内存块来分配(用void *kmalloc(size_t, GFP_KERNEL)来实现)。
Interrupt Transfers
start_frame [return value]
interval [mandatory input parameter]
这个元素为中断传输指定以毫秒为间隔。1<=interval<=255。指定0ms间隔会引起一个短暂的中断(不会自动重新安排)。你可以为中断端点在端点描述符中的bInterval找到中断间隔。
Isochronous Transfers
start_frame [input parameter or return value]
这个元素指定同步传输安排的第一个结构数。设置start_frame允许与端点进行同步传输。如果设置了USB_ISO_ASAP标志这个元素就会指示同步传输安排的第一个结构数。
number_of_packets [mandatory input parameter]
同步传输请求被当作一系列请求信号发送给USB内核。一个单独的请求信号传输一个数据包到一个指定的端点(管道)。这个元素设定传输的数据包数量。
error_count [return value]
在请求完成后(URB status is!=-EINPEOGRESS)这个元素记载了错误数据包的数量。Iso_frame_desc结构中有传输请求信号的详细情况。
timeout [input parameter] 在jiffies中超时可以指定自动的从主机控制器的时间表中删除一个URB。发生超时就会设置USB_TIMEOUT_KILLED。实际的传输状态代表着引起超时的USB状态。
iso_frame_desc [mandatory input parameter]
在每个同步URB的末尾这些结构为每个单独的请求数据包填充参数。
offset [mandatory input parameter]
为每个单独的请求指定偏移地址到transfer_buffer。
length [mandatory input parameter]
为每个单独的数据包指定数据缓冲区大小。如果length设置为0 USB结构会被跳过而且不会初始化传输。这个选项可被用来同步数据流。
actual_length [return value]
返回请求传输的实际字节数。
status [return value]
返回这个请求的状态。
URB函数
USB内核有四个处理URBs的函数。
purb_t usb_alloc_urb(int iso_packets);
要用到URB结构时调用此函数。ios_packets是用来在启动同步传输时在URB结构末尾指定iso_frame_desc的数量。如果成功则返回的指向URB结构的指针为0,否则返回NULL指针。
void usb_free_urb (purb_t purb);
用usb_alloc_urb释放内存时就调用此函数。
int usb_submit_urb(purb_t purb);
这个函数异步的发送一个传输请求给USB内核。purb指向以前的已初始化的URB结构。成功则返回0,否则返回对应的错误代码。这个函数返回的不会是块而且能够在无需等待的情况下为不同的端点安排多个URBs。在同步端点,还可以为一个端点安排多个URBs。这是USB协议错误处理和重试机制的限制。
int usb_unlink_urb(purb_t purb);
这个函数用来在请求完成之前取消操作。purb指向以前提交的URB结构。依赖于传输标志USB_ASYNC_UNLINK可以同步或异步的调用这个函数。同步的调用函数需要等待1ms而且不能在中断或完成的处理中调用。成功则返回0。异步调用则立刻返回。如果函数成功的启动了返回值为-EINPROGRESS。在函数完成以后当调用usb_unlink_urb时要用到完全的处理过程。URB的状态由-ENOENT(同步调用)或-ECONNRESET(异步调用)表示
usb_unlink_urb也用在终止一个中断传输URB。
URB宏
以下的宏用于初始化不同的传输类型:
FILL_CONTROL_URB(purb, dev, pipe, setup_packet, transfer_buffer, transfer_buffer_length, complete, context);
FILL_BULK_URB(purb, dev, pipe, transfer_buffer, transfer_buffer_length, complete, context);
FILL_INT_URB(purb, dev, pipe, transfer_buffer, transfer_buffer_length, complete, context, interval);
FILL_CONTROL_URB_TO();
FILL_BULK_URB_TO();
兼容性
USB内核包含多个较高级的函数,这些函数是为了与旧APIs兼容。有些函数仍然用来阻塞控制或块传输。
int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout);
发送一个阻塞标准控制请求。在jiffies必须指定超时。成功则返回一正数,该正数代表传输的字节,否则返回错误代码。
int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, unsigned long *actual_length, int timeout);
发送一个阻塞标准块控制。actual_length是一个可选的指针,它指向的变量代表这个请求传输的实际字节数。jiffies中必须要指定超时。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -