一、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
的内容了