六、v4l2 ctrl 函数初始化---增加自定义接口v4l2_ctrl_new_custom

一、V4L2应用层调用流程
二、V4L2设备注册
三、video设备初始化
四、V4L2 control结构框架图
五、v4l2 ctrl 函数初始化—增加标准接口v4l2_ctrl_new_std
六、v4l2 ctrl 函数初始化—增加自定义接口v4l2_ctrl_new_custom
七、V4L2 ioctl 标准接口 调用流程
八、V4L2 ioctl 控制接口 调用流程

v4l2_ctrl_new_custom

每一个ISP都有自定义的功能,例如 bypass某个算法模块、内部测试图案等等

//v4l2_ctrl_new_custom( hdl_cst_ctrl, xxx_v4l2_ctrl_test_pattern , null);
/*
static const struct v4l2_ctrl_config xxx_v4l2_ctrl_test_pattern = {
    .ops = &isp_v4l2_ctrl_ops_custom,
    .id = ISP_V4L2_CID_TEST_PATTERN,
    .name = "ISP Test Pattern",
    .type = V4L2_CTRL_TYPE_INTEGER,
    .min = 0,
    .max = 1,
    .step = 1,
    .def = 0,
};
*/
struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
							const struct v4l2_config *cfg, void *priv)
{
	bool is_menu;
	struct v4l2_ctrl *ctrl;
	const char *name = cfg->name;
	const char *const *qmenu = cfg->qmenu;
	const s64 *qmenu_int = cfg->qmenu_int;
	enum v4l2_ctrl_type type = cfg->type;
	u32 flags = cfg->flags;
	s64 min = cfg->min;
    s64 max = cfg->max;
    u64 step = cfg->step;
    s64 def = cfg->def;

	if (name == NULL)
		 v4l2_ctrl_fill(cfg->id, &name, &type, &min, &max, &step,&def, &flags);

	is_menu = (type == V4L2_CTRL_TYPE_MENU ||
                   type == V4L2_CTRL_TYPE_INTEGER_MENU);
    if (is_menu)
           WARN_ON(step);
    else    
           WARN_ON(cfg->menu_skip_mask);
    if (type == V4L2_CTRL_TYPE_MENU && !qmenu) {
                qmenu = v4l2_ctrl_get_menu(cfg->id);
    } else if (type == V4L2_CTRL_TYPE_INTEGER_MENU && !qmenu_int) {
          handler_set_err(hdl, -EINVAL);
          return NULL;
    }
    ctrl = v4l2_ctrl_new(hdl,cfg->ops,cfg->type_ops,cfg->id,name...)
    if (ctrl)
    	ctrl->is_private = cfg->is_private;
    	return ctrl;
}

v4l2_ctrl_new就重复前面五、v4l2 ctrl 函数初始化—增加标准接口v4l2_ctrl_new_std
的内容了

### V4L2 自定义 IOCTL 实现 在 Linux 内核中,Video4Linux2 (V4L2) 接口允许应用程序通过文件操作来控制视频设备。为了实现自定义的 `ioctl` 操作,在驱动程序中需注册新的命令并处理这些命令。 #### 定义自定义 IOCTL 命令编号 内核提供宏用于创建唯一的命令号,防止与其他命令冲突: ```c #define CUSTOM_IOCTL_MAGIC 'k' #define CUSTOM_IOCTL_GET_INFO _IOR(CUSTOM_IOCTL_MAGIC, 0, struct custom_info) ``` 这里 `_IOR()` 表示读取数据到用户空间;第一个参数是魔术字符,第二个是序号,第三个是指向结构体类型的指针[^1]。 #### 创建传递的数据结构 当使用 `ioctl` 进行通信时,通常会涉及一些特定于应用层的信息交换。因此可以定义如下结构体: ```c struct custom_info { __u32 param; char data[64]; }; ``` 此结构用来携带额外信息给内核模块或接收来自内核的数据。 #### 注册和处理 IOCTL 请求 为了让 V4L2 设备支持新定义的操作,需要更新其 `.fops.ioctl` 方法指向实际处理器函数,并确保该方法能够识别新增加的命令: ```c static long vidioc_custom_ioctl(struct file *file, unsigned int cmd, void *arg) { switch(cmd){ case CUSTOM_IOCTL_GET_INFO:{ struct custom_info info; /* Fill the structure with relevant information */ strncpy(info.data, "Custom Data", sizeof(info.data)); info.param = 42; // Example value if(copy_to_user(arg, &info, sizeof(info))) return -EFAULT; break; } default: return -ENOTTY; } return 0; } ``` 上述代码片段展示了如何根据传入的命令执行不同的逻辑分支。对于未知命令返回 `-ENOTTY` 错误码表示不支持当前请求。 #### 将 IOCTL 处理器绑定至 V4L2 文件操作表 最后一步是在初始化过程中设置好相应的钩子以便调用自定义的 `ioctl` 函数: ```c static const struct v4l2_file_operations my_v4l2_fops = { .owner = THIS_MODULE, .open = vidioc_open, .release = vidioc_release, .unlocked_ioctl = video_ioctl2, // Standard V4L2 ioctls handler .compat_ioctl32 = vidioc_compat_ioctl32, }; // Register your device and associate it with these operations... video_device->fops = &my_v4l2_fops; ``` 这样就完成了整个流程的设计与实现工作,使得基于 V4L2 的硬件可以通过标准接口访问的同时也提供了扩展功能的支持。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值