linux usb 驱动之创urb的创建和销毁

2024-01-07 17:21:24

struct urb 结构在驱动中必须不被静态创建, 或者在另一个结构中, 因为这可能破坏
USB 核心给 urb 使用的引用计数方法. 它必须使用对 usb_alloc_urb 函数的调用而被创
建. 这个函数有这个原型:
struct urb *usb_alloc_urb(int iso_packets, int mem_flags);
第一个参数, iso_packet, 是这个 urb 应当包含的同步报文的数目. 如果你不想创建一
个同步 urb, 这个变量应当被设置为 0. 第 2 个参数, mem_flags, 是和传递给 kmalloc
函数调用来从内核分配内存的相同的标志类型(见"flags 参数"一节, 第 8 章, 关于这些
标志的细节). 如果这个函数在分配足够内存给这个 urb 成功, 一个指向 urb 的指针被
返回给调用者. 如果返回值是 NULL, 某个错误在 USB 核心中发生了, 并且驱动需要正确
地清理.
在创建了一个 urb 之后, 它必须被正确初始化在它可被 USB 核心使用之前. 如何初始化
不同类型 urb 见下一节
为了告诉 USB 核心驱动用完这个 urb, 驱动必须调用 usb_free_urb 函数. 这个函数只
有一个参数:
void usb_free_urb(struct urb *urb);
参数是一个指向你要释放的 struct urb 的指针. 在这个函数被调用之后, urb 结构消失,
驱动不能再存取它.

中断 urb

函数 usb_fill_int_urb 是一个帮忙函数, 来正确初始化一个 urb 来发送给 USB 设备的
一个中断端点:

void usb_fill_int_urb(struct urb *urb, struct usb_device *dev,
unsigned int pipe, void *transfer_buffer,
int buffer_length, usb_complete_t complete,
void *context, int interval);
这个函数包含许多参数:
struct urb *urb
指向要被初始化的 urb 的指针.
struct usb_device *dev
这个 urb 要发送到的 USB 设备.
unsigned int pipe
这个 urb 要被发送到的 USB 设备的特定端点. 这个值被创建, 使用前面提过的
usb_sndintpipe 或者 usb_rcvintpipe 函数.
void *transfer_buffer
指向缓冲的指针, 从那里外出的数据被获取或者进入数据被接受. 注意这不能是一
个静态的缓冲并且必须使用 kmalloc 调用来创建.
int buffer_length
缓冲的长度, 被 transfer_buffer 指针指向.
usb_complete_t complete
指针, 指向当这个 urb 完成时被调用的完成处理者.
void *context
指向数据块的指针, 它被添加到这个 urb 结构为以后被完成处理者函数获取.
int interval
这个 urb 应当被调度的间隔. 见之前的 struct urb 结构的描述, 来找到这个值
的正确单位.

? 块 urb

块 urb 被初始化非常象中断 urb. 做这个的函数是 usb_fill_bulk_urb, 它看来如此:
void usb_fill_bulk_urb(struct urb *urb, struct usb_device *dev,unsigned int pipe, void *transfer_buffer,
int buffer_length, usb_complete_t complete,
void *context);

这个函数参数和 usb_fill_int_urb 函数的都相同. 但是, 没有 interval 参数因为
bulk urb 没有间隔值. 请注意这个 unsiged int pipe 变量必须被初始化用对
usb_sndbulkpipe 或者 usb_rcvbulkpipe 函数的调用.
usb_fill_int_urb 函数不设置 urb 中的 transfer_flags 变量, 因此任何对这个成员的
修改不得不由这个驱动自己完成.

控制 urb

控制 urb 被初始化几乎和 块 urb 相同的方式, 使用对函数 usb_fill_control_urb 的
调用:
void usb_fill_control_urb(struct urb *urb, struct usb_device *dev,
unsigned int pipe, unsigned char *setup_packet,
void *transfer_buffer, int buffer_length,
usb_complete_t complete, void *context);
函数参数和 usb_fill_bulk_urb 函数都相同, 除了有个新参数, unsigned char
*setup_packet, 它必须指向要发送给端点的 setup 报文数据. 还有, unsigned int
pipe 变量必须被初始化, 使用对 usb_sndctrlpipe 或者 usb_rcvictrlpipe 函数的调用.
usb_fill_control_urb 函数不设置 transfer_flags 变量在 urb 中, 因此任何对这个成
员的修改必须游驱动自己完成. 大部分驱动不使用这个函数, 因为使用在"USB 传送不用
urb"一节中介绍的同步 API 调用更简单.

同步 urb

不幸的是, 同步 urb 没有一个象中断, 控制, 和块 urb 的初始化函数. 因此它们必须在
驱动中"手动"初始化, 在它们可被提交给 USB 核心之前. 下面是一个如何正确初始化这
类 urb 的例子. 它是从 konicawc.c 内核驱动中取得的, 它位于主内核源码树的
drivers/usb/media 目录.
urb->dev = dev;
urb->context = uvd;
urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp-1);
urb->interval = 1;
urb->transfer_flags = URB_ISO_ASAP;
urb->transfer_buffer = cam->sts_buf[i];
urb->complete = konicawc_isoc_irq;
urb->number_of_packets = FRAMES_PER_DESC;
urb->transfer_buffer_length = FRAMES_PER_DESC;
for (j=0; j < FRAMES_PER_DESC; j++) {

urb->iso_frame_desc[j].offset = j;
urb->iso_frame_desc[j].length = 1;
}

文章来源:https://blog.csdn.net/liu1250836704/article/details/135415220
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。