urb传输的代码分析
如需引用,请注明出处blog.csdn.net/zkami 作者ZhengKui
分配一个urb,并初始化之。返回这个urb的指针
usb_alloc_urb(int iso_packets, gfp_t mem_flags) (core/message.c)
->urb = kmalloc(...); 分配一个urb
->usb_init_urb(urb); 初始化这个urb:初始化个字段为0,增加引用计数
根据传输类型,填写urb的一些字段(usb.h)
static inline 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_fn,
void *context)
static inline 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_fn,
void *context,
int interval)
static inline 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_fn,
void *context)
相
同:对于ctl/int/bulk这三种传输类型,在fill
urb时都需要填充dev,pipe,transfer_buffer,transfer_buffer_length,complete,
context 字段。其中pipe代表当前urb传输的管道,transfer_buffer
代表当前urb传输的数据的起始地址,transfer_buffer_length是当前urb传输的数据长度,complete是当前urb处理完后调用的回调函数。
不同:fill control urb时需要fill setup_packet字段,它指向一个setup包的起始地址
fill int urb时要根据传输速度来fill interval字段
提交urb。发出一个异步的传输请求,完成后将调用回调函数。在调用usb_submit_urb函数前必须正确的初始化urb, 最后urb的控制将返回给发出申请的dev driver。
usb_submit_urb(struct urb *urb, gfp_t mem_flags) (core/urb.c)
->ep = (usb_pipein(urb->pipe) ? dev->ep_in : dev->ep_out)[usb_pipeendpoint(urb->pipe)];
根据pipe得到urb要连接到哪个ep的list中
->xfertype = usb_endpoint_type(&ep->desc);
得到端点类型,并根据不同的类型进行设置,如填充urb的transfer_flags字段。
如果是ISO传输,根据iso packet的数量(urb->number_of_packets),初始化每一个packet。 (urb->iso_frame_desc[n])
如果是iso/int传输,根据端点速度类型设置urb->interval
->usb_hcd_submit_urb(urb, mem_flags) (core/hcd.c)
将提交的urb指派给合适的host controller driver,这里的HC遵守OHCI规范
->rh_urb_enqueue(hcd, urb); 如果是Root Hub,调用该函数
->rh_queue_status (hcd, urb); 如果是中断传输
->usb_hcd_link_urb_to_ep(hcd, urb); 把urb挂到ep上
->mod_timer(); 修改rh_timer polling的时间
->rh_call_control (hcd, urb); 如果是控制传输
->usb_hcd_link_urb_to_ep(hcd, urb); 把urb挂到ep上
然后根据不同的standard request(ch9.h) Setup Packet的request域来确定len
->ohci_hub_control(hcd, typeReq, wValue, wIndex,tbuf, wLength)
通过操作根Hub寄存器来完成上层对根Hub发送的命令
->usb_hcd_unlink_urb_from_ep(hcd, urb); 出错的话把urb从ep上脱链
->usb_hcd_giveback_urb(hcd, urb, status); urb处理完后调用回调函数
->ohci_urb_enqueue(hcd, urb, mem_flags) 如果不是Root Hub,调用该函数
-> ed_get (ohci, urb->ep, urb->dev, pipe, urb->interval))) ohci-q.c
如果ep上挂有ed,直接返回。如果没有,则用参数pipe、interval以及ep.desc加工一个ed,将其挂在ep上并返回
-> ed_alloc (ohci, GFP_ATOMIC); (ohci-mem.c)分配一个struct ed
-> td_alloc (ohci, GFP_ATOMIC); (ohci-mem.c)分配一个struct td
-> ed_free(ohci, ed); 释放struct ed
-> usb_calc_bus_time() 计算传输一个拥有最大字节数的数据包所需要的时间(ms)
然后:设定info的各个域,(info其实就是OHCI Spec中定义的Endpoint Descriptor的Dword 0
详见P16 OHCI spec figure4-1)再将info赋给ed->hwInfo
然后: 根据端点的类型确定size(size决定该端点上挂载的td的数目,除实时端点上的td外,
其它端点上的td能够装载4K的数据)
接着: 给urb_priv_t分配空间,并为其上所挂载的td指针数组分配空间
-> td_alloc (ohci, mem_flags); (ohci-mem.c) 分配ed中的每一个td
-> usb_hcd_link_urb_to_ep(hcd, urb); urb挂到ep的urb_list上
-> ed_schedule (ohci, ed);
根据ed的类型将ed插入到HC相应队列中,并读/写HC的寄存器
-> balance (ohci, ed->interval, ed->load);
-> periodic_link(ohci, ed);
-> usb_hcd_unlink_urb_from_ep(hcd, urb);
-> td_submit_urb (ohci, urb); 将urb需要发送的数据安排到相应ed下的td队列中
-> td_fill(ohci, info, data, 4096, urb, cnt);
message.c
usb_interrupt_msg(...) 事实上调用的是usb_bulk_msg()
->usb_bulk_msg(usb_dev, pipe, data, len, actual_length, timeout)
-> usb_alloc_urb(0, GFP_KERNEL) 分配一个urb
-> usb_fill_int_urb(urb, usb_dev, pipe, data, len,
usb_api_blocking_completion, NULL,
ep->desc.bInterval); 如果是int msg
-> usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
usb_api_blocking_completion, NULL); 如果是bulk msg
-> usb_start_wait_urb(urb, timeout, actual_length);
提交urb并等待完成或超时。将urb提交给usb core后就停在wait_for_completion_timeout()等待
当这个urb完成后,会调用usb_api_blocking_completion()进而调用complete来通知不用再等了。
->usb_submit_urb(urb, GFP_NOIO) 提交urb
->wait_for_completion_timeout(&ctx.done, expire)) 等待。其中expire是等待的时间限
&ctx.done是等到了的话,调用的回调函数
->usb_kill_urb(urb) 如果超时就kill这个urb
usb_control_msg(...)
->struct usb_ctrlrequest *dr = kmalloc(...)
首先创建一个usb_ctrlrequest的数据结构(详见usb2.0 spec ch9),并初始化bRequestType,bRequest,wValue
wIndex,wLength字段
->usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
->usb_alloc_urb(0, GFP_NOIO); 分配一个urb
->usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data,
len, usb_api_blocking_completion, NULL);
填充这个ctl urb, usb_api_blocking_completion是回调函数
->usb_start_wait_urb(urb, timeout, &length);
提交urb并等待完成或超时。将urb提交给usb core后就停在wait_for_completion_timeout()等待
当这个urb完成后,会调用usb_api_blocking_completion()进而调用complete来通知不用再等了。
->usb_submit_urb(urb, GFP_NOIO) 提交urb
->wait_for_completion_timeout(&ctx.done, expire)) 等待。其中expire是等待的时间限
&ctx.done是等到了的话,调用的回调函数
->usb_kill_urb(urb) 如果超时就kill这个urb
如需引用,请注明出处blog.csdn.net/zkami 作者ZhengKui
分享到:
相关推荐
usb_urb分析:抓包工具抓到的数据包的详细解析。
URB STATUS VALUE 0 这个 urb 传送是成功的. -ENOENT 这个 urb 被对 usb_kill_urb 的调用停止. -ECONNRESET urb 被对 usb_unlink_urb 的调用去链, 并且 transfer_flags 变量被设置为 URB_ASYNC_UNLINK. -EINPROGRESS...
URB1D\\_YMD-6WR3pdf,URB1D_YMD-6WR3 系列产品输出功率为 6W,超宽电压输入 40-160VDC,效率高达 86%,隔离电压 2250VDC,允许工作温度-40℃to 85℃,具有输入欠压保护,输出短路、过流、过压保护,广泛应用于 72V、...
金升阳URB-MP-12W产品说明pdf,金升阳URB-MP-12W产品说明
URB1D\\_LMD-10WR3pdf,URB1D_LMD-10WR3 系列产品输出功率 10W,超宽电压输入 40-160VDC,效率高达 85%,满足 2250VDC 加强绝缘等级隔离电压,允许工作温度-40℃ to 85℃,具有输入欠压保护,输出短路、过流、过压...
金升阳URB-MP-12W产品说明.pdf 介绍了关于金升阳URB-MP-12W产品说明的详细说明,提供直流电源的技术资料的下载。
千兆网变压器GST5009MLF+电源模块URB2424LD-20WR3 Altium原理图+PCB封装库,已在项目中使用,可直接用于你的设计中。
urb.projects.facturas
为满足铁路机车行业标准对隔离电源的特殊要求,金升阳推出10-20W URB1D-R3系列铁路电源。40-160VDC超宽电压输入,适用于72V、96V、110V的铁路车载电子设备。该R3系列产品在原产品基础上,将隔离电源升级为2250VDC,...
<1> Linux 驱动结构与原理的详细分析,结合Linux内核代码具体分析了设 备驱动原理,Linux驱动模型,以及sysfs 文件系统。 <2> Linux 系统下的USB驱动结构分析,包括Linux USB主机端驱动和设 备端驱动,着重分析USB...
端口映射在usb应用论文,学习开发使用理论资料
对陶粒菌膜反应器(URB)去除污水中重金属Cd2+,Ni2+时的特性进行了分析.URB反应器以经过驯化的金属硫蛋白基因菌为核心微生物.在动态实验中,设置进液pH为9、流速为2 L/h、温度为37℃,Cd2+,Ni2+质量浓度为50 mg/...
turbo全套资源urb全套 吴雨霏理论代码 ccsds 不同译码算法
不使用urb的USB传输 快速参考 第十四章 Linux设备模型 kobject、kset和子系统 低层sysfs操作 热插拔事件的产生 总线、设备和驱动程序 类 各环节的整合 热插拔 处理固件 快速索引 第十五章 内存映射和DMA...
The DARPA Urban Challenge required robotic vehicles to travel more than 90 km th
为了满足铁路机车行业标准对隔离电源的特殊要求,我司现推出6WR3系列高性价比铁路电源。40-160VDC超宽范围电压输入,隔离电压高达2250VDC。 满足铁路机车EN50155标准要求。产品具有输入欠压保护,输出短路、过流、过...
金升阳超薄隔离稳压系列功率段覆盖3W、6W、10W、15W。此系列产品传承R3系列性能优势,拥有2:1、4:1两种宽电压输入范围,可人性化满足不同的客户需求。隔离电压达1500VDC,可选DIP、SMD两种封装,具有齐全的输入欠压...
Linux下的CDC-ACM驱动源码,USB虚拟串口驱动程序,欢迎下载学习!
RNDIS数据在原生Wireshark只能解析到USB URB层,后面是RAW DATA;为了调研方便,于是用lua语言开发了rndis的解析插件。 20210806: 更新了脚本中的一些解析bug。 20220315: 支持linux控制头的rndis处理
用法参考我的Xavier读取RealSense数据的博客 `