当前位置:网站首页>USB URB
USB URB
2022-08-11 06:34:00 【Emily_rong_2021】
URB定义:
usb 请求块(usb request block, urb)是usb设备驱动中用来描述与usb设备通信所用的基本载体和核心数据结构,非常类似于网络设备驱动中的sk_buff结构体,是usb主机与设备通信的电波
- struct urb {
- /* private: usb core and host controller only fields in the urb */
- struct kref kref; /* URB引用计数 */
- void *hcpriv; /* hostController's private data */
- atomic_t use_count; /* Current commit count */
- atomic_t reject; /* Commit failure count */
- int unlinked; /* 连接失败代码 */
- /* public: documented fields in the urb that can be used by drivers */
- struct list_head urb_list; /* list head for use by the urb's
- * current owner */
- struct list_head anchor_list; /* the URB may be anchored */
- struct usb_anchor *anchor;
- struct usb_device *dev; /* 指向这个 urb 要发送的目标 struct usb_device 的指针,这个变量必须在这个 urb 被发送到 USB 核心之前被 USB 驱动初始化.*/
- struct usb_host_endpoint *ep; /* (internal) pointer to endpoint */
- unsigned int pipe;
- int status;
- unsigned int transfer_flags; /* 传输设置*/
- void *transfer_buffer; /* 指向用于发送数据到设备(OUT urb)或者从设备接收数据(IN urb)的缓冲区指针.为了主机控制器驱动正确访问这个缓冲, 它必须使用 kmalloc 调用来创建, 不是在堆栈或者静态内存中. 对控制端点, 这个缓冲区用于数据中转*/
- dma_addr_t transfer_dma; /* 用于以 DMA way to transmit data to USB 设备的缓冲区*/
- int transfer_buffer_length; /* transfer_buffer 或者 transfer_dma 变量指向的缓冲区大小.如果这是 0, 传送缓冲没有被 USB 核心所使用.对于一个 OUT 端点, 如果这个端点大小比这个变量指定的值小, 对这个 USB 设备的传输将被分成更小的块,以正确地传送数据.这种大的传送以连续的 USB 帧进行.在一个 urb 中提交一个大块数据, 并且使 USB 主机控制器去划分为更小的块, 比以连续地顺序发送小缓冲的速度快得多*/
- int actual_length; /* 当这个 urb 完成后, 该变量被设置为这个 urb (对于 OUT urb)发送或(对于 IN urb)接受数据的真实长度.对于 IN urb, 必须是用此变量而非 transfer_buffer_length , 因为接收的数据可能比整个缓冲小*/
- unsigned char *setup_packet; /* 指向控制urbThe set packet pointer.It is transferred before the data in the buffer is transferred(用于控制 urb)*/
- dma_addr_t setup_dma; /* 控制 urb Used to set up packets DMA 缓冲区地址,It is transferred before the data in the normal buffer(用于控制 urb)*/
- int start_frame; /* Sets or returns the initial number of frames(for isochronousurb) */
- int number_of_packets;
- int interval;
- int error_count; /* 等时urberror count,由USB核心设置 */
- void *context; /* Point to a can beUSBThe data block set by the drive module. 当 urb is returned to the drive,Can be used in end processing routines. */
- usb_complete_t complete; /* End handler function pointer, 当 urb 被完全传送或发生错误,它将被 USB 核心调用. 此函数检查这个 urb, 并决定释放它或重新提交给另一个传输中*/
- struct usb_iso_packet_descriptor iso_frame_desc[0];
- };
URB 处理流程
1, usb设备驱动程序创建并初始化an access specificusb设备特定端点的urb,并提交给usb core
2, usb core提交该urb到usb主控制器驱动程序
3, usb主控制器驱动程序根据urb描述的信息,来访问usb设备
4,当设备访问结束后,usb主控制器驱动程序通知usb core(调用这个函数usb_complete_t complete;)Then its again通知usb设备驱动程序
创建URB
struct urb *usb_alloc_urb(int iso_packets, int mem_flags)
参数:
iso_packets 是这个urb 应当包含的等时数据包的数目,若为0 表示不创建等时数据包.
mem_flags 参数是分配内存的标志,和kmalloc()函数的分配标志参数含义相同.如果分配成功,该函数返回一个urb 结构体指针,否则返回0.
urb 结构体在驱动中不能静态创建,因为这可能破坏USB 核心给urb 使用的引用计数方法.usb_alloc_urb()的“反函数”为:
void usb_free_urb(struct urb *urb);
该函数用于释放由usb_alloc_urb()分配的urb 结构体.
初始化URB
对于中断urb,使用usb_fill_int_urb函数来初始化:
static inline void usb_fill_int_urb (struct urb *urb,要初始化的urb指针.
struct usb_device *dev,所要访问的设备
unsigned int pipe,要访问的端点所对应的管道,使用usb_sndintpipe()或usb_rcvintpipe()创建
void *transfer_buffer,要传输的数据缓冲区
int buffer_length,缓冲区长度
usb_complete_t complete_fn,当完成该urb所请求的操作时,要调用的回调函数
void *context,complet_fn函数所需的上下文,通常取值为dev
int interval)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);
除了没有对应于调度间隔的interval 参数以外,其他参数和usb_fill_int_urb()函数的参数含义相同.
pipe 使用usb_sndbulkpipe()或者usb_rcvbulkpipe()函数来创建.
对于控制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);
除了增加了新的setup_packet 参数以外,其他参数和usb_fill_bulk_urb()函数的参数含义相同.setup_packet 参数指向即将被发送到端点的设置数据包.
上述函数参数中的pipe 使用usb_sndctrlpipe()或usb_rcvictrlpipe()函数来创建.
等时urb没有像中断,控制和批量urb那样的初始化函数,我们Can only be initialized manuallyurb.
提交URB
(3)被USB 设备驱动提交给USB 核心.
在完成第(1)、(2)步的创建和初始化urb 后,urb 便可以提交给USB 核心,通过usb_submit_urb()函数来完成,如下所示:
int usb_submit_urb(struct urb *urb, int mem_flags);
urb 参数是指向urb 的指针,mem_flags 参数与传递给kmalloc()函数参数的意义相同,它用于告知USB 核心如何在此时分配内存缓冲区.
在提交urb 到USB 核心后,直到完成函数被调用之前,不要访问urb 中的任何成员.
usb_submit_urb()在原子上下文和进程上下文中都可以被调用,mem_flags 变量需根据调用环
境进行相应的设置,如下所示.
GFP_ATOMIC:在中断处理函数、底半部、tasklet、定时器处理函数以及urb 完成函数中,在调用者持有自旋锁或者读写锁时以及当驱动将current→state 修改为非 TASK_RUNNING 时,应使用此标志.
GFP_NOIO:在存储设备的块I/O 和错误处理路径中,应使用此标志;
GFP_KERNEL:如果没有任何理由使用GFP_ATOMIC 和GFP_NOIO,就使用GFP_KERNEL.
如果usb_submit_urb()调用成功,即urb 的控制权被移交给USB 核心,该函数返回0;否则,
返回错误号.
(4)提交由USB 核心指定的USB 主机控制器驱动.
(5)被USB 主机控制器处理,进行一次到USB 设备的传送.
第(4)~(5)步由USB 核心和主机控制器完成,不受USB 设备驱动的控制.
(6)当urb 完成,USB 主机控制器驱动通知USB 设备驱动.
在如下3 种情况下,urb 将结束,urb 完成函数将被调用.
1、urb 被成功发送给设备,并且设备返回正确的确认.如果urb→status 为0,意味着对于一个输出urb,数据被成功发送;对于一个输入urb,请求的数据被成功收到.
2、如果发送数据到设备或从设备接收数据时发生了错误,urb→status 将记录错误值.
3、urb 被从USB 核心“去除连接”,这发生在驱动通过usb_unlink_urb()或usb_kill_urb()函数取消urb,或urb 虽已提交,而USB 设备被拔出的情况下.
当urb 生命结束时(处理完成或被解除链接),通过urb 结构体的status 成员可以获知其原因,
如0 表示传输成功,
-ENOENT 表示被usb_kill_urb()杀死,
-ECONNRESET 表示被usb_unlink_urb()杀死,
-EPROTO 表示传输中发生了bitstuff 错误或者硬件未能及时收到响应数据包,
-ENODEV表示USB 设备已被移除,-EXDEV 表示等时传输仅完成了一部分等.

处理URB:
来源:
边栏推荐
猜你喜欢

构建面向特征工程的数据生态 ——拥抱开源生态,OpenMLDB全面打通MLOps生态工具链

STM32学习笔记(白话文理解版)—USART通信接口

Node stepping on the pit 80 port is occupied

OpenMLDB Pulsar Connector: Efficiently connect real-time data to feature engineering

C语言的编译

He Kaiming's new work ViTDET: target detection field, subverting the concept of layered backbone

The whole process of Tinker access --- Compilation

EMQX企业版试用笔记

使用adb命令管理应用

STM32学习笔记(白话文理解版)—外部IO中断实验
随机推荐
Tinker's self-introduction
无效的修订:3.18.1-g262b901-dirty
USB URB
Promise.race学习(判断多个promise对象执行最快的一个)
promise 改变状态的方法和promise 的then方法
Intelligent risk control China design and fall to the ground
Day 71
Open Source Machine Learning Database OpenMLDB Contributor Program Fully Launched
vscode插件开发——代码提示、代码补全、代码分析
OpenMLDB v0.5.0 released | Performance, cost, flexibility reach new heights
Compilation exception resolution
vscode插件开发——懒人专用markdown插件开发
黑马大事件项目
js 学习进阶(Dom部分 pink老师教学笔记)
品优购项目实战笔记
栈stack
STM32-中断优先级管理NVIC
The third phase of the contributor task is wonderful
Ubuntu下安装mysql笔记
活动预告 | 4月23日,多场OpenMLDB精彩分享来袭,不负周末好时光