Commit b35d6c02 authored by Ricardo Ribalda's avatar Ricardo Ribalda Committed by Mauro Carvalho Chehab
Browse files

media: v4l2-core: Implement v4l2_ctrl_new_std_compound



Currently compound controls do not have a simple way of initializing its
values. This results in ofuscated code with type_ops init.

This patch introduces a new field on the control with the default value
for the compound control that can be set with the brand new
v4l2_ctrl_new_std_compound function

Suggested-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarRicardo Ribalda Delgado <ribalda@kernel.org>
[hverkuil@xs4all.nl: fix checkpatch warning]
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent d8b1ad7c
Loading
Loading
Loading
Loading
+43 −7
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@
#define call_op(master, op) \
	(has_op(master, op) ? master->ops->op(master) : 0)

static const union v4l2_ctrl_ptr ptr_null;

/* Internal temporary helper struct, one for each v4l2_ext_control */
struct v4l2_ctrl_helper {
	/* Pointer to the control reference of the master control */
@@ -1530,6 +1532,9 @@ static void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx,
	struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params;
	void *p = ptr.p + idx * ctrl->elem_size;

	if (ctrl->p_def.p)
		memcpy(p, ctrl->p_def.p, ctrl->elem_size);
	else
		memset(p, 0, ctrl->elem_size);

	/*
@@ -2354,7 +2359,8 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
			s64 min, s64 max, u64 step, s64 def,
			const u32 dims[V4L2_CTRL_MAX_DIMS], u32 elem_size,
			u32 flags, const char * const *qmenu,
			const s64 *qmenu_int, void *priv)
			const s64 *qmenu_int, const union v4l2_ctrl_ptr p_def,
			void *priv)
{
	struct v4l2_ctrl *ctrl;
	unsigned sz_extra;
@@ -2460,6 +2466,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
		 is_array)
		sz_extra += 2 * tot_ctrl_size;

	if (type >= V4L2_CTRL_COMPOUND_TYPES && p_def.p)
		sz_extra += elem_size;

	ctrl = kvzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL);
	if (ctrl == NULL) {
		handler_set_err(hdl, -ENOMEM);
@@ -2503,6 +2512,12 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
		ctrl->p_new.p = &ctrl->val;
		ctrl->p_cur.p = &ctrl->cur.val;
	}

	if (type >= V4L2_CTRL_COMPOUND_TYPES && p_def.p) {
		ctrl->p_def.p = ctrl->p_cur.p + tot_ctrl_size;
		memcpy(ctrl->p_def.p, p_def.p, elem_size);
	}

	for (idx = 0; idx < elems; idx++) {
		ctrl->type_ops->init(ctrl, idx, ctrl->p_cur);
		ctrl->type_ops->init(ctrl, idx, ctrl->p_new);
@@ -2554,7 +2569,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
			type, min, max,
			is_menu ? cfg->menu_skip_mask : step, def,
			cfg->dims, cfg->elem_size,
			flags, qmenu, qmenu_int, priv);
			flags, qmenu, qmenu_int, ptr_null, priv);
	if (ctrl)
		ctrl->is_private = cfg->is_private;
	return ctrl;
@@ -2579,7 +2594,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
	}
	return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
			     min, max, step, def, NULL, 0,
			     flags, NULL, NULL, NULL);
			     flags, NULL, NULL, ptr_null, NULL);
}
EXPORT_SYMBOL(v4l2_ctrl_new_std);

@@ -2612,7 +2627,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
	}
	return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
			     0, max, mask, def, NULL, 0,
			     flags, qmenu, qmenu_int, NULL);
			     flags, qmenu, qmenu_int, ptr_null, NULL);
}
EXPORT_SYMBOL(v4l2_ctrl_new_std_menu);

@@ -2644,11 +2659,32 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
	}
	return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
			     0, max, mask, def, NULL, 0,
			     flags, qmenu, NULL, NULL);
			     flags, qmenu, NULL, ptr_null, NULL);

}
EXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items);

/* Helper function for standard compound controls */
struct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl,
				const struct v4l2_ctrl_ops *ops, u32 id,
				const union v4l2_ctrl_ptr p_def)
{
	const char *name;
	enum v4l2_ctrl_type type;
	u32 flags;
	s64 min, max, step, def;

	v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
	if (type < V4L2_CTRL_COMPOUND_TYPES) {
		handler_set_err(hdl, -EINVAL);
		return NULL;
	}
	return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
			     min, max, step, def, NULL, 0,
			     flags, NULL, NULL, p_def, NULL);
}
EXPORT_SYMBOL(v4l2_ctrl_new_std_compound);

/* Helper function for standard integer menu controls */
struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
			const struct v4l2_ctrl_ops *ops,
@@ -2669,7 +2705,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
	}
	return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
			     0, max, 0, def, NULL, 0,
			     flags, NULL, qmenu_int, NULL);
			     flags, NULL, qmenu_int, ptr_null, NULL);
}
EXPORT_SYMBOL(v4l2_ctrl_new_int_menu);

+22 −0
Original line number Diff line number Diff line
@@ -200,6 +200,9 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
 *		not freed when the control is deleted. Should this be needed
 *		then a new internal bitfield can be added to tell the framework
 *		to free this pointer.
 * @p_def:	The control's default value represented via a union which
 *		provides a standard way of accessing control types
 *		through a pointer (for compound controls only).
 * @p_cur:	The control's current value represented via a union which
 *		provides a standard way of accessing control types
 *		through a pointer.
@@ -254,6 +257,7 @@ struct v4l2_ctrl {
		s32 val;
	} cur;

	union v4l2_ctrl_ptr p_def;
	union v4l2_ctrl_ptr p_new;
	union v4l2_ctrl_ptr p_cur;
};
@@ -646,6 +650,24 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
					       u64 mask, u8 def,
					       const char * const *qmenu);

/**
 * v4l2_ctrl_new_std_compound() - Allocate and initialize a new standard V4L2
 *      compound control.
 *
 * @hdl:       The control handler.
 * @ops:       The control ops.
 * @id:        The control ID.
 * @p_def:     The control's default value.
 *
 * Sames as v4l2_ctrl_new_std(), but with support to compound controls, thanks
 * to the @p_def field.
 *
 */
struct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl,
					     const struct v4l2_ctrl_ops *ops,
					     u32 id,
					     const union v4l2_ctrl_ptr p_def);

/**
 * v4l2_ctrl_new_int_menu() - Create a new standard V4L2 integer menu control.
 *