整理uvc驱动相关函数的调用流程

news2024/11/8 6:46:28

目录

  • 1、uvc_video.c
    • 初始化函数的调用关系
  • 2、uvc_queue.c
  • 3、uvc_v4l2.c
  • 4、v4l2-core
  • 5、数据传输
    • 1、分配一个gadget请求
    • 2、请求一个queue

1、uvc_video.c

// uvc_video.c
uvc_video_encode_header
uvc_video_encode_data
uvc_video_encode_bulk
uvc_video_encode_isoc
uvcg_video_ep_queue
uvc_video_complete
uvc_video_free_requests  //释放video请求
uvc_video_alloc_requests  //分配video请求
uvcg_video_pump  //Pump video data into the USB requests
uvcg_video_enable  //Enable or disable the video stream
uvcg_video_init  //Initialize UVC video stream

初始化函数的调用关系

uvc_function_bind //f_uvc.c
	uvcg_video_init(&uvc->video, uvc) //f_uvc.c   Initialise video
		uvcg_queue_init  //uvc_video.c Initialize the video buffers queue
			vb2_queue_init // videobuf2-v4l2.c
				vb2_core_queue_init //videobuf2-core.c

2、uvc_queue.c

uvc_queue_setup
uvc_buffer_prepare
uvc_buffer_queue
uvcg_queue_init
uvcg_free_buffers
uvcg_alloc_buffers
uvcg_query_buffer
uvcg_dequeue_buffer
uvcg_queue_poll
uvcg_queue_mmap
uvcg_queue_get_unmapped_area
uvcg_queue_cancel
uvcg_queue_enable
uvcg_queue_next_buffer
uvcg_queue_head

3、uvc_v4l2.c

uvc_send_response
uvc_v4l2_querycap
uvc_v4l2_get_format
uvc_v4l2_set_format
uvc_v4l2_reqbufs
uvc_v4l2_querybuf
uvc_v4l2_qbuf
uvc_v4l2_dqbuf
uvc_v4l2_streamon
uvc_v4l2_streamoff
uvc_v4l2_subscribe_event
uvc_v4l2_unsubscribe_event
uvc_v4l2_extend_configuration
uvc_v4l2_ioctl_default
uvc_v4l2_open
uvc_v4l2_release
uvc_v4l2_mmap
uvc_v4l2_poll
uvcg_v4l2_get_unmapped_area
#define call_qop(q, op, args...)					\
({									\
	int err;							\
									\
	log_qop(q, op);							\
	err = (q)->ops->op ? (q)->ops->op(args) : 0;			\
	if (!err)							\
		(q)->cnt_ ## op++;					\
	err;								\
})
uvc_function_bind //f_uvc.c
	uvc_register_video //f_uvc.c 
		结构体uvc_v4l2_ioctl_ops  //uvc_v4l2.c
			uvc_v4l2_streamon  //uvc_v4l2.c
				uvcg_video_enable  //uvc_video.c
					uvcg_queue_enable  //uvc_queue.c
						vb2_streamon //videobuf2-v4l2.c
							vb2_core_streamon //videobuf2-core.c
								vb2_start_streaming //videobuf2-core.c
									call_qop(q, start_streaming, q,atomic_read(&q->owned_by_drv_count)) videobuf2-core.c
	

4、v4l2-core

参考文章:https://blog.csdn.net/u013836909/article/details/125360024

在这里插入图片描述

//drivers\media\v4l2-core\v4l2-dev.c
static const struct file_operations v4l2_fops = {
	.owner = THIS_MODULE,
	.read = v4l2_read,
	.write = v4l2_write,
	.open = v4l2_open,
	.get_unmapped_area = v4l2_get_unmapped_area,
	.mmap = v4l2_mmap,
	.unlocked_ioctl = v4l2_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl = v4l2_compat_ioctl32,
#endif
	.release = v4l2_release,
	.poll = v4l2_poll,
	.llseek = no_llseek,
};
video_register_device //include/media/v4l2-dev.h
	__video_register_device //drivers/media/v4l2-core/v4l2-dev.c
		//自动创建设备节点
		device_register //drivers/media/v4l2-core/v4l2-dev.c	
// include\media\v4l2-dev.h
/**
 * struct v4l2_file_operations - fs operations used by a V4L2 device
 *
 * @owner: pointer to struct module
 * @read: operations needed to implement the read() syscall
 * @write: operations needed to implement the write() syscall
 * @poll: operations needed to implement the poll() syscall
 * @unlocked_ioctl: operations needed to implement the ioctl() syscall
 * @compat_ioctl32: operations needed to implement the ioctl() syscall for
 *	the special case where the Kernel uses 64 bits instructions, but
 *	the userspace uses 32 bits.
 * @get_unmapped_area: called by the mmap() syscall, used when %!CONFIG_MMU
 * @mmap: operations needed to implement the mmap() syscall
 * @open: operations needed to implement the open() syscall
 * @release: operations needed to implement the release() syscall
 *
 * .. note::
 *
 *	Those operations are used to implemente the fs struct file_operations
 *	at the V4L2 drivers. The V4L2 core overrides the fs ops with some
 *	extra logic needed by the subsystem.
 */
struct v4l2_file_operations {
	struct module *owner;
	ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
	ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
	__poll_t (*poll) (struct file *, struct poll_table_struct *);
	long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
#ifdef CONFIG_COMPAT
	long (*compat_ioctl32) (struct file *, unsigned int, unsigned long);
#endif
	unsigned long (*get_unmapped_area) (struct file *, unsigned long,
				unsigned long, unsigned long, unsigned long);
	int (*mmap) (struct file *, struct vm_area_struct *);
	int (*open) (struct file *);
	int (*release) (struct file *);
};
static const struct file_operations v4l2_fops = {
	.owner = THIS_MODULE,
	.read = v4l2_read,
	.write = v4l2_write,
	.open = v4l2_open,
	.get_unmapped_area = v4l2_get_unmapped_area,
	.mmap = v4l2_mmap,
	.unlocked_ioctl = v4l2_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl = v4l2_compat_ioctl32,
#endif
	.release = v4l2_release,
	.poll = v4l2_poll,
	.llseek = no_llseek,
};

通过V4L2子系统提供的v4l2_fops集合,可直接调用底层驱动实现的Video主设备struct v4l2_file_operations方法

__video_register_device
	vdev->cdev->ops = &v4l2_fops
		v4l2_open
			vdev->fops->open(filp) //调用uvc_v4l2.c中的uvc_v4l2_open		
		v4l2_ioctl
			vdev->fops->unlocked_ioctl(filp, cmd, arg) //调用uvc_v4l2.c中的video_ioctl2
				video_usercopy(file, cmd, arg, __video_do_ioctl)
					回调__video_do_ioctl		
						ops->vidioc_default //调用uvc_v4l2.c中的vidioc_default
//drivers\media\v4l2-core\v4l2-ioctl.c
long video_ioctl2(struct file *file,
	       unsigned int cmd, unsigned long arg)
{
	return video_usercopy(file, cmd, arg, __video_do_ioctl);
}
EXPORT_SYMBOL(video_ioctl2);

5、数据传输

参考文章:https://blog.csdn.net/qq_32938605/article/details/119787380

1、分配一个gadget请求

// \udc\ambarella_udc.c
static const struct usb_ep_ops ambarella_ep_ops = {
	.enable		= ambarella_udc_ep_enable,
	.disable	= ambarella_udc_ep_disable,

	.alloc_request	= ambarella_udc_alloc_request,
	.free_request	= ambarella_udc_free_request,

	.queue		= ambarella_udc_queue,
	.dequeue	= ambarella_udc_dequeue,

	.set_halt	= ambarella_udc_set_halt,
	/* fifo ops not implemented */
};

usb_ep_alloc_request 分配一个gadget请求

// \udc\core.c
/**
 * usb_ep_alloc_request - allocate a request object to use with this endpoint
 * @ep:the endpoint to be used with with the request
 * @gfp_flags:GFP_* flags to use
 *
 * Request objects must be allocated with this call, since they normally
 * need controller-specific setup and may even need endpoint-specific
 * resources such as allocation of DMA descriptors.
 * Requests may be submitted with usb_ep_queue(), and receive a single
 * completion callback.  Free requests with usb_ep_free_request(), when
 * they are no longer needed.
 *
 * Returns the request, or null if one could not be allocated.
 */
struct usb_request *usb_ep_alloc_request(struct usb_ep *ep,
						       gfp_t gfp_flags)
{
	struct usb_request *req = NULL;

	req = ep->ops->alloc_request(ep, gfp_flags);

	trace_usb_ep_alloc_request(ep, req, req ? 0 : -ENOMEM);

	return req;
}
EXPORT_SYMBOL_GPL(usb_ep_alloc_request);
//f_uvc.c的bind()函数
/* Preallocate control endpoint request. */
	uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
	uvc->control_buf = kmalloc(UVC_MAX_REQUEST_SIZE, GFP_KERNEL);
	if (uvc->control_req == NULL || uvc->control_buf == NULL) {
		ret = -ENOMEM;
		goto error;
	}

	uvc->control_req->buf = uvc->control_buf;
	uvc->control_req->complete = uvc_function_ep0_complete;
	uvc->control_req->context = uvc;
 //ambarella_udc.c
ambarella_udc_probe
	ambarella_init_gadget
		ep->ep.ops = &ambarella_ep_ops

2、请求一个queue

usb_ep_queue 请求一个queue

/**
 * usb_ep_queue - queues (submits) an I/O request to an endpoint.
 * @ep:the endpoint associated with the request
 * @req:the request being submitted
 * @gfp_flags: GFP_* flags to use in case the lower level driver couldn't
 *	pre-allocate all necessary memory with the request.
 *
 * This tells the device controller to perform the specified request through
 * that endpoint (reading or writing a buffer).  When the request completes,
 * including being canceled by usb_ep_dequeue(), the request's completion
 * routine is called to return the request to the driver.  Any endpoint
 * (except control endpoints like ep0) may have more than one transfer
 * request queued; they complete in FIFO order.  Once a gadget driver
 * submits a request, that request may not be examined or modified until it
 * is given back to that driver through the completion callback.
 *
 * Each request is turned into one or more packets.  The controller driver
 * never merges adjacent requests into the same packet.  OUT transfers
 * will sometimes use data that's already buffered in the hardware.
 * Drivers can rely on the fact that the first byte of the request's buffer
 * always corresponds to the first byte of some USB packet, for both
 * IN and OUT transfers.
 *
 * Bulk endpoints can queue any amount of data; the transfer is packetized
 * automatically.  The last packet will be short if the request doesn't fill it
 * out completely.  Zero length packets (ZLPs) should be avoided in portable
 * protocols since not all usb hardware can successfully handle zero length
 * packets.  (ZLPs may be explicitly written, and may be implicitly written if
 * the request 'zero' flag is set.)  Bulk endpoints may also be used
 * for interrupt transfers; but the reverse is not true, and some endpoints
 * won't support every interrupt transfer.  (Such as 768 byte packets.)
 *
 * Interrupt-only endpoints are less functional than bulk endpoints, for
 * example by not supporting queueing or not handling buffers that are
 * larger than the endpoint's maxpacket size.  They may also treat data
 * toggle differently.
 *
 * Control endpoints ... after getting a setup() callback, the driver queues
 * one response (even if it would be zero length).  That enables the
 * status ack, after transferring data as specified in the response.  Setup
 * functions may return negative error codes to generate protocol stalls.
 * (Note that some USB device controllers disallow protocol stall responses
 * in some cases.)  When control responses are deferred (the response is
 * written after the setup callback returns), then usb_ep_set_halt() may be
 * used on ep0 to trigger protocol stalls.  Depending on the controller,
 * it may not be possible to trigger a status-stage protocol stall when the
 * data stage is over, that is, from within the response's completion
 * routine.
 *
 * For periodic endpoints, like interrupt or isochronous ones, the usb host
 * arranges to poll once per interval, and the gadget driver usually will
 * have queued some data to transfer at that time.
 *
 * Note that @req's ->complete() callback must never be called from
 * within usb_ep_queue() as that can create deadlock situations.
 *
 * This routine may be called in interrupt context.
 *
 * Returns zero, or a negative error code.  Endpoints that are not enabled
 * report errors; errors will also be
 * reported when the usb peripheral is disconnected.
 *
 * If and only if @req is successfully queued (the return value is zero),
 * @req->complete() will be called exactly once, when the Gadget core and
 * UDC are finished with the request.  When the completion function is called,
 * control of the request is returned to the device driver which submitted it.
 * The completion handler may then immediately free or reuse @req.
 */
int usb_ep_queue(struct usb_ep *ep,
			       struct usb_request *req, gfp_t gfp_flags)
{
	int ret = 0;

	if (WARN_ON_ONCE(!ep->enabled && ep->address)) {
		ret = -ESHUTDOWN;
		goto out;
	}

	ret = ep->ops->queue(ep, req, gfp_flags);

out:
	trace_usb_ep_queue(ep, req, ret);

	return ret;
}
EXPORT_SYMBOL_GPL(usb_ep_queue);

usb_ep_queue的调用流程

// uvc_v4l2.c
ioctl(dev->fd, UVCIOC_SEND_RESPONSE, &resp)//应用层
uvc_v4l2_ioctl_default
	uvc_send_response(uvc, arg)
		usb_ep_queue(cdev->gadget->ep0, req, GFP_KERNEL)

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

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

相关文章

Python学习基础笔记七十八——Socket编程1

现在的软件开发基本上都需要网络通讯。 不管是传统计算机软件,还是手机软件,还是物联网嵌入系统软件,这些都要和其他网络系统进行通讯。 而当今世界基本上都是使用TCP/IP协议进行通讯的。 TCP/IP协议是一种传输数据的方案。 收发信息的程序…

每个epoch的溯源(MNE)

每个epoch的溯源: from mne.minimum_norm import apply_inverse_epochs stcs apply_inverse_epochs(epochs,inverse_operator,lambda2,method,pick_ori"normal"# naveevoked.nave, )

ArrayDeque 源码解析(JDK1.8)

目录 一. 前言 二. 源码解析 2.1. 概览 2.2. 属性 2.3. 构造方法 2.4. 入队 2.4.1. addFirst(E, e) 2.4.2. add(E e) & addLast(E e) 2.4.3. offer(E e) 2.5. 扩容 2.6. 出队 2.6.1. poll() & pollFirst() 2.6.2. pollLast() 2.7. 删除元素 2.8. 获取元…

springweb+vue前后端分离开发,集成部署

背景: 在自己做测试的时候,由于需要项目和项目的前端页面使用同样接口访问,所以需要将前端代码部署到后端项目下。前端采用vue,后端采用springboot。 首先时建立一个vue项目,这个可以参照网上的案例,创建方…

思维模型 巴纳姆效应

本系列文章 主要是 分享 思维模型,涉及各个领域,重在提升认知。 1 巴纳姆效应的应用 1.1 “占卜者”的故事 1 遇到占卜师的汤姆 汤姆是一位年轻的上班族,他一直对自己的未来感到迷茫和困惑。有一天,他在一家神秘的占卜店里遇到…

Python处理PDF——PyMuPDF的安装与使用详解

​​​​​​​ 1、PyMuPDF简介 1. 介绍 在介绍PyMuPDF之前,先来了解一下MuPDF,从命名形式中就可以看出,PyMuPDF是MuPDF的Python接口形式。 MuPDF MuPDF 是一个轻量级的 PDF、XPS和电子书查看器。MuPDF 由软件库、命令行工具和各种…

28 mysql 数据记录的 存储更新删除

前言 前面 我们探讨了 索引记录的 新增, 更新, 删除 这里 我们来看一下 mysql 的核心数据记录的 新增更新删除 这里 来看一下 增删改 的相关实现 数据记录 和 索引记录 的处理方式是一致的 mysql 数据记录的存储 新增部分参见 自增长主键的实现 以及 记录的插入 mysql…

解决提交到App Store时的ITMS-90478和ITMS-90062错误

目录 引言 正文 1. 什么是ITMS-90478和ITMS-90062错误? 2. 解决方法 2.1 确定当前的版本号和构建号 2.2 递增版本号和构建号 2.3 再次尝试提交应用 总结 参考资料 错误记录 摘要:本文为iOS技术博主分享,将详细介绍解决提交应用到App…

QCustomPlot添加标题头

1 效果图 2 代码 is2Label QString("add title layout element");// add title layout element:ui->customplot->plotLayout()->insertRow(0);ui->customplot->plotLayout()->addElement(0, 0, new QCPTextElement(ui->customplot, xAxis2Lab…

设备巡检管理系统有什么用?企业如何提高生产效率和生产安全?

在当今工业生产领域,设备巡检的重要性不言而喻。然而,传统巡检方式存在的诸多问题,如数据不规范、漏检误检等,严重制约了企业生产效率和产品质量。为解决这一问题,我们推出了一款设备巡检管理系统——“的修”工单管理…

宝塔Nginx配置反向代理后如何配置跨域?

直接将 27行更换成如下配置即可 上图有示例 if ( $static_fileAUWz2fmi 0 ){add_header Cache-Control no-cache;add_header Access-Control-Allow-Origin "$http_origin";add_header Access-Control-Allow-Methods GET, POST, PUT, DELETE, OPTIONS;add_header Acc…

ASEMI肖特基二极管MBR10100CT参数,MBR10100CT封装

编辑-Z MBR10100CT参数描述: 型号:MBR10100CT 最大重复峰值反向电压VRRM:100V 最大RMS电压VRMS:70V 最大直流阻断电压VDC:100V 最大平均正向电流IF:10A 峰值正向浪涌电流IFSM:150A 最大…

使用java代码调用超融合登录接口,跟着敲就完事,官方文档也没有的资源~

一、准备工作 接口地址: 获取公钥:/vapi/json/public_key 登录:/vapi/json/access/ticket 登陆接口和 API 调用说明: 这部分步骤均为官网文档,最后步骤则是本地测试用户列表接口 1、第一步:获取公钥 注意&…

Echarts自定义柱状图

目录 效果图 echarts官网找相似图 将柱状图引入html页面中 自定义柱状图 将不需要的属性删除 ​编辑 修改图形大小 grid 不显示x轴 ​编辑 不显示y轴线和相关刻度 ​编辑 y轴文字的颜色设置为自己想要的颜色 修改第一组柱子相关样式(条状) …

Richard Stallman 正在与癌症作战

导读为了纪念 GNU 项目成立 40 周年,自由软件基金会(FSF)已计划在 10 月 1 日(即GNU 40)为家庭、学生以及美国的其他人群组织一场黑客马拉松活动。 活动之前,GNU 项目于 9 月 27 日迎来了 40 岁生日&#…

GraalVM入门教程

GraalVM入门教程 GraalVM是什么几个名词介绍native-imagegu 基础环境搭建linux下载GraalVM配置环境变量下载安装AOT编译器 native-image安装gcc、glibc-devel 与 zlib-devel下载maven并配置环境变量 windows下载GraalVM配置环境变量下载安装AOT编译器 native-image下载配置wind…

阿里云服务器的购买方式有哪些?哪些实例规格的云服务器价格相对便宜一点?

对于还没购买过阿里云服务器的用户来说,如何购买阿里云服务器以及现在购买哪些实例规格的云服务器价格比较便宜是用户比较关心的,购买阿里云服务器的方式主要有四种,而目前价格比较便宜的云服务器实例规格有轻量应用服务器和和经济型、通用算…

【ROS 2 基础-常用工具】-6 Rviz基础使用

所有内容请查看:博客学习目录_Howe_xixi的博客-CSDN博客

图形学--shading着色

概念:对不同物体应用不同材质 llumination shading着色 Blinn-Phong reflectance model Diffuse Reflection 漫反射 光打到了shading point上然后光线四面八方均匀散射 光源会根据光源传播的距离进行一定的能量衰减 按球的表面积来算,吸收的能量和光…

分类预测 | Matlab实现WOA-GRU鲸鱼算法优化门控循环单元的数据多输入分类预测

分类预测 | Matlab实现WOA-GRU鲸鱼算法优化门控循环单元的数据多输入分类预测 目录 分类预测 | Matlab实现WOA-GRU鲸鱼算法优化门控循环单元的数据多输入分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现WOA-GRU鲸鱼算法优化门控循环单元的数据多输入…