/Documentation/usb/URB.txt

如果想评论或更新本文的内容,请直接联系原文档的维护者。

如果你使用英文交流有困难的话,也可以向中文版维护者求助。

如果本翻译更新不及时或者翻译存在问题,请联系中文版维护者。

中文版维护者: 姚家珺AriosYao   ks666dejia@163.com

中文版翻译者: 姚家珺AriosYao   ks666dejia@163.com

中文版校译者: 姚家珺AriosYao   ks666dejia@163.com

 

Revised: 2000-Dec-05.
Again:   2002-Jul-06
Again:   2005-Sep-19

    NOTE/小记:

    The USB subsystem now has a substantial section in "The Linux Kernel API"
    guide (in Documentation/DocBook), generated from the current source
    code.  This particular documentation file isn't particularly current or
    complete; don't rely on it except for a quick overview.

 USB子系统现在有一个主要部分“Linux内核API”
    指南(在 Documentation/DocBook),从当前源
    代码产生。这种特定的文档文件并不是完全正确或者完整的;除非是为了快速了解,尽量不要依赖它。

1.1. Basic concept or 'What is an URB?'/基本概念,什么是URB?

The basic idea of the new driver is message passing, the message itself is
called USB Request Block, or URB for short.

新的驱动程序的基本思路是消息传递,消息本身是
称为USB请求块,或URB。

- An URB consists of all relevant information to execute any USB transaction
  and deliver the data and status back.
 
  一个URB包括执行任何USB事务和提供的数据和状态回所有相关信息。

- Execution of an URB is inherently an asynchronous operation, i.e. the
  usb_submit_urb(urb) call returns immediately after it has successfully
  queued the requested action.
 
  URB本质上是执行一个异步操作,即usb_submit_urb(URB)调用后立即返回它已经成功地排队请求的操作。

- Transfers for one URB can be canceled with usb_unlink_urb(urb) at any time.

  一个URB转发可以在任何时候用usb_unlink_urb(URB)取消。

- Each URB has a completion handler, which is called after the action
  has been successfully completed or canceled. The URB also contains a
  context-pointer for passing information to the completion handler.
 
  每个URB有一个完成处理操作,这就是所谓的行动后,已成功完成或取消。
  URB还包含一个上下文指针传递信息用以完成处理。

- Each endpoint for a device logically supports a queue of requests.
  You can fill that queue, so that the USB hardware can still transfer
  data to an endpoint while your driver handles completion of another.
  This maximizes use of USB bandwidth, and supports seamless streaming
  of data to (or from) devices when using periodic transfer modes.
 
  每个端点设备在逻辑上支持的请求队列。
  您可以填写该队列,使USB硬件仍然可以在您的驱动程序处理完成另一个操作的同时传输数据到端点。
  这最大限度地利用了USB带宽,并在使用定期传输模式时支持无缝输入(输出)设备的数据流。


1.2. The URB structure/URB结构

Some of the fields in an URB are:/URB的部分结构:

struct urb
{
// (IN) device and pipe specify the endpoint queue
 struct usb_device *dev;         // pointer to associated USB device
 unsigned int pipe;              // endpoint information

 unsigned int transfer_flags;    // ISO_ASAP, SHORT_NOT_OK, etc.

// (IN) all urbs need completion routines
 void *context;                  // context for completion routine
 void (*complete)(struct urb *); // pointer to completion routine

// (OUT) status after each completion
 int status;                     // returned status

// (IN) buffer used for data transfers
 void *transfer_buffer;          // associated data buffer
 int transfer_buffer_length;     // data buffer length
 int number_of_packets;          // size of iso_frame_desc

// (OUT) sometimes only part of CTRL/BULK/INTR transfer_buffer is used
 int actual_length;              // actual data buffer length

// (IN) setup stage for CTRL (pass a struct usb_ctrlrequest)
 unsigned char* setup_packet;    // setup packet (control only)

// Only for PERIODIC transfers (ISO, INTERRUPT)
    // (IN/OUT) start_frame is set unless ISO_ASAP isn't set
 int start_frame;                // start frame
 int interval;                   // polling interval

    // ISO only: packets are only "best effort"; each can have errors
 int error_count;                // number of errors
 struct usb_iso_packet_descriptor iso_frame_desc[0];
};

Your driver must create the "pipe" value using values from the appropriate
endpoint descriptor in an interface that it's claimed.

您的驱动程序必须创建一个接口“管”,它声称适当的端点描述符中的值。


1.3. How to get an URB?/如何使用URB:

URBs are allocated with the following call
URB通过下面的调用启动

 struct urb *usb_alloc_urb(int isoframes, int mem_flags)

Return value is a pointer to the allocated URB, 0 if allocation failed.
The parameter isoframes specifies the number of isochronous transfer frames
you want to schedule. For CTRL/BULK/INT, use 0.  The mem_flags parameter
holds standard memory allocation flags, letting you control (among other
things) whether the underlying code may block or not.

如果分配失败,返回值是一个指针分配URB,0。
参数isoframes指定你要安排的同步传输帧的数量。对于CTRL/BULK/INT, use 0。
参数mem_flags保存了标准内存分配标志,让您控制底层代码(其中包括)是否可能被阻止。

To free an URB, use/释放URB

 void usb_free_urb(struct urb *urb)

You may free an urb that you've submitted, but which hasn't yet been
returned to you in a completion callback.  It will automatically be
deallocated when it is no longer in use.

您可能会释放一个你已经提交的URB,但在一个完整的回调中尚未返回。此时它会自动被解除分配,不再使用。


1.4. What has to be filled in?/需要填写的信息

Depending on the type of transaction, there are some inline functions
defined in <linux/usb.h> to simplify the initialization, such as
fill_control_urb() and fill_bulk_urb().  In general, they need the usb
device pointer, the pipe (usual format from usb.h), the transfer buffer,
the desired transfer length, the completion  handler, and its context.
Take a look at the some existing drivers to see how they're used.

根据不同的事务,也有一些内联函数中定义<linux/usb.h>简化初始化,如fill_control_urb()和fill_bulk_urb()。
在一般情况下,他们需要USB设备的指针,管道(usb.h中常用的格式),传输缓冲区,需要的传输长度,完成处理程序,它的上下文。
了解一些一些现有的驱动程序,看看他们是如何使用。

Flags:/标志
For ISO there are two startup behaviors: Specified start_frame or ASAP.
For ASAP set URB_ISO_ASAP in transfer_flags.

对于ISO有两个启动行为:指定start_frame的或ASAP。
对于ASAP,在transfer_flags设置URB_ISO_ASAP。

If short packets should NOT be tolerated, set URB_SHORT_NOT_OK in
transfer_flags.

如果短数据包无法使用,在transfer_flags设置URB_SHORT_NOT_OK。

1.5. How to submit an URB?/如何注册一个URB

Just call/直接调用

 int usb_submit_urb(struct urb *urb, int mem_flags)

The mem_flags parameter, such as SLAB_ATOMIC, controls memory allocation,
such as whether the lower levels may block when memory is tight.

参数mem_flags,如SLAB_ATOMIC,控制内存分配,比如在较低水平时,是否可能会阻止内存资源紧张。

It immediately returns, either with status 0 (request queued) or some
error code, usually caused by the following:

如果它立即返回,无论是与状态0(请求排队)或一些错误代码,通常由以下原因引起的:

- Out of memory (-ENOMEM)/内存不足
- Unplugged device (-ENODEV)/设备没有加电
- Stalled endpoint (-EPIPE)/停滞的端点
- Too many queued ISO transfers (-EAGAIN)/ISO传输队列过长
- Too many requested ISO frames (-EFBIG)/ISO帧请求太多
- Invalid INT interval (-EINVAL)/无效的INT间隔
- More than one packet for INT (-EINVAL)/多个INT数据包

After submission, urb->status is -EINPROGRESS; however, you should never
look at that value except in your completion callback.

提交后,URB->状态是EINPROGRESS,但是,完成回调之前该值无意义。

For isochronous endpoints, your completion handlers should (re)submit
URBs to the same endpoint with the ISO_ASAP flag, using multi-buffering,
to get seamless ISO streaming.

对于同步端点,完成处理程序应该(重新)提交URB的相同的端点与ISO_ASAP标志,使用多缓冲,获得无缝ISO流。


1.6. How to cancel an already running URB?/如何取消一个已经运行的URB?

There are two ways to cancel an URB you've submitted but which hasn't
been returned to your driver yet.  For an asynchronous cancel, call

有两种取消已经运行的URB的方法,但是并没有返回给你的驱动。
对于异步取消,调用

 int usb_unlink_urb(struct urb *urb)

It removes the urb from the internal list and frees all allocated
HW descriptors. The status is changed to reflect unlinking.  Note
that the URB will not normally have finished when usb_unlink_urb()
returns; you must still wait for the completion handler to be called.

它消除了URB从内部列表,并释放所有分配的硬件描述。
状态更改为断开链接。
注意URB的不正常结束时的usb_unlink_urb()返回,您仍然必须等待被调用的程序完成处理。

To cancel an URB synchronously, call/取消同步URB,调用

 void usb_kill_urb(struct urb *urb)

It does everything usb_unlink_urb does, and in addition it waits
until after the URB has been returned and the completion handler
has finished.  It also marks the URB as temporarily unusable, so
that if the completion handler or anyone else tries to resubmit it
they will get a -EPERM error.  Thus you can be sure that when
usb_kill_urb() returns, the URB is totally idle.


它跟usb_unlink_urb的功能差不多,除了等待,直到URB后已返回并完成处理程序已完成。
这也标志着URB暂时无法使用,所以,如果完成处理或其他任何人试图重新提交,他们会得到一个EPERM错误。
因此,可以肯定,当usb_kill_urb()返回时,URB是完全闲置的。

There is a lifetime issue to consider.  An URB may complete at any
time, and the completion handler may free the URB.  If this happens
while usb_unlink_urb or usb_kill_urb is running, it will cause a
memory-access violation.  The driver is responsible for avoiding this,
which often means some sort of lock will be needed to prevent the URB
from being deallocated while it is still in use.

有其是一个很严重的问题。一个URB可能在任何时间完成,并完成处理可能释放URB。
如果发生这种情况,而usb_unlink_urb或usb_kill_urb正在运行,它会导致一个内存访问冲突。
为避免这种驱动程序负责,这往往意味着某种类型的锁,用来防止URB被释放时它仍然在使用。

On the other hand, since usb_unlink_urb may end up calling the
completion handler, the handler must not take any lock that is held
when usb_unlink_urb is invoked.  The general solution to this problem
is to increment the URB's reference count while holding the lock, then
drop the lock and call usb_unlink_urb or usb_kill_urb, and then
decrement the URB's reference count.  You increment the reference
count by calling

另一方面,由于usb_unlink_urb可能最终会调用完成处理程序,处理程序在调用usb_unlink_urb时不能使用任何锁。
解决这个问题使用了URB的引用计数递增,同时持有锁,然后放下锁调用usb_unlink_urb或usb_kill_urb,然后递减的URB的引用计数。
调用递增引用计数:

 struct urb *usb_get_urb(struct urb *urb)

(ignore the return value; it is the same as the argument) and
decrement the reference count by calling usb_free_urb.  Of course,
none of this is necessary if there's no danger of the URB being freed
by the completion handler.

(忽略返回值,它跟参数相同)通过调用usb_free_urb递减引用计数。
当然,如果没有危险的URB被释放完成处理程序,这是没有必要的。


1.7. What about the completion handler?/关于完成处理程序

The handler is of the following type:/处理程序的类

 typedef void (*usb_complete_t)(struct urb *, struct pt_regs *)

I.e., it gets the URB that caused the completion call, plus the
register values at the time of the corresponding interrupt (if any).
In the completion handler, you should have a look at urb->status to
detect any USB errors. Since the context parameter is included in the URB,
you can pass information to the completion handler.

即,它得到产生完成调用操作的URB,在相应的中断时间(如有的话)附加寄存器的值。
在完成处理程序中,你应该查看URB->状态检测是否有任何USB错误。
由于上下文参数包含在URB,你可以传递信息至完成处理程序。

Note that even when an error (or unlink) is reported, data may have been
transferred.  That's because USB transfers are packetized; it might take
sixteen packets to transfer your 1KByte buffer, and ten of them might
have transferred successfully before the completion was called.

请注意,即使在出现错误(或解除链接)报告,数据可能已经被转移。
这是因为USB传输打包的时候,可能需要16个数据包传输1K字节的缓冲区,
其中十个数据包可能在完成调用发生之前就转移完毕了。


NOTE:  ***** WARNING *****/警告
NEVER SLEEP IN A COMPLETION HANDLER.  These are normally called
during hardware interrupt processing.  If you can, defer substantial
work to a tasklet (bottom half) to keep system latencies low.  You'll
probably need to use spinlocks to protect data structures you manipulate
in completion handlers.

不要在完成处理程序使用睡眠模式。
这些通常被称为硬件中断处理过程中。如果可以的话,大量的工作推迟到一个tasklet(的下半部),以保持较低的系统延迟。
您可能会需要使用自旋锁保护你操纵的完成处理程序的数据结构,。


1.8. How to do isochronous (ISO) transfers?/如何做到同步(ISO)传输?

For ISO transfers you have to fill a usb_iso_packet_descriptor structure,
allocated at the end of the URB by usb_alloc_urb(n,mem_flags), for each
packet you want to schedule.   You also have to set urb->interval to say
how often to make transfers; it's often one per frame (which is once
every microframe for highspeed devices).  The actual interval used will
be a power of two that's no bigger than what you specify.

对于ISO传输,你必须填补usb_iso_packet_descriptor的结构,通过usb_alloc_urb(N,mem_flags)分配结束时的URB,要排定每个数据包。
你还必须设置URB->设置间隔多久时间进行转移, 这个时间往往是一个帧(这是一次微帧的高速设备)。
将使用实际的间隔会变成2的幂次方,但是不会大于你所限定的数值。

The usb_submit_urb() call modifies urb->interval to the implemented interval
value that is less than or equal to the requested interval value.  If
ISO_ASAP scheduling is used, urb->start_frame is also updated.

usb_submit_urb()调用修改urb的时间间隔实施的时间间隔值,该值是小于或等于所需的时间间隔值。
如果使用ISO_ASAP调度,URB-> start_frame中也被更新。

For each entry you have to specify the data offset for this frame (base is
transfer_buffer), and the length you want to write/expect to read.
After completion, actual_length contains the actual transferred length and
status contains the resulting status for the ISO transfer for this frame.
It is allowed to specify a varying length from frame to frame (e.g. for
audio synchronisation/adaptive transfer rates). You can also use the length
0 to omit one or more frames (striping).

对于每个条目,你必须指定这个框架(基本是transfer_buffer),你想要写的长度/期望读的数据偏移。
项目建成后,actual_length包含实际传输长度,status包含ISO传输这个框架包含的结果状态。
它被允许指定一个不同的帧与帧之间的长度(例如,音频同步/自适应传输速率)。您还可以使用长度为0的缺省一个或多个帧(分段)。

For scheduling you can choose your own start frame or ISO_ASAP. As explained
earlier, if you always keep at least one URB queued and your completion
keeps (re)submitting a later URB, you'll get smooth ISO streaming (if usb
bandwidth utilization allows).


调度方面,您可以选择您的自己的起始帧或ISO_ASAP。
如前所述,如果你始终保持至少一个URB排队,并完成保持(重新)提交以后URB,你就会得到一个顺畅的ISO流(如果USB带宽利用率允许)。

If you specify your own start frame, make sure it's several frames in advance
of the current frame.  You might want this model if you're synchronizing
ISO data with some other event stream.

如果您指定自己的起始帧,确保它在当前帧的前几帧。如果你与其他一些事件流同步ISO数据,你可能会需要这个模式。


1.9. How to start interrupt (INT) transfers?/如何启动中断的(INT)转移?

Interrupt transfers, like isochronous transfers, are periodic, and happen
in intervals that are powers of two (1, 2, 4 etc) units.  Units are frames
for full and low speed devices, and microframes for high speed ones.
The usb_submit_urb() call modifies urb->interval to the implemented interval
value that is less than or equal to the requested interval value.

像同步传输,中断传输,是周期性的,而发生的时间间隔是2的幂次方(1,2,4等)的单位。
单位是全速和低速设备和高速的微帧的帧。usb_submit_urb()调用修改urb->interval所实现的的时间间隔值,该值小于或等于所需的时间间隔值。

In Linux 2.6, unlike earlier versions, interrupt URBs are not automagically
restarted when they complete.  They end when the completion handler is
called, just like other URBs.  If you want an interrupt URB to be restarted,
your completion handler must resubmit it.

与以前的版本不同的是,在Linux 2.6中,中断URB的都不会自动重新启动,当他们完成。
他们最终完成处理程序被调用时,就像其他URB的。如果你想重新启动中断URB,你的完成处理程序必须重新提交。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
将QT += core QT -= gui CONFIG += c++11 TARGET = UavRectifyLoadLIb CONFIG += console CONFIG -= app_bundle TEMPLATE = app SOURCES += main.cpp # The following define makes your compiler emit warnings if you use # any feature of Qt which as been marked deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS win32{ CONFIG(debug, debug|release){ DESTDIR = $$PWD/../../../../RasterManager/bin/Debug } else{ DESTDIR = $$PWD/../../../../RasterManager/bin/release } INCLUDEPATH += $$PWD/../../../include/gdal1101 DEPENDPATH += $$PWD/../../../include/gdal1101 } else{ CONFIG(debug, debug|release){ DESTDIR = $$PWD/../../../product/release32 } else{ DESTDIR = $$PWD/../../../product/release32 } } # You can also make your code fail to compile if you use deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 unix:!macx: LIBS += -L$$PWD/../../../product/release32/ -lUAVAutoRectifyMt -lUAVAutoRectify -lUAVAutoRectifyFi INCLUDEPATH += $$PWD/../include DEPENDPATH += $$PWD/../include unix:!macx: LIBS += -L$$PWD/../../../lib/opencvf249/ -lopencv_core unix:!macx: LIBS += -L$$PWD/../../../lib/opencvf249/ -lopencv_highgui unix:!macx: LIBS += -L$$PWD/../../../lib/opencvf249/ -lopencv_imgproc INCLUDEPATH += $$PWD/../../../lib/opencvf249 DEPENDPATH += $$PWD/../../../lib/opencvf249 unix:!macx: LIBS += -L$$PWD/../../../../../../../usr/local/lib/ -lopencv_core #unix:!macx: LIBS += -L$$PWD/../../../../../../../usr/local/lib/ -lopencv_highgui unix:!macx: LIBS += -L$$PWD/../../../../../../../usr/local/lib/ -lopencv_imgproc unix:!macx: LIBS += -L$$PWD/../../../../../../../usr/local/lib/ -lopencv_features2d unix:!macx: LIBS += -L$$PWD/../../../../../../../usr/local/lib/ -lopencv_imgcodecs INCLUDEPATH += $$PWD/../../../../../../../usr/local/include DEPENDPATH += $$PWD/../../../../../../../usr/local/include unix:!macx: LIBS += -L$$PWD/../../../product/release32/ -lDEMDriver unix:!macx: LIBS += -L$$PWD/../../../product/release32/ -lProjection unix:!macx: LIBS += -L$$PWD/../../../product/release32/ -lIImage_gC QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO QMAKE_LFLAGS_RELEASE = $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO 转为cmake格式
06-11
根据给出的代码,可以将其转化为以下CMake代码: ``` cmake_minimum_required(VERSION 3.5) project(UavRectifyLoadLIb LANGUAGES CXX) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) find_package(Qt5Core REQUIRED) add_executable(UavRectifyLoadLIb main.cpp ) target_link_libraries(UavRectifyLoadLIb PRIVATE Qt5::Core UAVAutoRectifyMt UAVAutoRectify UAVAutoRectifyFi DEMDriver Projection IImage_gC opencv_core opencv_highgui opencv_imgproc opencv_features2d opencv_imgcodecs ) target_include_directories(UavRectifyLoadLIb PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../../include/gdal1101 ${CMAKE_CURRENT_SOURCE_DIR}/../include ${CMAKE_CURRENT_SOURCE_DIR}/../../../lib/opencvf249 ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../../usr/local/include ) if(UNIX AND NOT APPLE) target_link_directories(UavRectifyLoadLIb PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../../product/release32 ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../../usr/local/lib ) endif() if(WIN32) if(CMAKE_BUILD_TYPE STREQUAL "Debug") set_target_properties(UavRectifyLoadLIb PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_SOURCE_DIR}/../../../../RasterManager/bin/Debug ) else() set_target_properties(UavRectifyLoadLIb PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_SOURCE_DIR}/../../../../RasterManager/bin/release ) endif() else() if(CMAKE_BUILD_TYPE STREQUAL "Debug") set_target_properties(UavRectifyLoadLIb PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_SOURCE_DIR}/../../../product/release32 ) else() set_target_properties(UavRectifyLoadLIb PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_SOURCE_DIR}/../../../product/release32 ) endif() endif() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值