linux usb声卡 submit urb,linux usb urb详解

linux usb urb详解

谨以此文纪念过往的岁月

一.前言

在前文中看过了hub的驱动以及host的驱动还有usb设备的驱动,在把这些东西关联起来的东东中,一个很重要的urb(usb request blk),在本文中会详细来看urb的实现,以及具体的应用。

二.Urb

urb是什么东西,那先来看urb的定义吧。

1struct urb

2{

3/*私有的:只能由usb核心和主机控制器访问的字段*/

4struct kref kref; /*urb引用计数*/

5spinlock_t lock; /* urb锁*/

6void *hcpriv; /*主机控制器私有数据*/

7int bandwidth; /* int/iso请求的带宽*/

8atomic_t use_count; /*并发传输计数*/

9u8 reject; /*传输将失败*/

10

11/*公共的: 可以被驱动使用的字段*/

12struct list_head urb_list; /*链表头*/

13struct usb_device *dev; /*关联的usb设备*/

14unsigned int pipe; /*管道信息*/

15int status; /* urb的当前状态*/

16unsigned int transfer_flags; /* urb_short_not_ok | ...*/

17void *transfer_buffer; /*发送数据到设备或从设备接收数据的缓冲区*/

18dma_addr_t transfer_dma; /*用来以dma方式向设备传输数据的缓冲区*/

19int transfer_buffer_length;/*transfer_buffer或transfer_dma指向缓冲区的大小*/

20

21int actual_length; /* urb结束后,发送或接收数据的实际长度*/

22unsigned char *setup_packet; /*指向控制urb的设置数据包的指针*/

23dma_addr_t setup_dma; /*控制urb的设置数据包的dma缓冲区*/

24int start_frame; /*等时传输中用于设置或返回初始帧*/

25int number_of_packets; /*等时传输中等时缓冲区数据*/

26int interval; /* urb被轮询到的时间间隔(对中断和等时urb有效)*/

27int error_count;/*等时传输错误数量 */

28void *context; /* completion函数上下文*/

29usb_complete_t complete; /*当urb被完全传输或发生错误时,被调用*/

30struct usb_iso_packet_descriptor iso_frame_desc[0];

31/*单个urb一次可定义多个等时传输时,描述各个等时传输*/

32 };

2.1 urb申请

usb_alloc_urb开辟一个urb空间并对其部分的成员初始化。

iso_packets:等时传输的包数

mem_flags:开辟urb空间的mem旗标,一般为GFP_KERNEL

struct urb *usb_alloc_urb(int, gfp_t )

{

struct

urb *urb;

urb

= kmalloc(sizeof(struct urb) +iso_packets * sizeof(struct

usb_iso_packet_descriptor),

mem_flags);--开辟空间

if

(!urb) {

return

NULL;

}

usb_init_urb(urb);

--初始化部分成员

return

urb;

}

void usb_init_urb(struct urb *urb)

{

if

(urb) {

memset(urb,

0, sizeof(*urb));

kref_init(&urb->kref);--初始化urb计数器

INIT_LIST_HEAD(&urb->anchor_list);--初始化锁定链表

}

}

一般会在初始化之后,对urb的各个成员进行初始化。例如调用usb_fill_int_urb对urb进行成员的填充。在此不做讲述,这个还是比较简单的。

2.2 usb_submit_urb提交urb

int usb_submit_urb(struct urb *urb, gfp_t

mem_flags)

{

intxfertype, max;

struct

usb_device*dev;

struct

usb_host_endpoint*ep;

intis_out;

if

(!urb || urb->hcpriv || !urb->complete)

return

-EINVAL;

dev

= urb->dev;

if

((!dev) || (dev->state < USB_STATE_DEFAULT))

return

-ENODEV;

ep

= (usb_pipein(urb->pipe) ? dev->ep_in : dev->ep_out) [usb_pipeendpoint(urb->pipe)];

--查找设备端点

if

(!ep)

return

-ENOENT;

urb->ep

= ep;

urb->status

= -EINPROGRESS;

urb->actual_length

= 0;

xfertype

= usb_endpoint_type(&ep->desc);

if

(xfertype == USB_ENDPOINT_XFER_CONTROL) {--如果是控制类型

struct

usb_ctrlrequest *setup = (struct usb_ctrlrequest *) urb->setup_packet;

if

(!setup)

return

-ENOEXEC;

is_out

= !(setup->bRequestType & USB_DIR_IN) ||!setup->wLength;

}

else {

is_out

= usb_endpoint_dir_out(&ep->desc);

}

urb->transfer_flags

= (urb->transfer_flags & ~URB_DIR_MASK) | (is_out ? URB_DIR_OUT :

URB_DIR_IN);--缓存的方向留待后用

if

(xfertype != USB_ENDPOINT_XFER_CONTROL &&dev->state <

USB_STATE_CONFIGURED)--在设备没有配置前,传输的类型必为控制类型,唯有设备配置完成后才能传输其他类型的urb

return

-ENODEV;

max

= le16_to_cpu(ep->desc.wMaxPacketSize);

if

(max <= 0) {

return

-EMSGSIZE;

}

if

(xfertype == USB_ENDPOINT_XFER_ISOC) {--等时传输

intn, len;

if

(dev->speed == USB_SPEED_HIGH) {

intmult = 1 + ((max >> 11) & 0x03);

max

&= 0x07ff;

max

*= mult;

}

if

(urb->number_of_packets <= 0)

return

-EINVAL;

for

(n = 0; n < urb->number_of_packets; n++) {

len

= urb->iso_frame_desc[n].length;

if

(len < 0 || len > max)

return

-EMSGSIZE;

urb->iso_frame_desc[n].status

= -EXDEV;

urb->iso_frame_desc[n].actual_length

= 0;

}

}

if

(urb->transfer_buffer_length < 0)

return

-EMSGSIZE;

switch

(xfertype) {--对等时传输和中断传输的等待时间进行检测

case

USB_ENDPOINT_XFER_ISOC:

case

USB_ENDPOINT_XFER_INT:

if

(urb->interval <= 0)

return

-EINVAL;

switch

(dev->speed) {

case

USB_SPEED_HIGH:

/*

NOTE usb handles 2^15 */

if

(urb->interval > (1024 * 8))

urb->interval

= 1024 * 8;

max

= 1024 * 8;

break;

case

USB_SPEED_FULL:

case

USB_SPEED_LOW:

if

(xfertype == USB_ENDPOINT_XFER_INT) {

if

(urb->interval > 255)

return

-EINVAL;

max

= 128;

}

else {

if

(urb->interval > 1024)

urb->interval

= 1024;

max

= 1024;

}

break;

default:

return

-EINVAL;

}

urb->interval

= min(max, 1 << ilog2(urb->interval));

}

return

(urb,

mem_flags);

}

int usb_hcd_submit_urb (struct urb *urb,

gfp_t mem_flags)

{

intstatus;

struct

usb_hcd*hcd =

bus_to_hcd(urb->dev->bus);

usb_get_urb(urb);

atomic_inc(&urb->use_count);--增减urb计数

atomic_inc(&urb->dev->urbnum);--增加dev的urb计数

usbmon_urb_submit(&hcd->self,

urb);--退化为空函数

status

= map_urb_for_dma(hcd, urb, mem_flags);--将urb的缓冲区与dma的区间映射

if

(unlikely(status)) {

usbmon_urb_submit_error(&hcd->self,

urb, status);

goto

error;

}

if

(is_root_hub(urb->dev))

status

= rh_urb_enqueue(hcd, urb);

else

status

= hcd->driver->urb_enqueue(hcd, urb, mem_flags);--将urb入队

if

(unlikely(status)) {

usbmon_urb_submit_error(&hcd->self,

urb, status);

unmap_urb_for_dma(hcd,

urb);

error:

urb->hcpriv

= NULL;

INIT_LIST_HEAD(&urb->urb_list);

atomic_dec(&urb->use_count);

atomic_dec(&urb->dev->urbnum);

if

(atomic_read(&urb->reject))

wake_up(&usb_kill_urb_queue);

usb_put_urb(urb);

}

return

status;

}

在函数usb_hcd_submit_urb调用该hcd的urb_enqueue,在ohci中将会调用ohci_urb_enqueue。其实到此我们需要放下urb的探索,重新来看ohci中关于ed,td的应用。在前文中对ohci的probe进行了讲述,但是对于其余的函数并没有仔细说明,那在后中仔细来看关于ohci的详情。

2.3usb_anchor_urb

当urb在处理的时候锁定。这个函数其实实现很简单就是将urb->anchor_list添加到anchor->urb_list中。关于该函数的具体实现我并不知道具体是做什么用的。

void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor)

{

unsigned long flags;

spin_lock_irqsave(&anchor->lock,

flags);

usb_get_urb(urb);

list_add_tail(&,

&;

urb->anchor = anchor;

if

(unlikely(anchor->poisoned)) {

atomic_inc(&urb->reject);

}

spin_unlock_irqrestore(&anchor->lock,

flags);

}

2.4 usb_unanchor_urb

该函数与上面的函数刚好相反,解锁一个urb同时删除urb

void(struct urb *urb)

{

unsigned long flags;

struct usb_anchor

*anchor;

if (!urb)

return;

anchor =

urb->anchor;

if (!anchor)

return;

spin_lock_irqsave(&anchor->lock,

flags);

if (unlikely(anchor !=

urb->anchor)) {

spin_unlock_irqrestore(&anchor->lock,

flags);

return;

}

urb->anchor = NULL;

list_del(&urb->anchor_list);--将urb从anchor的链表中删除

spin_unlock_irqrestore(&anchor->lock,

flags);

usb_put_urb(urb);--减少urb计数同时删除urb == usb_free_urb

if

(list_empty(&anchor->urb_list))

(&anchor->wait);

}

void (struct urb *urb)

{

if (urb)

kref_put(&urb->kref,

urb_destroy);

}

在某一方面来讲anchor类似一个urb的守护链表,在urb被使用时是不能被删除的。在删除一个urb时需要调用usb_wait_anchor_empty_timeout来等待urb传输完全结束。下面的wait_event_timeout则与上面的wake_up相互对应。

int(struct

usb_anchor *anchor,unsigned int timeout)

{

return (anchor->wait,

list_empty(&anchor->urb_list),

msecs_to_jiffies(timeout));

}

三.总结

urb在某一方面来说是设备驱动与hcd的通信的东东,关于urb的处理其本质还是在ohci中。这个将会在后面的学习中好好学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/343125.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新一代蓝牙对工业物联网(IIOT)的应用

蓝牙是一种收到市场广大认可的一种无线通信技术&#xff0c;并且得益于Mesh组网、低功耗和传输速度快等方面的优势&#xff0c;蓝牙在工业物联网中也起着极为重要的地位。 此外市场上的无线连接技术有着很多的种类&#xff0c;每项技术都这其优缺点和使用环境&#xff0c;包括w…

【渝粤教育】国家开放大学2019年春季 8042-22T养殖业基础 参考试题

科目编号&#xff1a;[8042] 座位号 2018-2019学年度第二学期期末考试 养殖业基础 试题 2019年 5月 一、名词解释&#xff08;本大题共5小题&#xff0c;每小题4分&#xff0c;共计20分&#xff09; 1.必需氨基酸 2&#xff0e;嗳气 3&#xff0e;质量性状 4.人工授精 5.负…

LoRa通信技术和其优势

LoRa 是LPWAN通信技术中的一种&#xff0c;是美国Semtech公司采用和推广的一种基于扩频技术的超远距离无线传输方案。这一方案的出现改变了以往关于传输距离和功耗需要折中的考虑方式&#xff0c;为用户提供了一种简单的能实现远距离通信、电池寿命长、大容量的系统&#xff0c…

【渝粤教育】电大中专常用电器与PLC控制 (2)作业 题库

1.三相笼型异步电动机的电气控制线路中&#xff0c;如果使用热继电器作过载保护&#xff0c;就不必再装设熔断器作短路保护。 A.正确 B.错误 错误 正确答案&#xff1a;左边查询 学生答案&#xff1a;A 2.交流接触器通电后如果铁心吸合受阻&#xff0c;将导致圈烧毁。 A.正确 B…

Linux下读取smBIOS源码,Linux下读取SMBIOS信息

来源&#xff1a;http://www.linuxde.net/2013/02/12499.htmluefi shell下使用smbiosviewlinux下使用dmidecode 或者amidecode(amidecode貌似只支持服务器端AMI平台产品)使用方法 dmidecode -t type_numtype_num表规范如下&#xff1a;SMBIOS specification 2.7.1 中定义了如下…

E95-DTU(4G01-485)数传电台的特点及其应用详解

1、E95-DTU(4G01-485简介 E95-DTU(4G01-485)是采用 4G CAT1 方案的云数传电台&#xff0c;电台支持微信小程序简单配对使用。可以显现一对一、一对多、多对多等复杂应用场景。由于采用了云技术&#xff0c;数传电台相互透传的距离不受限制。 云数传电台作为一种突破性的数传产…

【渝粤题库】陕西师范大学300003 世界史 (上)

《世界史 (上)》作业 一、名词解释 1&#xff0e;氏族 2&#xff0e;《吉尔伽美什史诗》 3&#xff0e;“空中花园” 4&#xff0e;邪马台国  5&#xff0e;托马斯阿奎那 6&#xff0e;图腾崇拜 7&#xff0e;贝希斯敦铭文 8&#xff0e;荷马史诗 9&#xff0e;《罗马民法大全…

SDH光端机概述与技术应用详解

SDH技术自从90年代引入以来&#xff0c;至今已经是一种成熟、标准的技术&#xff0c;在骨干网中被广泛采用&#xff0c;且价格越来越低。SDH光端机可广泛应用于电信数据业务、电力、银行、公安、部队等部门公用电话网接入或专线信息传输。接下来飞畅科技的小编将来为大家详细讲…

物联网技术在智慧校园中的应用

虽然很多人可能会不注意&#xff0c;但是物联网技术已经很普遍的应用在了我们的生活当中&#xff0c;小到日常穿戴、出行&#xff0c;大到农业、工业领域。 物联网应用的范围现在已经遍布在我们生活的各个角落&#xff0c;让物体和物体之间能够时间沟通互联。随着物联网的不断发…

【渝粤教育】21秋期末考试市场调查与预测10243k2

1、运用算术平均法预测时&#xff0c;一般地说&#xff0c;当时间序列资料波动&#xff08;&#xff09;时&#xff0c;其观察期可以&#xff08; &#xff09;&#xff0c;所用数据可以&#xff08; &#xff09;。 &#xff08;3 分&#xff09; A&#xff0e;小 短些 少些 B…

junit测试设置不回滚_正确设置JUnit测试名称

junit测试设置不回滚寻找好名字是手工软件的挑战之一。 您需要随时随地找到它们-类&#xff0c;方法&#xff0c;变量&#xff0c;仅举几例。 但是&#xff0c;什么使名字成为好名字呢&#xff1f; 引用Oncle Bob的话&#xff1a;“三件事&#xff1a;可读性&#xff0c;可读性…

linux中用参数代替键盘输入,Linux终端中使用上一命令减少键盘输入

减少键盘输入&#xff0c;可以大大提高程序员的工作效率&#xff0c;快捷键的使用就是一个很好的例子。程序员经常使用终端。那么在终端上有没有类似的“快捷键”可以提高我们的效率呢&#xff1f;程序员的工作往往是前后相关连的。所以&#xff0c;本文将演示如何使用上一条命…

【渝粤题库】陕西师范大学209006教育政策与法规作业(高起专、高起本)

单选题 1、( )是发扬社会主义民主&#xff0c;加强党的领导在教育领域的直接体现和必然要求。 A依法治教 B教师申诉制度 C教育法 D 教育行政法 2、&#xff08; &#xff09;是在社会主义市场经济条件下&#xff0c;教育进一步改革与发展的客观需要。 A依法治教 B教师申诉制度 …

光端机图像出现噪点或者数据有时不通的情况

光端机是常用的视频输入设备&#xff0c;主要是远距离传输视频、音频、数据,以太网等业务&#xff0c;抗干扰性能强&#xff0c;但是我们在使用光端机的过程中难免也会遇到一些问题&#xff0c;比如说是光端机的图像出现噪点或者数据有时不通的情况&#xff0c;那么&#xff0c…

创建一个Java :: Geci生成器

几天前&#xff0c;我写了有关Java :: Geci架构&#xff0c;代码生成原理以及生成Java源代码的可能不同方式的文章。 在本文中&#xff0c;我将讨论在Java :: Geci中创建生成器有多么简单。 您好&#xff0c;Wold生成器 HelloWorld1 最简单的生成器是Hello, World! 发电机。…

物联网技术的应用和发展

和数字城市、无线城市、智能城市这些理念不同&#xff0c;智慧城市是源于2010年。它是建立在云计算和物联网技术等技术的蓬勃发展的基础上&#xff0c;并与政府行业的需求相结合而产生的。 所以&#xff0c;智慧城市并没有一个特定的标准&#xff0c;智慧城市也难以一蹴而就&am…

c语言 将点同时保证x坐标从小到大,y坐标从小到大地排序,C语言第五六次作业.ppt...

《C语言第五六次作业.ppt》由会员分享&#xff0c;可在线阅读&#xff0c;更多相关《C语言第五六次作业.ppt(40页珍藏版)》请在人人文库网上搜索。1、C语言作业解析,第四弹,。原来真正变态的是这两作业哇 原本是做完第五次作业等大家数分期中考完以后给大家&#xff0c;结果直接…

物联网应用技术的十大基础功能

物联网应用技术是基于互联网的基础&#xff0c;在互联网发展到一定的程度后&#xff0c;物联网应用技术也就应运而生。众所周知&#xff0c;物联网最基本的功能特征就是“无处不在的链接和在线服务”&#xff0c;此外还具备以下十大基本功能&#xff1a; 1、定位追溯&#xff1…

光端机与光电转换器的区别介绍

光端机与光电转换器从本质上讲没啥明百显的界限或区别&#xff0c;都是把光信号和电信号之间做个转换度。实际使用上&#xff1a;光电转换器&#xff08;知俗称‘收发器’&#xff09;&#xff0c;一般用道来传输数据信号&#xff1b;而光端机一般指的都内是视频光端容机&#…

物联网在智慧林业中的应用

以森林防火视频监控、道路视频监控、红外野保相机、生态因子监测、水文水质监测、无线通信专网等物联网相关技术在林业科研、生产、管理及服务上都得到了非常广泛的应用&#xff0c;并且已经成为了支撑智慧林业发展的只要信息手段。 智慧林业具有感知化、物联化、智能化、生态化…