Linux 内核提交和控制一个 urb
当驱动有数据发送到 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安装 微信开发者工具(deepin linux ubt)
- Linux Command cut 切割
- 怎样使用linux的iptables工具进行网络共享
- 扩展分区和文件系统_Linux数据盘
- linux查看应用对应的端口
- linux下获取本机的获取内网和外网地址
- Linux:监控CPU、磁盘、内存、I/O资源命令(mpstat、vmstat、pidstat、iostat)
- Linux:磁盘管理命令和手动划分磁盘
- Linux自学篇——linux命令英文全称及解释
- 【Linux】linux ln文件夹的链接(转)
- 从Windows复制文件到Linux显示乱码问题
- Linux 内核控制 urb
- PHP源码进行加密(仅linux)
- 记录一次实验室linux系统的GPU服务器死机故障的排查——Linux系统的Power States
- linux系统编程:进程控制(fork)
- Linux的ftp工具的使用
- Linux的lftp命令使用
- Linux 如何将linux主机变为路由器&&iptables的基本用法
- Linux基础:系统启动过程(5个阶段)、linux关机正确流程及常用实例命令、linux目录结构(常见目录解释及目录的分类介绍)
- Linux学习---Linux安装ftp组件
- 【正点原子MP157连载】 第十一章 触摸按键控制LED灯实验【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7
- 更改linux文件的拥有者及用户组(chown和chgrp)
- Linux内核project导论——linux学习和职业曲线(刚開始学习的人,中级,高级都可參考)
- Linux学习笔记(21)linux查看系统状态
- Linux学习笔记(10)linux网络管理与配置之一——主机名与IP地址,DNS解析与本地hosts解析(1-4)
- linux学习之防火墙,查看Linux防火墙状态,开启/关闭Linux防火墙,Linux防火墙开放5236端口