当驱动有数据发送到 USB 设备(如同在驱动的 write 函数中发生的), 一个 urb 必须被 分配来传送数据到设备.

urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb)

{

retval = -ENOMEM; goto error;

}

在 urb 被成功分配后, 一个 DMA 缓冲也应当被创建来发送数据到设备以最有效的方式, 并且被传递到驱动的数据应当被拷贝到缓冲:

buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma); if (!buf)

{

retval = -ENOMEM; goto error;

}

if (copy_from_user(buf, user_buffer, count))

{

retval = -EFAULT; goto error;

}

应当数据被正确地从用户空间拷贝到本地缓冲, urb 在它可被提交给 USB 核心之前必须 被正确初始化:

/* initialize the urb properly */ usb_fill_bulk_urb(urb, dev->udev,

usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),

buf, count,
skel_write_bulk_callback, dev); urb->transfer_flags |=
URB_NO_TRANSFER_DMA_MAP;

现在 urb 被正确分配, 数据被正确拷贝, 并且 urb 被正确初始化, 它可被提交给 USB 核心来传递给设备.

/*
send the data out the bulk port */ retval = usb_submit_urb(urb, GFP_KERNEL); if
(retval)

{

err("%s
- failed submitting write urb, error %d", FUNCTION , retval); goto error;

}


urb 被成功传递到 USB 设备(或者在传输中发生了什么), urb 回调被 USB 核心调用. 在我们的例子中, 我们初始化 urb 来指向函数
skel_write_bulk_callback, 并且那就是 被调用的函数:

static
void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs)

{

/*
sync/async unlink faults aren't errors */ if (urb->status &&

!(urb->status
== -ENOENT ||

urb->status ==
-ECONNRESET || urb->status == -ESHUTDOWN)){

dbg("%s - nonzero write
bulk status received: %d",

FUNCTION  , urb->status);

}

/*
free up our allocated buffer */

usb_buffer_free(urb->dev,
urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma);

}

回调函数做的第一件事是检查 urb 的状态来决定是否这个 urb 成功完成或没有. 错误值,

-ENOENT, -ECONNRESET, 和 -ESHUTDOWN 不是真正的传送错误, 只是报告伴随成功传送的 情况. (见
urb 的可能错误的列表, 在"结构 struct urb"一节中详细列出). 接着这个回 调释放安排给这个 urb 传送的已分配的缓冲.

在 urb 的回调函数在运行时另一个 urb 被提交给设备是普遍的. 当流数据到设备时是有 用的. 记住 urb 回调是在中断上下文运行,
因此它不应当做任何内存分配, 持有任何旗 标, 或者任何可导致进程睡眠的事情. 当从回调中提交 urb, 使用
GFP_ATOMIC 标志来告 知 USB 核心不要睡眠, 如果它需要分配新内存块在提交过程中.

Linux 内核提交和控制一个 urb的更多相关文章

  1. Linux 内核提交 urb

    一旦 urb 被正确地创建,并且被 USB 驱动初始化, 它已准备好被提交给 USB 核心来发送 出到 USB 设备. 这通过调用函数 usb_submit_urb 实现: int usb_submi ...

  2. Linux内核装载和启动一个可执行程序

    “平安的祝福 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” 理解编 ...

  3. 理解Linux内核之中断控制

    乍一看下边的Linux内核代码,貌似L3389有bug,于是我就绕有兴趣地阅读了一下local_irq_save/local_irq_restore的源代码. /* linux-4.14.12/mm/ ...

  4. linux内核学习之二 一个精简内核的分析(基于时间片轮转)

    一   实验过程及效果 1.准备好相关的代码,分别是mymain.c,mypcb.h,myinterrupt.c ,如下图,make make成功: 在qemu创建的虚拟环境下的运行效果:(使用的命令 ...

  5. Linux内核分析:完成一个简单的时间片轮转多道程序内核代码

    PS.贺邦   原创作品转载请注明出处  <Linux内核分析>MOOC课程    http://mooc.study.163.com/course/USTC-1000029000 1.m ...

  6. Linux内核是如何创建一个新进程的?

    进程描述 进程描述符(task_struct) 用来描述进程的数据结构,可以理解为进程的属性.比如进程的状态.进程的标识(PID)等,都被封装在了进程描述符这个数据结构中,该数据结构被定义为task_ ...

  7. 实验七:Linux内核如何装载和启动一个可执行程序

    原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 题目自拟,内容围绕对Linu ...

  8. 作业七:Linux内核如何装载和启动一个可执行程序

    作业七:Linux内核如何装载和启动一个可执行程序 一.编译链接的过程和ELF可执行文件格式 可执行文件的创建——预处理.编译和链接 在object文件中有三种主要的类型. 一个可重定位(reloca ...

  9. 20135323符运锦----第七周:Linux内核如何装载和启动一个可执行程序

    可执行程序的装载 一.预处理.编译.链接和目标文件的格式 1.可执行程序是怎么得来的 ①编译器预处理 gcc -E -o XX.cpp XX.c (-m32)// 注:把include的文件包含进来, ...

随机推荐

  1. python 类的创建

  2. 【JZOJ1637】【ZJOI2009】狼和羊的故事

    题目描述 "狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向......" Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干 ...

  3. 【机器学习】Iris Data Set(鸢尾花数据集)

    [机器学习]Iris Data Set(鸢尾花数据集) 注:数据是机器学习模型的原材料,当下机器学习的热潮离不开大数据的支撑.在机器学习领域,有大量的公开数据集可以使用,从几百个样本到几十万个样本的数 ...

  4. Centos7.3-mysql5.7复制安装过程

    一.环境 192.168.56.102 为主服务器 192.168.56.101 为从服务器 Mysql5.7.20 二进制安装包环境 1. 下载免编译安装包并进行安装 从官网下载 mysql-5.7 ...

  5. 什么是Hessian协议呢?

    什么是Hessian协议呢? 目前,Web服务技术是解决异构平台系统的集成及互操作问题的主流技术. 它所基于的XML已经是Internet上交换数据的实际标准,基于通用的进程间通信协议和网络传输协议屏 ...

  6. Java练习 SDUT-1119_输入数字星期,输出英文(switch语句)

    C语言实验--输入数字星期,输出英文(switch语句) Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 从键盘上输入数 ...

  7. 在 windows 安装 Jekyll

    本文告诉大家一个简单的方法在 Windows 安装 Jekyll 下载 ps1 文件 首先需要安装 Chocolatey ,这个工具可以快速安装 Jekyll 先下载Chocolatey,如果无法从这 ...

  8. Data Flow-File Read-详细过程

  9. @codechef - TREEPATH@ Decompose the Tree

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一棵无根树,每个节点上都写了一个整数. 你的任务就是统计有多 ...

  10. @codechef - MXMN@ Maximum and Minimum

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 定义函数 f(G, x, y) 为 G 中点 x 和点 y 之间 ...