All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFCv2 PATCH 00/21] Add support for complex controls
@ 2014-01-20 12:45 Hans Verkuil
  2014-01-20 12:45 ` [RFCv2 PATCH 01/21] v4l2-ctrls: increase internal min/max/step/def to 64 bit Hans Verkuil
                   ` (21 more replies)
  0 siblings, 22 replies; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:45 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws

This patch series adds support for complex controls (aka 'Properties') to
the control framework. It is the first part of a larger patch series that
adds support for configuration stores, motion detection matrix controls and
support for 'Multiple Selections'.

This patch series is based on this RFC:

http://permalink.gmane.org/gmane.linux.drivers.video-input-infrastructure/71822

A more complete patch series (including configuration store support and the
motion detection work) can be found here:

http://git.linuxtv.org/hverkuil/media_tree.git/shortlog/refs/heads/propapi-doc

This patch series is a revision of this series:

http://www.spinics.net/lists/linux-media/msg71281.html

Changes since RFCv1 are:

- dropped configuration store support for now (there is no driver at the moment
  that needs it).
- dropped the term 'property', instead call it a 'control with a complex type'
  or 'complex control' for short.
- added DocBook documentation.

The API changes required to support complex controls are minimal:

- A new V4L2_CTRL_FLAG_HIDDEN has been added: any control with this flag (and
  complex controls will always have this flag) will never be shown by control
  panel GUIs. The only way to discover them is to pass the new _FLAG_NEXT_HIDDEN
  flag to QUERYCTRL.

- A new VIDIOC_QUERY_EXT_CTRL ioctl has been added: needed to get the number of elements
  stored in the control (rows by columns) and the size in byte of each element.
  As a bonus feature a unit string has also been added as this has been requested
  in the past. In addition min/max/step/def values are now 64-bit.

- A new 'p' field is added to struct v4l2_ext_control to set/get complex values.

- A helper flag V4L2_CTRL_FLAG_IS_PTR has been added to tell apps whether the
  'value' or 'value64' fields of the v4l2_ext_control struct can be used (bit
  is cleared) or if the 'p' pointer can be used (bit it set).

There is one open item: if a complex control is a matrix, then it is possible
to set only the first N elements of that matrix (starting at the first row).
Currently the API will initialize the remaining elements to their default
value. The idea was that if you have an array of, say, selection
rectangles, then if you just set the first one the others will be automatically
zeroed (i.e. set to unused). Without that you would be forced to set the whole
array unless you are certain that they are already zeroed.

It also has the advantage that when you set a control you know that all elements
are set, even if you don't specify them all.

Should I support the ability to set only the first N elements of a matrix at all?

I see three options:

1) allow getting/setting only the first N elements and (when setting) initialize
   the remaining elements to their default value.
2) allow getting/setting only the first N elements and leave the remaining
   elements to their old value.
3) always set the full matrix.

I am actually leaning towards 3 as that is the only unambiguous option. If there
is a good use case in the future support for 1 or 2 can always be added later.

Once everyone agrees with this API extension I will make a third version of this
patch series that adds the Motion Detection support for the solo6x10 and go7007
drivers that can now use the new matrix controls. That way actual drivers will
start using this (and it will allow me to move those drivers out of staging).

Regards,

	Hans


^ permalink raw reply	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 01/21] v4l2-ctrls: increase internal min/max/step/def to 64 bit
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
@ 2014-01-20 12:45 ` Hans Verkuil
  2014-01-22 22:45   ` Sylwester Nawrocki
  2014-01-20 12:45 ` [RFCv2 PATCH 02/21] v4l2-ctrls: add unit string Hans Verkuil
                   ` (20 subsequent siblings)
  21 siblings, 1 reply; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:45 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

While VIDIOC_QUERYCTRL is limited to 32 bit min/max/step/def values
for controls, the upcoming VIDIOC_QUERY_EXT_CTRL isn't. So increase
the internal representation to 64 bits in preparation.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/v4l2-common.c       |  6 ++-
 drivers/media/v4l2-core/v4l2-ctrls.c        | 76 +++++++++++++++++------------
 drivers/staging/media/msi3101/sdr-msi3101.c |  2 +-
 include/media/v4l2-ctrls.h                  | 38 +++++++--------
 4 files changed, 69 insertions(+), 53 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index 433d6d7..ccaa38f 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -111,9 +111,13 @@ int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
 EXPORT_SYMBOL(v4l2_ctrl_check);
 
 /* Fill in a struct v4l2_queryctrl */
-int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
+int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 _min, s32 _max, s32 _step, s32 _def)
 {
 	const char *name;
+	s64 min = _min;
+	s64 max = _max;
+	u64 step = _step;
+	s64 def = _def;
 
 	v4l2_ctrl_fill(qctrl->id, &name, &qctrl->type,
 		       &min, &max, &step, &def, &qctrl->flags);
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 6ff002b..5b60b53 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -864,7 +864,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 EXPORT_SYMBOL(v4l2_ctrl_get_name);
 
 void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
-		    s32 *min, s32 *max, s32 *step, s32 *def, u32 *flags)
+		    s64 *min, s64 *max, u64 *step, s64 *def, u32 *flags)
 {
 	*name = v4l2_ctrl_get_name(id);
 	*flags = 0;
@@ -1322,7 +1322,7 @@ static int cluster_changed(struct v4l2_ctrl *master)
 
 /* Control range checking */
 static int check_range(enum v4l2_ctrl_type type,
-		s32 min, s32 max, u32 step, s32 def)
+		s64 min, s64 max, u64 step, s64 def)
 {
 	switch (type) {
 	case V4L2_CTRL_TYPE_BOOLEAN:
@@ -1330,7 +1330,8 @@ static int check_range(enum v4l2_ctrl_type type,
 			return -ERANGE;
 		/* fall through */
 	case V4L2_CTRL_TYPE_INTEGER:
-		if (step <= 0 || min > max || def < min || def > max)
+	case V4L2_CTRL_TYPE_INTEGER64:
+		if (step == 0 || min > max || def < min || def > max)
 			return -ERANGE;
 		return 0;
 	case V4L2_CTRL_TYPE_BITMASK:
@@ -1355,23 +1356,30 @@ static int check_range(enum v4l2_ctrl_type type,
 	}
 }
 
+/* Round towards the closest legal value */
+#define ROUND_TO_RANGE(val, offset_type, ctrl)			\
+({								\
+	offset_type offset;					\
+	val += (ctrl)->step / 2;				\
+	val = clamp_t(typeof(val), val,				\
+		      (ctrl)->minimum, (ctrl)->maximum);	\
+	offset = (val) - (ctrl)->minimum;			\
+	offset = (ctrl)->step * (offset / (ctrl)->step);	\
+	val = (ctrl)->minimum + offset;				\
+	0;							\
+})
+
 /* Validate a new control */
 static int validate_new(const struct v4l2_ctrl *ctrl,
 			struct v4l2_ext_control *c)
 {
 	size_t len;
-	u32 offset;
-	s32 val;
 
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_INTEGER:
-		/* Round towards the closest legal value */
-		val = c->value + ctrl->step / 2;
-		val = clamp(val, ctrl->minimum, ctrl->maximum);
-		offset = val - ctrl->minimum;
-		offset = ctrl->step * (offset / ctrl->step);
-		c->value = ctrl->minimum + offset;
-		return 0;
+		return ROUND_TO_RANGE(*(s32 *)&c->value, u32, ctrl);
+	case V4L2_CTRL_TYPE_INTEGER64:
+		return ROUND_TO_RANGE(*(s64 *)&c->value64, u64, ctrl);
 
 	case V4L2_CTRL_TYPE_BOOLEAN:
 		c->value = !!c->value;
@@ -1397,9 +1405,6 @@ static int validate_new(const struct v4l2_ctrl *ctrl,
 		c->value = 0;
 		return 0;
 
-	case V4L2_CTRL_TYPE_INTEGER64:
-		return 0;
-
 	case V4L2_CTRL_TYPE_STRING:
 		len = strlen(c->string);
 		if (len < ctrl->minimum)
@@ -1623,7 +1628,7 @@ unlock:
 static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 			const struct v4l2_ctrl_ops *ops,
 			u32 id, const char *name, enum v4l2_ctrl_type type,
-			s32 min, s32 max, u32 step, s32 def,
+			s64 min, s64 max, u64 step, s64 def,
 			u32 flags, const char * const *qmenu,
 			const s64 *qmenu_int, void *priv)
 {
@@ -1708,10 +1713,10 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
 	const s64 *qmenu_int = cfg->qmenu_int;
 	enum v4l2_ctrl_type type = cfg->type;
 	u32 flags = cfg->flags;
-	s32 min = cfg->min;
-	s32 max = cfg->max;
-	u32 step = cfg->step;
-	s32 def = cfg->def;
+	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,
@@ -1744,7 +1749,7 @@ EXPORT_SYMBOL(v4l2_ctrl_new_custom);
 /* Helper function for standard non-menu controls */
 struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
 			const struct v4l2_ctrl_ops *ops,
-			u32 id, s32 min, s32 max, u32 step, s32 def)
+			u32 id, s64 min, s64 max, u64 step, s64 def)
 {
 	const char *name;
 	enum v4l2_ctrl_type type;
@@ -1764,15 +1769,17 @@ EXPORT_SYMBOL(v4l2_ctrl_new_std);
 /* Helper function for standard menu controls */
 struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
 			const struct v4l2_ctrl_ops *ops,
-			u32 id, s32 max, s32 mask, s32 def)
+			u32 id, u8 _max, u64 mask, u8 _def)
 {
 	const char * const *qmenu = NULL;
 	const s64 *qmenu_int = NULL;
 	unsigned int qmenu_int_len = 0;
 	const char *name;
 	enum v4l2_ctrl_type type;
-	s32 min;
-	s32 step;
+	s64 min;
+	s64 max = _max;
+	s64 def = _def;
+	u64 step;
 	u32 flags;
 
 	v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
@@ -1793,14 +1800,16 @@ EXPORT_SYMBOL(v4l2_ctrl_new_std_menu);
 
 /* Helper function for standard menu controls with driver defined menu */
 struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
-			const struct v4l2_ctrl_ops *ops, u32 id, s32 max,
-			s32 mask, s32 def, const char * const *qmenu)
+			const struct v4l2_ctrl_ops *ops, u32 id, u8 _max,
+			u64 mask, u8 _def, const char * const *qmenu)
 {
 	enum v4l2_ctrl_type type;
 	const char *name;
 	u32 flags;
-	s32 step;
-	s32 min;
+	u64 step;
+	s64 min;
+	s64 max = _max;
+	s64 def = _def;
 
 	/* v4l2_ctrl_new_std_menu_items() should only be called for
 	 * standard controls without a standard menu.
@@ -1824,12 +1833,14 @@ EXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items);
 /* 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,
-			u32 id, s32 max, s32 def, const s64 *qmenu_int)
+			u32 id, u8 _max, u8 _def, const s64 *qmenu_int)
 {
 	const char *name;
 	enum v4l2_ctrl_type type;
-	s32 min;
-	s32 step;
+	s64 min;
+	u64 step;
+	s64 max = _max;
+	s64 def = _def;
 	u32 flags;
 
 	v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
@@ -2856,13 +2867,14 @@ void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void
 EXPORT_SYMBOL(v4l2_ctrl_notify);
 
 int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
-			s32 min, s32 max, u32 step, s32 def)
+			s64 min, s64 max, u64 step, s64 def)
 {
 	int ret = check_range(ctrl->type, min, max, step, def);
 	struct v4l2_ext_control c;
 
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_INTEGER:
+	case V4L2_CTRL_TYPE_INTEGER64:
 	case V4L2_CTRL_TYPE_BOOLEAN:
 	case V4L2_CTRL_TYPE_MENU:
 	case V4L2_CTRL_TYPE_INTEGER_MENU:
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index 4c3bf77..1152ca3 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -1713,7 +1713,7 @@ static int msi3101_s_ctrl(struct v4l2_ctrl *ctrl)
 					ctrl_handler);
 	int ret;
 	dev_dbg(&s->udev->dev,
-			"%s: id=%d name=%s val=%d min=%d max=%d step=%d\n",
+			"%s: id=%d name=%s val=%d min=%lld max=%lld step=%llu\n",
 			__func__, ctrl->id, ctrl->name, ctrl->val,
 			ctrl->minimum, ctrl->maximum, ctrl->step);
 
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 16f7f26..0b347e8 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -131,10 +131,10 @@ struct v4l2_ctrl {
 	u32 id;
 	const char *name;
 	enum v4l2_ctrl_type type;
-	s32 minimum, maximum, default_value;
+	s64 minimum, maximum, default_value;
 	union {
-		u32 step;
-		u32 menu_skip_mask;
+		u64 step;
+		u64 menu_skip_mask;
 	};
 	union {
 		const char * const *qmenu;
@@ -231,12 +231,12 @@ struct v4l2_ctrl_config {
 	u32 id;
 	const char *name;
 	enum v4l2_ctrl_type type;
-	s32 min;
-	s32 max;
-	u32 step;
-	s32 def;
+	s64 min;
+	s64 max;
+	u64 step;
+	s64 def;
 	u32 flags;
-	u32 menu_skip_mask;
+	u64 menu_skip_mask;
 	const char * const *qmenu;
 	const s64 *qmenu_int;
 	unsigned int is_private:1;
@@ -257,7 +257,7 @@ struct v4l2_ctrl_config {
   * control framework this function will no longer be exported.
   */
 void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
-		    s32 *min, s32 *max, s32 *step, s32 *def, u32 *flags);
+		    s64 *min, s64 *max, u64 *step, s64 *def, u32 *flags);
 
 
 /** v4l2_ctrl_handler_init_class() - Initialize the control handler.
@@ -362,7 +362,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
   */
 struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
 			const struct v4l2_ctrl_ops *ops,
-			u32 id, s32 min, s32 max, u32 step, s32 def);
+			u32 id, s64 min, s64 max, u64 step, s64 def);
 
 /** v4l2_ctrl_new_std_menu() - Allocate and initialize a new standard V4L2 menu control.
   * @hdl:	The control handler.
@@ -372,9 +372,9 @@ struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
   * @mask: 	The control's skip mask for menu controls. This makes it
   *		easy to skip menu items that are not valid. If bit X is set,
   *		then menu item X is skipped. Of course, this only works for
-  *		menus with <= 32 menu items. There are no menus that come
+  *		menus with <= 64 menu items. There are no menus that come
   *		close to that number, so this is OK. Should we ever need more,
-  *		then this will have to be extended to a u64 or a bit array.
+  *		then this will have to be extended to a bit array.
   * @def: 	The control's default value.
   *
   * Same as v4l2_ctrl_new_std(), but @min is set to 0 and the @mask value
@@ -384,7 +384,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
   */
 struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
 			const struct v4l2_ctrl_ops *ops,
-			u32 id, s32 max, s32 mask, s32 def);
+			u32 id, u8 max, u64 mask, u8 def);
 
 /** v4l2_ctrl_new_std_menu_items() - Create a new standard V4L2 menu control
   * with driver specific menu.
@@ -395,9 +395,9 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
   * @mask:	The control's skip mask for menu controls. This makes it
   *		easy to skip menu items that are not valid. If bit X is set,
   *		then menu item X is skipped. Of course, this only works for
-  *		menus with <= 32 menu items. There are no menus that come
+  *		menus with <= 64 menu items. There are no menus that come
   *		close to that number, so this is OK. Should we ever need more,
-  *		then this will have to be extended to a u64 or a bit array.
+  *		then this will have to be extended to a bit array.
   * @def:	The control's default value.
   * @qmenu:	The new menu.
   *
@@ -406,8 +406,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
   *
   */
 struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
-			const struct v4l2_ctrl_ops *ops, u32 id, s32 max,
-			s32 mask, s32 def, const char * const *qmenu);
+			const struct v4l2_ctrl_ops *ops, u32 id, u8 max,
+			u64 mask, u8 def, const char * const *qmenu);
 
 /** v4l2_ctrl_new_int_menu() - Create a new standard V4L2 integer menu control.
   * @hdl:	The control handler.
@@ -424,7 +424,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
   */
 struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
 			const struct v4l2_ctrl_ops *ops,
-			u32 id, s32 max, s32 def, const s64 *qmenu_int);
+			u32 id, u8 max, u8 def, const s64 *qmenu_int);
 
 /** v4l2_ctrl_add_ctrl() - Add a control from another handler to this handler.
   * @hdl:	The control handler.
@@ -560,7 +560,7 @@ void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed);
   * take the lock itself.
   */
 int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
-			s32 min, s32 max, u32 step, s32 def);
+			s64 min, s64 max, u64 step, s64 def);
 
 /** v4l2_ctrl_lock() - Helper function to lock the handler
   * associated with the control.
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 02/21] v4l2-ctrls: add unit string.
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
  2014-01-20 12:45 ` [RFCv2 PATCH 01/21] v4l2-ctrls: increase internal min/max/step/def to 64 bit Hans Verkuil
@ 2014-01-20 12:45 ` Hans Verkuil
  2014-01-22 22:47   ` Sylwester Nawrocki
  2014-01-24 10:35   ` Sakari Ailus
  2014-01-20 12:45 ` [RFCv2 PATCH 03/21] v4l2-ctrls: use pr_info/cont instead of printk Hans Verkuil
                   ` (19 subsequent siblings)
  21 siblings, 2 replies; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:45 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

The upcoming VIDIOC_QUERY_EXT_CTRL adds support for a unit string. This
allows userspace to show the unit belonging to a particular control.

This patch adds support for the unit string to the control framework.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/v4l2-common.c |  3 ++-
 drivers/media/v4l2-core/v4l2-ctrls.c  | 36 +++++++++++++++++++++--------------
 include/media/v4l2-ctrls.h            | 13 +++++++++----
 3 files changed, 33 insertions(+), 19 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index ccaa38f..ee8ea66 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -114,12 +114,13 @@ EXPORT_SYMBOL(v4l2_ctrl_check);
 int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 _min, s32 _max, s32 _step, s32 _def)
 {
 	const char *name;
+	const char *unit = NULL;
 	s64 min = _min;
 	s64 max = _max;
 	u64 step = _step;
 	s64 def = _def;
 
-	v4l2_ctrl_fill(qctrl->id, &name, &qctrl->type,
+	v4l2_ctrl_fill(qctrl->id, &name, &unit, &qctrl->type,
 		       &min, &max, &step, &def, &qctrl->flags);
 
 	if (name == NULL)
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 5b60b53..0b9246b 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -863,8 +863,9 @@ const char *v4l2_ctrl_get_name(u32 id)
 }
 EXPORT_SYMBOL(v4l2_ctrl_get_name);
 
-void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
-		    s64 *min, s64 *max, u64 *step, s64 *def, u32 *flags)
+void v4l2_ctrl_fill(u32 id, const char **name, const char **unit,
+		    enum v4l2_ctrl_type *type, s64 *min, s64 *max,
+		    u64 *step, s64 *def, u32 *flags)
 {
 	*name = v4l2_ctrl_get_name(id);
 	*flags = 0;
@@ -1627,7 +1628,8 @@ unlock:
 /* Add a new control */
 static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 			const struct v4l2_ctrl_ops *ops,
-			u32 id, const char *name, enum v4l2_ctrl_type type,
+			u32 id, const char *name, const char *unit,
+			enum v4l2_ctrl_type type,
 			s64 min, s64 max, u64 step, s64 def,
 			u32 flags, const char * const *qmenu,
 			const s64 *qmenu_int, void *priv)
@@ -1675,6 +1677,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 	ctrl->ops = ops;
 	ctrl->id = id;
 	ctrl->name = name;
+	ctrl->unit = unit;
 	ctrl->type = type;
 	ctrl->flags = flags;
 	ctrl->minimum = min;
@@ -1709,6 +1712,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
 	bool is_menu;
 	struct v4l2_ctrl *ctrl;
 	const char *name = cfg->name;
+	const char *unit = cfg->unit;
 	const char * const *qmenu = cfg->qmenu;
 	const s64 *qmenu_int = cfg->qmenu_int;
 	enum v4l2_ctrl_type type = cfg->type;
@@ -1719,8 +1723,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
 	s64 def = cfg->def;
 
 	if (name == NULL)
-		v4l2_ctrl_fill(cfg->id, &name, &type, &min, &max, &step,
-								&def, &flags);
+		v4l2_ctrl_fill(cfg->id, &name, &unit, &type,
+			       &min, &max, &step, &def, &flags);
 
 	is_menu = (cfg->type == V4L2_CTRL_TYPE_MENU ||
 		   cfg->type == V4L2_CTRL_TYPE_INTEGER_MENU);
@@ -1736,7 +1740,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
 		return NULL;
 	}
 
-	ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->id, name,
+	ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->id, name, unit,
 			type, min, max,
 			is_menu ? cfg->menu_skip_mask : step,
 			def, flags, qmenu, qmenu_int, priv);
@@ -1752,16 +1756,17 @@ struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
 			u32 id, s64 min, s64 max, u64 step, s64 def)
 {
 	const char *name;
+	const char *unit = NULL;
 	enum v4l2_ctrl_type type;
 	u32 flags;
 
-	v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
+	v4l2_ctrl_fill(id, &name, &unit, &type, &min, &max, &step, &def, &flags);
 	if (type == V4L2_CTRL_TYPE_MENU
 	    || type == V4L2_CTRL_TYPE_INTEGER_MENU) {
 		handler_set_err(hdl, -EINVAL);
 		return NULL;
 	}
-	return v4l2_ctrl_new(hdl, ops, id, name, type,
+	return v4l2_ctrl_new(hdl, ops, id, name, unit, type,
 			     min, max, step, def, flags, NULL, NULL, NULL);
 }
 EXPORT_SYMBOL(v4l2_ctrl_new_std);
@@ -1775,6 +1780,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
 	const s64 *qmenu_int = NULL;
 	unsigned int qmenu_int_len = 0;
 	const char *name;
+	const char *unit = NULL;
 	enum v4l2_ctrl_type type;
 	s64 min;
 	s64 max = _max;
@@ -1782,7 +1788,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
 	u64 step;
 	u32 flags;
 
-	v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
+	v4l2_ctrl_fill(id, &name, &unit, &type, &min, &max, &step, &def, &flags);
 
 	if (type == V4L2_CTRL_TYPE_MENU)
 		qmenu = v4l2_ctrl_get_menu(id);
@@ -1793,7 +1799,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
 		handler_set_err(hdl, -EINVAL);
 		return NULL;
 	}
-	return v4l2_ctrl_new(hdl, ops, id, name, type,
+	return v4l2_ctrl_new(hdl, ops, id, name, unit, type,
 			     0, max, mask, def, flags, qmenu, qmenu_int, NULL);
 }
 EXPORT_SYMBOL(v4l2_ctrl_new_std_menu);
@@ -1805,6 +1811,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
 {
 	enum v4l2_ctrl_type type;
 	const char *name;
+	const char *unit = NULL;
 	u32 flags;
 	u64 step;
 	s64 min;
@@ -1819,12 +1826,12 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
 		return NULL;
 	}
 
-	v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
+	v4l2_ctrl_fill(id, &name, &unit, &type, &min, &max, &step, &def, &flags);
 	if (type != V4L2_CTRL_TYPE_MENU || qmenu == NULL) {
 		handler_set_err(hdl, -EINVAL);
 		return NULL;
 	}
-	return v4l2_ctrl_new(hdl, ops, id, name, type, 0, max, mask, def,
+	return v4l2_ctrl_new(hdl, ops, id, name, unit, type, 0, max, mask, def,
 			     flags, qmenu, NULL, NULL);
 
 }
@@ -1836,6 +1843,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
 			u32 id, u8 _max, u8 _def, const s64 *qmenu_int)
 {
 	const char *name;
+	const char *unit = NULL;
 	enum v4l2_ctrl_type type;
 	s64 min;
 	u64 step;
@@ -1843,12 +1851,12 @@ struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
 	s64 def = _def;
 	u32 flags;
 
-	v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
+	v4l2_ctrl_fill(id, &name, &unit, &type, &min, &max, &step, &def, &flags);
 	if (type != V4L2_CTRL_TYPE_INTEGER_MENU) {
 		handler_set_err(hdl, -EINVAL);
 		return NULL;
 	}
-	return v4l2_ctrl_new(hdl, ops, id, name, type,
+	return v4l2_ctrl_new(hdl, ops, id, name, unit, type,
 			     0, max, 0, def, flags, NULL, qmenu_int, NULL);
 }
 EXPORT_SYMBOL(v4l2_ctrl_new_int_menu);
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 0b347e8..3998049 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -85,6 +85,7 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
   * @ops:	The control ops.
   * @id:	The control ID.
   * @name:	The control name.
+  * @unit:	The control's unit. May be NULL.
   * @type:	The control type.
   * @minimum:	The control's minimum value.
   * @maximum:	The control's maximum value.
@@ -130,6 +131,7 @@ struct v4l2_ctrl {
 	const struct v4l2_ctrl_ops *ops;
 	u32 id;
 	const char *name;
+	const char *unit;
 	enum v4l2_ctrl_type type;
 	s64 minimum, maximum, default_value;
 	union {
@@ -207,6 +209,7 @@ struct v4l2_ctrl_handler {
   * @ops:	The control ops.
   * @id:	The control ID.
   * @name:	The control name.
+  * @unit:	The control's unit.
   * @type:	The control type.
   * @min:	The control's minimum value.
   * @max:	The control's maximum value.
@@ -230,6 +233,7 @@ struct v4l2_ctrl_config {
 	const struct v4l2_ctrl_ops *ops;
 	u32 id;
 	const char *name;
+	const char *unit;
 	enum v4l2_ctrl_type type;
 	s64 min;
 	s64 max;
@@ -249,15 +253,16 @@ struct v4l2_ctrl_config {
   * and @name will be NULL.
   *
   * This function will overwrite the contents of @name, @type and @flags.
-  * The contents of @min, @max, @step and @def may be modified depending on
-  * the type.
+  * The contents of @unit, @min, @max, @step and @def may be modified depending
+  * on the type.
   *
   * Do not use in drivers! It is used internally for backwards compatibility
   * control handling only. Once all drivers are converted to use the new
   * control framework this function will no longer be exported.
   */
-void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
-		    s64 *min, s64 *max, u64 *step, s64 *def, u32 *flags);
+void v4l2_ctrl_fill(u32 id, const char **name, const char **unit,
+		    enum v4l2_ctrl_type *type, s64 *min, s64 *max,
+		    u64 *step, s64 *def, u32 *flags);
 
 
 /** v4l2_ctrl_handler_init_class() - Initialize the control handler.
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 03/21] v4l2-ctrls: use pr_info/cont instead of printk.
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
  2014-01-20 12:45 ` [RFCv2 PATCH 01/21] v4l2-ctrls: increase internal min/max/step/def to 64 bit Hans Verkuil
  2014-01-20 12:45 ` [RFCv2 PATCH 02/21] v4l2-ctrls: add unit string Hans Verkuil
@ 2014-01-20 12:45 ` Hans Verkuil
  2014-01-22 22:48   ` Sylwester Nawrocki
  2014-01-20 12:45 ` [RFCv2 PATCH 04/21] videodev2.h: add initial support for complex controls Hans Verkuil
                   ` (18 subsequent siblings)
  21 siblings, 1 reply; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:45 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Codingstyle fix.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 0b9246b..1060365 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -2036,45 +2036,45 @@ static void log_ctrl(const struct v4l2_ctrl *ctrl,
 	if (ctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
 		return;
 
-	printk(KERN_INFO "%s%s%s: ", prefix, colon, ctrl->name);
+	pr_info("%s%s%s: ", prefix, colon, ctrl->name);
 
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_INTEGER:
-		printk(KERN_CONT "%d", ctrl->cur.val);
+		pr_cont("%d", ctrl->cur.val);
 		break;
 	case V4L2_CTRL_TYPE_BOOLEAN:
-		printk(KERN_CONT "%s", ctrl->cur.val ? "true" : "false");
+		pr_cont("%s", ctrl->cur.val ? "true" : "false");
 		break;
 	case V4L2_CTRL_TYPE_MENU:
-		printk(KERN_CONT "%s", ctrl->qmenu[ctrl->cur.val]);
+		pr_cont("%s", ctrl->qmenu[ctrl->cur.val]);
 		break;
 	case V4L2_CTRL_TYPE_INTEGER_MENU:
-		printk(KERN_CONT "%lld", ctrl->qmenu_int[ctrl->cur.val]);
+		pr_cont("%lld", ctrl->qmenu_int[ctrl->cur.val]);
 		break;
 	case V4L2_CTRL_TYPE_BITMASK:
-		printk(KERN_CONT "0x%08x", ctrl->cur.val);
+		pr_cont("0x%08x", ctrl->cur.val);
 		break;
 	case V4L2_CTRL_TYPE_INTEGER64:
-		printk(KERN_CONT "%lld", ctrl->cur.val64);
+		pr_cont("%lld", ctrl->cur.val64);
 		break;
 	case V4L2_CTRL_TYPE_STRING:
-		printk(KERN_CONT "%s", ctrl->cur.string);
+		pr_cont("%s", ctrl->cur.string);
 		break;
 	default:
-		printk(KERN_CONT "unknown type %d", ctrl->type);
+		pr_cont("unknown type %d", ctrl->type);
 		break;
 	}
 	if (ctrl->flags & (V4L2_CTRL_FLAG_INACTIVE |
 			   V4L2_CTRL_FLAG_GRABBED |
 			   V4L2_CTRL_FLAG_VOLATILE)) {
 		if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
-			printk(KERN_CONT " inactive");
+			pr_cont(" inactive");
 		if (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)
-			printk(KERN_CONT " grabbed");
+			pr_cont(" grabbed");
 		if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE)
-			printk(KERN_CONT " volatile");
+			pr_cont(" volatile");
 	}
-	printk(KERN_CONT "\n");
+	pr_cont("\n");
 }
 
 /* Log all controls owned by the handler */
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 04/21] videodev2.h: add initial support for complex controls.
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
                   ` (2 preceding siblings ...)
  2014-01-20 12:45 ` [RFCv2 PATCH 03/21] v4l2-ctrls: use pr_info/cont instead of printk Hans Verkuil
@ 2014-01-20 12:45 ` Hans Verkuil
  2014-01-22 22:55   ` Sylwester Nawrocki
  2014-01-20 12:45 ` [RFCv2 PATCH 05/21] videodev2.h: add struct v4l2_query_ext_ctrl and VIDIOC_QUERY_EXT_CTRL Hans Verkuil
                   ` (17 subsequent siblings)
  21 siblings, 1 reply; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:45 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Complex controls are controls that can be used for compound and array
types. This allows for more complex datastructures to be used with the
control framework.

Such controls always have the V4L2_CTRL_FLAG_HIDDEN flag set. Note that
'simple' controls can also set that flag.

The existing V4L2_CTRL_FLAG_NEXT_CTRL flag will only enumerate controls
that do not have the HIDDEN flag, so a new V4L2_CTRL_FLAG_NEXT_HIDDEN flag
is added to enumerate hidden controls. Set both flags to enumerate any
controls (hidden or not).

Complex control types will start at V4L2_CTRL_COMPLEX_TYPES. In addition, any
control that uses the new 'p' field or the existing 'string' field will have
flag V4L2_CTRL_FLAG_IS_PTR set.

While not strictly necessary, adding that flag makes life for applications
a lot simpler. If the flag is not set, then the control value is set
through the value or value64 fields of struct v4l2_ext_control, otherwise
a pointer points to the value.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 include/uapi/linux/videodev2.h | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 6ae7bbe..4d7782a 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -1228,6 +1228,7 @@ struct v4l2_ext_control {
 		__s32 value;
 		__s64 value64;
 		char *string;
+		void *p;
 	};
 } __attribute__ ((packed));
 
@@ -1252,7 +1253,10 @@ enum v4l2_ctrl_type {
 	V4L2_CTRL_TYPE_CTRL_CLASS    = 6,
 	V4L2_CTRL_TYPE_STRING        = 7,
 	V4L2_CTRL_TYPE_BITMASK       = 8,
-	V4L2_CTRL_TYPE_INTEGER_MENU = 9,
+	V4L2_CTRL_TYPE_INTEGER_MENU  = 9,
+
+	/* Complex types are >= 0x0100 */
+	V4L2_CTRL_COMPLEX_TYPES	     = 0x0100,
 };
 
 /*  Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
@@ -1288,9 +1292,12 @@ struct v4l2_querymenu {
 #define V4L2_CTRL_FLAG_SLIDER 		0x0020
 #define V4L2_CTRL_FLAG_WRITE_ONLY 	0x0040
 #define V4L2_CTRL_FLAG_VOLATILE		0x0080
+#define V4L2_CTRL_FLAG_HIDDEN		0x0100
+#define V4L2_CTRL_FLAG_IS_PTR		0x0200
 
-/*  Query flag, to be ORed with the control ID */
+/*  Query flags, to be ORed with the control ID */
 #define V4L2_CTRL_FLAG_NEXT_CTRL	0x80000000
+#define V4L2_CTRL_FLAG_NEXT_HIDDEN	0x40000000
 
 /*  User-class control IDs defined by V4L2 */
 #define V4L2_CID_MAX_CTRLS		1024
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 05/21] videodev2.h: add struct v4l2_query_ext_ctrl and VIDIOC_QUERY_EXT_CTRL.
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
                   ` (3 preceding siblings ...)
  2014-01-20 12:45 ` [RFCv2 PATCH 04/21] videodev2.h: add initial support for complex controls Hans Verkuil
@ 2014-01-20 12:45 ` Hans Verkuil
  2014-01-22 23:02   ` Sylwester Nawrocki
  2014-01-24 11:28   ` Sakari Ailus
  2014-01-20 12:45 ` [RFCv2 PATCH 06/21] v4l2-ctrls: add support for complex types Hans Verkuil
                   ` (16 subsequent siblings)
  21 siblings, 2 replies; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:45 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Add a new struct and ioctl to extend the amount of information you can
get for a control.

It gives back a unit string, the range is now a s64 type, and the matrix
and element size can be reported through cols/rows/elem_size.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 include/uapi/linux/videodev2.h | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 4d7782a..9e5b7d4 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -1272,6 +1272,34 @@ struct v4l2_queryctrl {
 	__u32		     reserved[2];
 };
 
+/*  Used in the VIDIOC_QUERY_EXT_CTRL ioctl for querying extended controls */
+struct v4l2_query_ext_ctrl {
+	__u32		     id;
+	__u32		     type;
+	char		     name[32];
+	char		     unit[32];
+	union {
+		__s64 val;
+		__u32 reserved[4];
+	} min;
+	union {
+		__s64 val;
+		__u32 reserved[4];
+	} max;
+	union {
+		__u64 val;
+		__u32 reserved[4];
+	} step;
+	union {
+		__s64 val;
+		__u32 reserved[4];
+	} def;
+	__u32                flags;
+	__u32                cols, rows;
+	__u32                elem_size;
+	__u32		     reserved[17];
+};
+
 /*  Used in the VIDIOC_QUERYMENU ioctl for querying menu items */
 struct v4l2_querymenu {
 	__u32		id;
@@ -1965,6 +1993,8 @@ struct v4l2_create_buffers {
    Never use these in applications! */
 #define VIDIOC_DBG_G_CHIP_INFO  _IOWR('V', 102, struct v4l2_dbg_chip_info)
 
+#define VIDIOC_QUERY_EXT_CTRL	_IOWR('V', 103, struct v4l2_query_ext_ctrl)
+
 /* Reminder: when adding new ioctls please add support for them to
    drivers/media/video/v4l2-compat-ioctl32.c as well! */
 
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 06/21] v4l2-ctrls: add support for complex types.
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
                   ` (4 preceding siblings ...)
  2014-01-20 12:45 ` [RFCv2 PATCH 05/21] videodev2.h: add struct v4l2_query_ext_ctrl and VIDIOC_QUERY_EXT_CTRL Hans Verkuil
@ 2014-01-20 12:45 ` Hans Verkuil
  2014-01-23 11:44   ` Sylwester Nawrocki
  2014-01-24 15:44   ` Sakari Ailus
  2014-01-20 12:46 ` [RFCv2 PATCH 07/21] v4l2: integrate support for VIDIOC_QUERY_EXT_CTRL Hans Verkuil
                   ` (15 subsequent siblings)
  21 siblings, 2 replies; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:45 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

This patch implements initial support for complex types.

For the most part the changes are fairly obvious (basic support for is_ptr
types, the type_is_int function is replaced by a is_int bitfield, and
v4l2_query_ext_ctrl is added), but one change needs more explanation:

The v4l2_ctrl struct adds a 'new' field and a 'stores' array at the end
of the struct. This is in preparation for future patches where each control
can have multiple configuration stores. The idea is that stores[0] is the current
control value, stores[1] etc. are the control values for each configuration store
and the 'new' value can be accessed through 'stores[-1]', i.e. the 'new' field.
However, for now only stores[-1] and stores[0] is used.

These new fields use the v4l2_ctrl_ptr union, which is a pointer to a control
value.

Note that these two new fields are not yet actually used.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 235 ++++++++++++++++++++++++++---------
 include/media/v4l2-ctrls.h           |  38 +++++-
 2 files changed, 209 insertions(+), 64 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 1060365..98e940f 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1086,20 +1086,6 @@ void v4l2_ctrl_fill(u32 id, const char **name, const char **unit,
 }
 EXPORT_SYMBOL(v4l2_ctrl_fill);
 
-/* Helper function to determine whether the control type is compatible with
-   VIDIOC_G/S_CTRL. */
-static bool type_is_int(const struct v4l2_ctrl *ctrl)
-{
-	switch (ctrl->type) {
-	case V4L2_CTRL_TYPE_INTEGER64:
-	case V4L2_CTRL_TYPE_STRING:
-		/* Nope, these need v4l2_ext_control */
-		return false;
-	default:
-		return true;
-	}
-}
-
 static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 changes)
 {
 	memset(ev->reserved, 0, sizeof(ev->reserved));
@@ -1108,7 +1094,7 @@ static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 change
 	ev->u.ctrl.changes = changes;
 	ev->u.ctrl.type = ctrl->type;
 	ev->u.ctrl.flags = ctrl->flags;
-	if (ctrl->type == V4L2_CTRL_TYPE_STRING)
+	if (ctrl->is_ptr)
 		ev->u.ctrl.value64 = 0;
 	else
 		ev->u.ctrl.value64 = ctrl->cur.val64;
@@ -1143,6 +1129,9 @@ static int cur_to_user(struct v4l2_ext_control *c,
 {
 	u32 len;
 
+	if (ctrl->is_ptr && !ctrl->is_string)
+		return copy_to_user(c->p, ctrl->cur.p, ctrl->elem_size);
+
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_STRING:
 		len = strlen(ctrl->cur.string);
@@ -1170,6 +1159,9 @@ static int user_to_new(struct v4l2_ext_control *c,
 	u32 size;
 
 	ctrl->is_new = 1;
+	if (ctrl->is_ptr && !ctrl->is_string)
+		return copy_from_user(ctrl->p, c->p, ctrl->elem_size);
+
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_INTEGER64:
 		ctrl->val64 = c->value64;
@@ -1204,6 +1196,9 @@ static int new_to_user(struct v4l2_ext_control *c,
 {
 	u32 len;
 
+	if (ctrl->is_ptr && !ctrl->is_string)
+		return copy_to_user(c->p, ctrl->p, ctrl->elem_size);
+
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_STRING:
 		len = strlen(ctrl->string);
@@ -1230,6 +1225,7 @@ static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags)
 
 	if (ctrl == NULL)
 		return;
+
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_BUTTON:
 		changed = true;
@@ -1244,8 +1240,13 @@ static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags)
 		ctrl->cur.val64 = ctrl->val64;
 		break;
 	default:
-		changed = ctrl->val != ctrl->cur.val;
-		ctrl->cur.val = ctrl->val;
+		if (ctrl->is_ptr) {
+			changed = memcmp(ctrl->p, ctrl->cur.p, ctrl->elem_size);
+			memcpy(ctrl->cur.p, ctrl->p, ctrl->elem_size);
+		} else {
+			changed = ctrl->val != ctrl->cur.val;
+			ctrl->cur.val = ctrl->val;
+		}
 		break;
 	}
 	if (ch_flags & V4L2_EVENT_CTRL_CH_FLAGS) {
@@ -1285,7 +1286,10 @@ static void cur_to_new(struct v4l2_ctrl *ctrl)
 		ctrl->val64 = ctrl->cur.val64;
 		break;
 	default:
-		ctrl->val = ctrl->cur.val;
+		if (ctrl->is_ptr)
+			memcpy(ctrl->p, ctrl->cur.p, ctrl->elem_size);
+		else
+			ctrl->val = ctrl->cur.val;
 		break;
 	}
 }
@@ -1498,7 +1502,7 @@ static struct v4l2_ctrl_ref *find_private_ref(
 		   VIDIOC_G/S_CTRL. */
 		if (V4L2_CTRL_ID2CLASS(ref->ctrl->id) == V4L2_CTRL_CLASS_USER &&
 		    V4L2_CTRL_DRIVER_PRIV(ref->ctrl->id)) {
-			if (!type_is_int(ref->ctrl))
+			if (!ref->ctrl->is_int)
 				continue;
 			if (id == 0)
 				return ref;
@@ -1568,8 +1572,12 @@ static int handler_new_ref(struct v4l2_ctrl_handler *hdl,
 	u32 class_ctrl = V4L2_CTRL_ID2CLASS(id) | 1;
 	int bucket = id % hdl->nr_of_buckets;	/* which bucket to use */
 
-	/* Automatically add the control class if it is not yet present. */
-	if (id != class_ctrl && find_ref_lock(hdl, class_ctrl) == NULL)
+	/*
+	 * Automatically add the control class if it is not yet present and
+	 * the new control is not hidden.
+	 */
+	if (!(ctrl->flags & V4L2_CTRL_FLAG_HIDDEN) &&
+	    id != class_ctrl && find_ref_lock(hdl, class_ctrl) == NULL)
 		if (!v4l2_ctrl_new_std(hdl, NULL, class_ctrl, 0, 0, 0, 0))
 			return hdl->error;
 
@@ -1631,23 +1639,45 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 			u32 id, const char *name, const char *unit,
 			enum v4l2_ctrl_type type,
 			s64 min, s64 max, u64 step, s64 def,
+			u32 elem_size,
 			u32 flags, const char * const *qmenu,
 			const s64 *qmenu_int, void *priv)
 {
 	struct v4l2_ctrl *ctrl;
-	unsigned sz_extra = 0;
+	unsigned sz_extra;
+	void *data;
 	int err;
 
 	if (hdl->error)
 		return NULL;
 
+	if (type == V4L2_CTRL_TYPE_INTEGER64)
+		elem_size = sizeof(s64);
+	else if (type == V4L2_CTRL_TYPE_STRING)
+		elem_size = max + 1;
+	else if (type < V4L2_CTRL_COMPLEX_TYPES)
+		elem_size = sizeof(s32);
+
 	/* Sanity checks */
 	if (id == 0 || name == NULL || id >= V4L2_CID_PRIVATE_BASE ||
+	    elem_size == 0 ||
 	    (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) ||
 	    (type == V4L2_CTRL_TYPE_INTEGER_MENU && qmenu_int == NULL)) {
 		handler_set_err(hdl, -ERANGE);
 		return NULL;
 	}
+	/* Complex controls are always hidden */
+	if (type >= V4L2_CTRL_COMPLEX_TYPES)
+		flags |= V4L2_CTRL_FLAG_HIDDEN;
+	/*
+	 * No hidden controls are allowed in the USER class
+	 * due to backwards compatibility with old applications.
+	 */
+	if (V4L2_CTRL_ID2CLASS(id) == V4L2_CTRL_CLASS_USER &&
+	    (flags & V4L2_CTRL_FLAG_HIDDEN)) {
+		handler_set_err(hdl, -EINVAL);
+		return NULL;
+	}
 	err = check_range(type, min, max, step, def);
 	if (err) {
 		handler_set_err(hdl, err);
@@ -1658,12 +1688,13 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 		return NULL;
 	}
 
+	sz_extra = sizeof(union v4l2_ctrl_ptr);
 	if (type == V4L2_CTRL_TYPE_BUTTON)
 		flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
 	else if (type == V4L2_CTRL_TYPE_CTRL_CLASS)
 		flags |= V4L2_CTRL_FLAG_READ_ONLY;
-	else if (type == V4L2_CTRL_TYPE_STRING)
-		sz_extra += 2 * (max + 1);
+	else if (type == V4L2_CTRL_TYPE_STRING || type >= V4L2_CTRL_COMPLEX_TYPES)
+		sz_extra += 2 * elem_size;
 
 	ctrl = kzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL);
 	if (ctrl == NULL) {
@@ -1683,18 +1714,31 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 	ctrl->minimum = min;
 	ctrl->maximum = max;
 	ctrl->step = step;
+	ctrl->default_value = def;
+	ctrl->is_string = type == V4L2_CTRL_TYPE_STRING;
+	ctrl->is_ptr = type >= V4L2_CTRL_COMPLEX_TYPES || ctrl->is_string;
+	ctrl->is_int = !ctrl->is_ptr && type != V4L2_CTRL_TYPE_INTEGER64;
+	ctrl->elem_size = elem_size;
 	if (type == V4L2_CTRL_TYPE_MENU)
 		ctrl->qmenu = qmenu;
 	else if (type == V4L2_CTRL_TYPE_INTEGER_MENU)
 		ctrl->qmenu_int = qmenu_int;
 	ctrl->priv = priv;
-	ctrl->cur.val = ctrl->val = ctrl->default_value = def;
+	ctrl->cur.val = ctrl->val = def;
+	data = &ctrl->stores[1];
+
+	if (ctrl->is_string) {
+		ctrl->string = ctrl->new.p_char = data;
+		ctrl->stores[0].p_char = data + elem_size;
 
-	if (ctrl->type == V4L2_CTRL_TYPE_STRING) {
-		ctrl->cur.string = (char *)&ctrl[1] + sz_extra - (max + 1);
-		ctrl->string = (char *)&ctrl[1] + sz_extra - 2 * (max + 1);
 		if (ctrl->minimum)
 			memset(ctrl->cur.string, ' ', ctrl->minimum);
+	} else if (ctrl->is_ptr) {
+		ctrl->p = ctrl->new.p = data;
+		ctrl->stores[0].p = data + elem_size;
+	} else {
+		ctrl->new.p = &ctrl->val;
+		ctrl->stores[0].p = &ctrl->cur.val;
 	}
 	if (handler_new_ref(hdl, ctrl)) {
 		kfree(ctrl);
@@ -1743,7 +1787,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
 	ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->id, name, unit,
 			type, min, max,
 			is_menu ? cfg->menu_skip_mask : step,
-			def, flags, qmenu, qmenu_int, priv);
+			def, cfg->elem_size,
+			flags, qmenu, qmenu_int, priv);
 	if (ctrl)
 		ctrl->is_private = cfg->is_private;
 	return ctrl;
@@ -1761,13 +1806,15 @@ struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
 	u32 flags;
 
 	v4l2_ctrl_fill(id, &name, &unit, &type, &min, &max, &step, &def, &flags);
-	if (type == V4L2_CTRL_TYPE_MENU
-	    || type == V4L2_CTRL_TYPE_INTEGER_MENU) {
+	if (type == V4L2_CTRL_TYPE_MENU ||
+	    type == V4L2_CTRL_TYPE_INTEGER_MENU ||
+	    type >= V4L2_CTRL_COMPLEX_TYPES) {
 		handler_set_err(hdl, -EINVAL);
 		return NULL;
 	}
 	return v4l2_ctrl_new(hdl, ops, id, name, unit, type,
-			     min, max, step, def, flags, NULL, NULL, NULL);
+			     min, max, step, def, 0,
+			     flags, NULL, NULL, NULL);
 }
 EXPORT_SYMBOL(v4l2_ctrl_new_std);
 
@@ -1800,7 +1847,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
 		return NULL;
 	}
 	return v4l2_ctrl_new(hdl, ops, id, name, unit, type,
-			     0, max, mask, def, flags, qmenu, qmenu_int, NULL);
+			     0, max, mask, def, 0,
+			     flags, qmenu, qmenu_int, NULL);
 }
 EXPORT_SYMBOL(v4l2_ctrl_new_std_menu);
 
@@ -1832,7 +1880,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
 		return NULL;
 	}
 	return v4l2_ctrl_new(hdl, ops, id, name, unit, type, 0, max, mask, def,
-			     flags, qmenu, NULL, NULL);
+			     0, flags, qmenu, NULL, NULL);
 
 }
 EXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items);
@@ -1857,7 +1905,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
 		return NULL;
 	}
 	return v4l2_ctrl_new(hdl, ops, id, name, unit, type,
-			     0, max, 0, def, flags, NULL, qmenu_int, NULL);
+			     0, max, 0, def, 0,
+			     flags, NULL, qmenu_int, NULL);
 }
 EXPORT_SYMBOL(v4l2_ctrl_new_int_menu);
 
@@ -2145,9 +2194,10 @@ int v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl)
 }
 EXPORT_SYMBOL(v4l2_ctrl_handler_setup);
 
-/* Implement VIDIOC_QUERYCTRL */
-int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
+/* Implement VIDIOC_QUERY_EXT_CTRL */
+int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctrl *qc)
 {
+	const unsigned next_flags = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_HIDDEN;
 	u32 id = qc->id & V4L2_CTRL_ID_MASK;
 	struct v4l2_ctrl_ref *ref;
 	struct v4l2_ctrl *ctrl;
@@ -2160,7 +2210,15 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
 	/* Try to find it */
 	ref = find_ref(hdl, id);
 
-	if ((qc->id & V4L2_CTRL_FLAG_NEXT_CTRL) && !list_empty(&hdl->ctrl_refs)) {
+	if ((qc->id & next_flags) && !list_empty(&hdl->ctrl_refs)) {
+		unsigned mask = V4L2_CTRL_FLAG_HIDDEN;
+		unsigned match = 0;
+
+		if ((qc->id & next_flags) == V4L2_CTRL_FLAG_NEXT_HIDDEN)
+			match = mask;
+		if ((qc->id & next_flags) == next_flags)
+			mask = 0;
+
 		/* Find the next control with ID > qc->id */
 
 		/* Did we reach the end of the control list? */
@@ -2168,19 +2226,28 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
 			ref = NULL; /* Yes, so there is no next control */
 		} else if (ref) {
 			/* We found a control with the given ID, so just get
-			   the next one in the list. */
-			ref = list_entry(ref->node.next, typeof(*ref), node);
+			   the next valid one in the list. */
+			list_for_each_entry_continue(ref, &hdl->ctrl_refs, node)
+				if (id < ref->ctrl->id &&
+				    (ref->ctrl->flags & mask) == match)
+					break;
+			if (&ref->node == &hdl->ctrl_refs)
+				ref = NULL;
 		} else {
 			/* No control with the given ID exists, so start
 			   searching for the next largest ID. We know there
 			   is one, otherwise the first 'if' above would have
 			   been true. */
 			list_for_each_entry(ref, &hdl->ctrl_refs, node)
-				if (id < ref->ctrl->id)
+				if (id < ref->ctrl->id &&
+				    (ref->ctrl->flags & mask) == match)
 					break;
+			if (&ref->node == &hdl->ctrl_refs)
+				ref = NULL;
 		}
 	}
 	mutex_unlock(hdl->lock);
+
 	if (!ref)
 		return -EINVAL;
 
@@ -2191,23 +2258,63 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
 	else
 		qc->id = ctrl->id;
 	strlcpy(qc->name, ctrl->name, sizeof(qc->name));
-	qc->minimum = ctrl->minimum;
-	qc->maximum = ctrl->maximum;
-	qc->default_value = ctrl->default_value;
+	qc->flags = ctrl->flags;
+	qc->type = ctrl->type;
+	if (ctrl->is_ptr)
+		qc->flags |= V4L2_CTRL_FLAG_IS_PTR;
+	if (ctrl->unit)
+		strlcpy(qc->unit, ctrl->unit, sizeof(qc->unit));
+	qc->elem_size = ctrl->elem_size;
+	qc->min.val = ctrl->minimum;
+	qc->max.val = ctrl->maximum;
+	qc->def.val = ctrl->default_value;
+	qc->cols = qc->rows = 1;
 	if (ctrl->type == V4L2_CTRL_TYPE_MENU
 	    || ctrl->type == V4L2_CTRL_TYPE_INTEGER_MENU)
-		qc->step = 1;
+		qc->step.val = 1;
 	else
-		qc->step = ctrl->step;
-	qc->flags = ctrl->flags;
-	qc->type = ctrl->type;
+		qc->step.val = ctrl->step;
+	return 0;
+}
+EXPORT_SYMBOL(v4l2_query_ext_ctrl);
+
+/* Implement VIDIOC_QUERYCTRL */
+int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
+{
+	struct v4l2_query_ext_ctrl qec = { 0, qc->id };
+	int rc;
+
+	/* VIDIOC_QUERYCTRL cannot be used to enumerate hidden controls */
+	if (qc->flags & V4L2_CTRL_FLAG_NEXT_HIDDEN)
+		return -EINVAL;
+	rc = v4l2_query_ext_ctrl(hdl, &qec);
+	if (rc)
+		return rc;
+
+	qc->id = qec.id;
+	qc->type = qec.type;
+	qc->flags = qec.flags;
+	strlcpy(qc->name, qec.name, sizeof(qc->name));
+	switch (qc->type) {
+	case V4L2_CTRL_TYPE_INTEGER:
+	case V4L2_CTRL_TYPE_BOOLEAN:
+	case V4L2_CTRL_TYPE_MENU:
+	case V4L2_CTRL_TYPE_INTEGER_MENU:
+	case V4L2_CTRL_TYPE_STRING:
+	case V4L2_CTRL_TYPE_BITMASK:
+		qc->minimum = qec.min.val;
+		qc->maximum = qec.max.val;
+		qc->step = qec.step.val;
+		qc->default_value = qec.def.val;
+		break;
+	}
 	return 0;
 }
 EXPORT_SYMBOL(v4l2_queryctrl);
 
 int v4l2_subdev_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
 {
-	if (qc->id & V4L2_CTRL_FLAG_NEXT_CTRL)
+	if (qc->id & (V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_HIDDEN))
 		return -EINVAL;
 	return v4l2_queryctrl(sd->ctrl_handler, qc);
 }
@@ -2307,7 +2414,8 @@ EXPORT_SYMBOL(v4l2_subdev_querymenu);
    Find the controls in the control array and do some basic checks. */
 static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
 			     struct v4l2_ext_controls *cs,
-			     struct v4l2_ctrl_helper *helpers)
+			     struct v4l2_ctrl_helper *helpers,
+			     bool get)
 {
 	struct v4l2_ctrl_helper *h;
 	bool have_clusters = false;
@@ -2339,6 +2447,13 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
 			have_clusters = true;
 		if (ctrl->cluster[0] != ctrl)
 			ref = find_ref_lock(hdl, ctrl->cluster[0]->id);
+		if (ctrl->is_ptr && !ctrl->is_string && c->size < ctrl->elem_size) {
+			if (get) {
+				c->size = ctrl->elem_size;
+				return -ENOSPC;
+			}
+			return -EFAULT;
+		}
 		/* Store the ref to the master control of the cluster */
 		h->mref = ref;
 		h->ctrl = ctrl;
@@ -2419,7 +2534,7 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs
 			return -ENOMEM;
 	}
 
-	ret = prepare_ext_ctrls(hdl, cs, helpers);
+	ret = prepare_ext_ctrls(hdl, cs, helpers, true);
 	cs->error_idx = cs->count;
 
 	for (i = 0; !ret && i < cs->count; i++)
@@ -2481,11 +2596,11 @@ static int get_ctrl(struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c)
 	int ret = 0;
 	int i;
 
-	/* String controls are not supported. The new_to_user() and
+	/* Complex controls are not supported. The new_to_user() and
 	 * cur_to_user() calls below would need to be modified not to access
 	 * userspace memory when called from get_ctrl().
 	 */
-	if (ctrl->type == V4L2_CTRL_TYPE_STRING)
+	if (!ctrl->is_int)
 		return -EINVAL;
 
 	if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
@@ -2511,7 +2626,7 @@ int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control)
 	struct v4l2_ext_control c;
 	int ret;
 
-	if (ctrl == NULL || !type_is_int(ctrl))
+	if (ctrl == NULL || !ctrl->is_int)
 		return -EINVAL;
 	ret = get_ctrl(ctrl, &c);
 	control->value = c.value;
@@ -2530,7 +2645,7 @@ s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl)
 	struct v4l2_ext_control c;
 
 	/* It's a driver bug if this happens. */
-	WARN_ON(!type_is_int(ctrl));
+	WARN_ON(!ctrl->is_int);
 	c.value = 0;
 	get_ctrl(ctrl, &c);
 	return c.value;
@@ -2666,7 +2781,7 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
 		if (!helpers)
 			return -ENOMEM;
 	}
-	ret = prepare_ext_ctrls(hdl, cs, helpers);
+	ret = prepare_ext_ctrls(hdl, cs, helpers, false);
 	if (!ret)
 		ret = validate_ctrls(cs, helpers, set);
 	if (ret && set)
@@ -2771,11 +2886,11 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
 	struct v4l2_ctrl *master = ctrl->cluster[0];
 	int i;
 
-	/* String controls are not supported. The user_to_new() and
+	/* Complex controls are not supported. The user_to_new() and
 	 * cur_to_user() calls below would need to be modified not to access
 	 * userspace memory when called from set_ctrl().
 	 */
-	if (ctrl->type == V4L2_CTRL_TYPE_STRING)
+	if (!ctrl->is_int)
 		return -EINVAL;
 
 	/* Reset the 'is_new' flags of the cluster */
@@ -2817,7 +2932,7 @@ int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
 	struct v4l2_ext_control c;
 	int ret;
 
-	if (ctrl == NULL || !type_is_int(ctrl))
+	if (ctrl == NULL || !ctrl->is_int)
 		return -EINVAL;
 
 	if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
@@ -2841,7 +2956,7 @@ int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
 	struct v4l2_ext_control c;
 
 	/* It's a driver bug if this happens. */
-	WARN_ON(!type_is_int(ctrl));
+	WARN_ON(!ctrl->is_int);
 	c.value = val;
 	return set_ctrl_lock(NULL, ctrl, &c);
 }
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 3998049..e92b237 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -36,6 +36,19 @@ struct v4l2_subscribed_event;
 struct v4l2_fh;
 struct poll_table_struct;
 
+/** union v4l2_ctrl_ptr - A pointer to a control value.
+ * @val:	Pointer to a 32-bit signed value.
+ * @val64:	Pointer to a 64-bit signed value.
+ * @string:	Pointer to a string.
+ * @p:		Pointer to a complex value.
+ */
+union v4l2_ctrl_ptr {
+	s32 *p_s32;
+	s64 *p_s64;
+	char *p_char;
+	void *p;
+};
+
 /** struct v4l2_ctrl_ops - The control operations that the driver has to provide.
   * @g_volatile_ctrl: Get a new value for this control. Generally only relevant
   *		for volatile (and usually read-only) controls such as a control
@@ -73,6 +86,12 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
   *		members are in 'automatic' mode or 'manual' mode. This is
   *		used for autogain/gain type clusters. Drivers should never
   *		set this flag directly.
+  * @is_int:    If set, then this control has a simple integer value (i.e. it
+  *		uses ctrl->val).
+  * @is_string: If set, then this control has type V4L2_CTRL_TYPE_STRING.
+  * @is_ptr:	If set, then this control is a matrix and/or has type >= V4L2_CTRL_COMPLEX_TYPES
+  *		and/or has type V4L2_CTRL_TYPE_STRING. In other words, struct
+  *		v4l2_ext_control uses field p to point to the data.
   * @has_volatiles: If set, then one or more members of the cluster are volatile.
   *		Drivers should never touch this flag.
   * @call_notify: If set, then call the handler's notify function whenever the
@@ -91,6 +110,7 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
   * @maximum:	The control's maximum value.
   * @default_value: The control's default value.
   * @step:	The control's step value for non-menu controls.
+  * @elem_size:	The size in bytes of the control.
   * @menu_skip_mask: The control's skip mask for menu controls. This makes it
   *		easy to skip menu items that are not valid. If bit X is set,
   *		then menu item X is skipped. Of course, this only works for
@@ -105,7 +125,6 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
   * @cur:	The control's current value.
   * @val:	The control's new s32 value.
   * @val64:	The control's new s64 value.
-  * @string:	The control's new string value.
   * @priv:	The control's private pointer. For use by the driver. It is
   *		untouched by the control framework. Note that this pointer is
   *		not freed when the control is deleted. Should this be needed
@@ -124,6 +143,9 @@ struct v4l2_ctrl {
 	unsigned int is_new:1;
 	unsigned int is_private:1;
 	unsigned int is_auto:1;
+	unsigned int is_int:1;
+	unsigned int is_string:1;
+	unsigned int is_ptr:1;
 	unsigned int has_volatiles:1;
 	unsigned int call_notify:1;
 	unsigned int manual_mode_value:8;
@@ -134,6 +156,7 @@ struct v4l2_ctrl {
 	const char *unit;
 	enum v4l2_ctrl_type type;
 	s64 minimum, maximum, default_value;
+	u32 elem_size;
 	union {
 		u64 step;
 		u64 menu_skip_mask;
@@ -143,17 +166,21 @@ struct v4l2_ctrl {
 		const s64 *qmenu_int;
 	};
 	unsigned long flags;
+	void *priv;
 	union {
 		s32 val;
 		s64 val64;
 		char *string;
-	} cur;
+		void *p;
+	};
 	union {
 		s32 val;
 		s64 val64;
 		char *string;
-	};
-	void *priv;
+		void *p;
+	} cur;
+	union v4l2_ctrl_ptr new;
+	union v4l2_ctrl_ptr stores[];
 };
 
 /** struct v4l2_ctrl_ref - The control reference.
@@ -215,6 +242,7 @@ struct v4l2_ctrl_handler {
   * @max:	The control's maximum value.
   * @step:	The control's step value for non-menu controls.
   * @def: 	The control's default value.
+  * @elem_size:	The size in bytes of the control.
   * @flags:	The control's flags.
   * @menu_skip_mask: The control's skip mask for menu controls. This makes it
   *		easy to skip menu items that are not valid. If bit X is set,
@@ -239,6 +267,7 @@ struct v4l2_ctrl_config {
 	s64 max;
 	u64 step;
 	s64 def;
+	u32 elem_size;
 	u32 flags;
 	u64 menu_skip_mask;
 	const char * const *qmenu;
@@ -664,6 +693,7 @@ unsigned int v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait);
 
 /* Helpers for ioctl_ops. If hdl == NULL then they will all return -EINVAL. */
 int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc);
+int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctrl *qc);
 int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm);
 int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *ctrl);
 int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 07/21] v4l2: integrate support for VIDIOC_QUERY_EXT_CTRL.
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
                   ` (5 preceding siblings ...)
  2014-01-20 12:45 ` [RFCv2 PATCH 06/21] v4l2-ctrls: add support for complex types Hans Verkuil
@ 2014-01-20 12:46 ` Hans Verkuil
  2014-01-23 11:44   ` Sylwester Nawrocki
  2014-01-20 12:46 ` [RFCv2 PATCH 08/21] v4l2-ctrls: create type_ops Hans Verkuil
                   ` (14 subsequent siblings)
  21 siblings, 1 reply; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:46 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c |  1 +
 drivers/media/v4l2-core/v4l2-dev.c            |  2 ++
 drivers/media/v4l2-core/v4l2-ioctl.c          | 31 +++++++++++++++++++++++++++
 drivers/media/v4l2-core/v4l2-subdev.c         |  3 +++
 include/media/v4l2-ioctl.h                    |  2 ++
 5 files changed, 39 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 8f7a6a4..0d9b97e 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -1089,6 +1089,7 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
 	case VIDIOC_ENUM_FREQ_BANDS:
 	case VIDIOC_SUBDEV_G_EDID32:
 	case VIDIOC_SUBDEV_S_EDID32:
+	case VIDIOC_QUERY_EXT_CTRL:
 		ret = do_video_ioctl(file, cmd, arg);
 		break;
 
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index b5aaaac..1bf4634 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -576,6 +576,8 @@ static void determine_valid_ioctls(struct video_device *vdev)
 	   be valid if the filehandle passed the control handler. */
 	if (vdev->ctrl_handler || ops->vidioc_queryctrl)
 		set_bit(_IOC_NR(VIDIOC_QUERYCTRL), valid_ioctls);
+	if (vdev->ctrl_handler || ops->vidioc_query_ext_ctrl)
+		set_bit(_IOC_NR(VIDIOC_QUERY_EXT_CTRL), valid_ioctls);
 	if (vdev->ctrl_handler || ops->vidioc_g_ctrl || ops->vidioc_g_ext_ctrls)
 		set_bit(_IOC_NR(VIDIOC_G_CTRL), valid_ioctls);
 	if (vdev->ctrl_handler || ops->vidioc_s_ctrl || ops->vidioc_s_ext_ctrls)
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 707aef7..16c2652 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -515,6 +515,19 @@ static void v4l_print_queryctrl(const void *arg, bool write_only)
 			p->step, p->default_value, p->flags);
 }
 
+static void v4l_print_query_ext_ctrl(const void *arg, bool write_only)
+{
+	const struct v4l2_query_ext_ctrl *p = arg;
+
+	pr_cont("id=0x%x, type=%d, name=%.*s, unit=%.*s, min/max=%lld/%lld, "
+		"step=%lld, default=%lld, flags=0x%08x, cols=%u, rows=%u\n",
+			p->id, p->type, (int)sizeof(p->name), p->name,
+			(int)sizeof(p->unit), p->unit,
+			p->min.val, p->max.val,
+			p->step.val, p->def.val, p->flags,
+			p->cols, p->rows);
+}
+
 static void v4l_print_querymenu(const void *arg, bool write_only)
 {
 	const struct v4l2_querymenu *p = arg;
@@ -1505,6 +1518,23 @@ static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops,
 	return -ENOTTY;
 }
 
+static int v4l_query_ext_ctrl(const struct v4l2_ioctl_ops *ops,
+				struct file *file, void *fh, void *arg)
+{
+	struct video_device *vfd = video_devdata(file);
+	struct v4l2_query_ext_ctrl *p = arg;
+	struct v4l2_fh *vfh =
+		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
+
+	if (vfh && vfh->ctrl_handler)
+		return v4l2_query_ext_ctrl(vfh->ctrl_handler, p);
+	if (vfd->ctrl_handler)
+		return v4l2_query_ext_ctrl(vfd->ctrl_handler, p);
+	if (ops->vidioc_query_ext_ctrl)
+		return ops->vidioc_query_ext_ctrl(file, fh, p);
+	return -ENOTTY;
+}
+
 static int v4l_querymenu(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
@@ -2058,6 +2088,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
 	IOCTL_INFO_STD(VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap, v4l_print_dv_timings_cap, INFO_FL_CLEAR(v4l2_dv_timings_cap, type)),
 	IOCTL_INFO_FNC(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0),
 	IOCTL_INFO_FNC(VIDIOC_DBG_G_CHIP_INFO, v4l_dbg_g_chip_info, v4l_print_dbg_chip_info, INFO_FL_CLEAR(v4l2_dbg_chip_info, match)),
+	IOCTL_INFO_FNC(VIDIOC_QUERY_EXT_CTRL, v4l_query_ext_ctrl, v4l_print_query_ext_ctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_query_ext_ctrl, id)),
 };
 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
 
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 996c248..9242daa 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -139,6 +139,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 	case VIDIOC_QUERYCTRL:
 		return v4l2_queryctrl(vfh->ctrl_handler, arg);
 
+	case VIDIOC_QUERY_EXT_CTRL:
+		return v4l2_query_ext_ctrl(vfh->ctrl_handler, arg);
+
 	case VIDIOC_QUERYMENU:
 		return v4l2_querymenu(vfh->ctrl_handler, arg);
 
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index e0b74a4..ac2b8b9 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -150,6 +150,8 @@ struct v4l2_ioctl_ops {
 		/* Control handling */
 	int (*vidioc_queryctrl)        (struct file *file, void *fh,
 					struct v4l2_queryctrl *a);
+	int (*vidioc_query_ext_ctrl)   (struct file *file, void *fh,
+					struct v4l2_query_ext_ctrl *a);
 	int (*vidioc_g_ctrl)           (struct file *file, void *fh,
 					struct v4l2_control *a);
 	int (*vidioc_s_ctrl)           (struct file *file, void *fh,
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 08/21] v4l2-ctrls: create type_ops.
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
                   ` (6 preceding siblings ...)
  2014-01-20 12:46 ` [RFCv2 PATCH 07/21] v4l2: integrate support for VIDIOC_QUERY_EXT_CTRL Hans Verkuil
@ 2014-01-20 12:46 ` Hans Verkuil
  2014-01-23 14:23   ` Sylwester Nawrocki
  2014-01-24 15:46   ` Sakari Ailus
  2014-01-20 12:46 ` [RFCv2 PATCH 09/21] v4l2-ctrls: rewrite copy routines to operate on union v4l2_ctrl_ptr Hans Verkuil
                   ` (13 subsequent siblings)
  21 siblings, 2 replies; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:46 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Since complex controls can have non-standard types we need to be able to do
type-specific checks etc. In order to make that easy type operations are added.
There are four operations:

- equal: check if two values are equal
- init: initialize a value
- log: log the value
- validate: validate a new value

This patch uses the v4l2_ctrl_ptr union for the first time.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 267 ++++++++++++++++++++++-------------
 include/media/v4l2-ctrls.h           |  21 +++
 2 files changed, 190 insertions(+), 98 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 98e940f..9f97af4 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1123,6 +1123,149 @@ static void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes)
 			v4l2_event_queue_fh(sev->fh, &ev);
 }
 
+static bool std_equal(const struct v4l2_ctrl *ctrl,
+		      union v4l2_ctrl_ptr ptr1,
+		      union v4l2_ctrl_ptr ptr2)
+{
+	switch (ctrl->type) {
+	case V4L2_CTRL_TYPE_BUTTON:
+		return false;
+	case V4L2_CTRL_TYPE_STRING:
+		/* strings are always 0-terminated */
+		return !strcmp(ptr1.p_char, ptr2.p_char);
+	case V4L2_CTRL_TYPE_INTEGER64:
+		return *ptr1.p_s64 == *ptr2.p_s64;
+	default:
+		if (ctrl->is_ptr)
+			return !memcmp(ptr1.p, ptr2.p, ctrl->elem_size);
+		return *ptr1.p_s32 == *ptr2.p_s32;
+	}
+}
+
+static void std_init(const struct v4l2_ctrl *ctrl,
+		     union v4l2_ctrl_ptr ptr)
+{
+	switch (ctrl->type) {
+	case V4L2_CTRL_TYPE_STRING:
+		memset(ptr.p_char, ' ', ctrl->minimum);
+		ptr.p_char[ctrl->minimum] = '\0';
+		break;
+	case V4L2_CTRL_TYPE_INTEGER64:
+		*ptr.p_s64 = ctrl->default_value;
+		break;
+	case V4L2_CTRL_TYPE_INTEGER:
+	case V4L2_CTRL_TYPE_INTEGER_MENU:
+	case V4L2_CTRL_TYPE_MENU:
+	case V4L2_CTRL_TYPE_BITMASK:
+	case V4L2_CTRL_TYPE_BOOLEAN:
+		*ptr.p_s32 = ctrl->default_value;
+		break;
+	default:
+		break;
+	}
+}
+
+static void std_log(const struct v4l2_ctrl *ctrl)
+{
+	union v4l2_ctrl_ptr ptr = ctrl->stores[0];
+
+	switch (ctrl->type) {
+	case V4L2_CTRL_TYPE_INTEGER:
+		pr_cont("%d", *ptr.p_s32);
+		break;
+	case V4L2_CTRL_TYPE_BOOLEAN:
+		pr_cont("%s", *ptr.p_s32 ? "true" : "false");
+		break;
+	case V4L2_CTRL_TYPE_MENU:
+		pr_cont("%s", ctrl->qmenu[*ptr.p_s32]);
+		break;
+	case V4L2_CTRL_TYPE_INTEGER_MENU:
+		pr_cont("%lld", ctrl->qmenu_int[*ptr.p_s32]);
+		break;
+	case V4L2_CTRL_TYPE_BITMASK:
+		pr_cont("0x%08x", *ptr.p_s32);
+		break;
+	case V4L2_CTRL_TYPE_INTEGER64:
+		pr_cont("%lld", *ptr.p_s64);
+		break;
+	case V4L2_CTRL_TYPE_STRING:
+		pr_cont("%s", ptr.p_char);
+		break;
+	default:
+		pr_cont("unknown type %d", ctrl->type);
+		break;
+	}
+}
+
+/* Round towards the closest legal value */
+#define ROUND_TO_RANGE(val, offset_type, ctrl)			\
+({								\
+	offset_type offset;					\
+	val += (ctrl)->step / 2;				\
+	val = clamp_t(typeof(val), val,				\
+		      (ctrl)->minimum, (ctrl)->maximum);	\
+	offset = (val) - (ctrl)->minimum;			\
+	offset = (ctrl)->step * (offset / (ctrl)->step);	\
+	val = (ctrl)->minimum + offset;				\
+	0;							\
+})
+
+/* Validate a new control */
+static int std_validate(const struct v4l2_ctrl *ctrl,
+			union v4l2_ctrl_ptr ptr)
+{
+	size_t len;
+
+	switch (ctrl->type) {
+	case V4L2_CTRL_TYPE_INTEGER:
+		return ROUND_TO_RANGE(*ptr.p_s32, u32, ctrl);
+	case V4L2_CTRL_TYPE_INTEGER64:
+		return ROUND_TO_RANGE(*ptr.p_s64, u64, ctrl);
+
+	case V4L2_CTRL_TYPE_BOOLEAN:
+		*ptr.p_s32 = !!*ptr.p_s32;
+		return 0;
+
+	case V4L2_CTRL_TYPE_MENU:
+	case V4L2_CTRL_TYPE_INTEGER_MENU:
+		if (*ptr.p_s32 < ctrl->minimum || *ptr.p_s32 > ctrl->maximum)
+			return -ERANGE;
+		if (ctrl->menu_skip_mask & (1 << *ptr.p_s32))
+			return -EINVAL;
+		if (ctrl->type == V4L2_CTRL_TYPE_MENU &&
+		    ctrl->qmenu[*ptr.p_s32][0] == '\0')
+			return -EINVAL;
+		return 0;
+
+	case V4L2_CTRL_TYPE_BITMASK:
+		*ptr.p_s32 &= ctrl->maximum;
+		return 0;
+
+	case V4L2_CTRL_TYPE_BUTTON:
+	case V4L2_CTRL_TYPE_CTRL_CLASS:
+		*ptr.p_s32 = 0;
+		return 0;
+
+	case V4L2_CTRL_TYPE_STRING:
+		len = strlen(ptr.p_char);
+		if (len < ctrl->minimum)
+			return -ERANGE;
+		if ((len - ctrl->minimum) % ctrl->step)
+			return -ERANGE;
+		return 0;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct v4l2_ctrl_type_ops std_type_ops = {
+	.equal = std_equal,
+	.init = std_init,
+	.log = std_log,
+	.validate = std_validate,
+};
+
 /* Helper function: copy the current control value back to the caller */
 static int cur_to_user(struct v4l2_ext_control *c,
 		       struct v4l2_ctrl *ctrl)
@@ -1306,21 +1449,7 @@ static int cluster_changed(struct v4l2_ctrl *master)
 
 		if (ctrl == NULL)
 			continue;
-		switch (ctrl->type) {
-		case V4L2_CTRL_TYPE_BUTTON:
-			/* Button controls are always 'different' */
-			return 1;
-		case V4L2_CTRL_TYPE_STRING:
-			/* strings are always 0-terminated */
-			diff = strcmp(ctrl->string, ctrl->cur.string);
-			break;
-		case V4L2_CTRL_TYPE_INTEGER64:
-			diff = ctrl->val64 != ctrl->cur.val64;
-			break;
-		default:
-			diff = ctrl->val != ctrl->cur.val;
-			break;
-		}
+		diff = !ctrl->type_ops->equal(ctrl, ctrl->stores[0], ctrl->new);
 	}
 	return diff;
 }
@@ -1361,65 +1490,30 @@ static int check_range(enum v4l2_ctrl_type type,
 	}
 }
 
-/* Round towards the closest legal value */
-#define ROUND_TO_RANGE(val, offset_type, ctrl)			\
-({								\
-	offset_type offset;					\
-	val += (ctrl)->step / 2;				\
-	val = clamp_t(typeof(val), val,				\
-		      (ctrl)->minimum, (ctrl)->maximum);	\
-	offset = (val) - (ctrl)->minimum;			\
-	offset = (ctrl)->step * (offset / (ctrl)->step);	\
-	val = (ctrl)->minimum + offset;				\
-	0;							\
-})
-
 /* Validate a new control */
 static int validate_new(const struct v4l2_ctrl *ctrl,
 			struct v4l2_ext_control *c)
 {
-	size_t len;
+	union v4l2_ctrl_ptr ptr;
 
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_INTEGER:
-		return ROUND_TO_RANGE(*(s32 *)&c->value, u32, ctrl);
-	case V4L2_CTRL_TYPE_INTEGER64:
-		return ROUND_TO_RANGE(*(s64 *)&c->value64, u64, ctrl);
-
-	case V4L2_CTRL_TYPE_BOOLEAN:
-		c->value = !!c->value;
-		return 0;
-
-	case V4L2_CTRL_TYPE_MENU:
 	case V4L2_CTRL_TYPE_INTEGER_MENU:
-		if (c->value < ctrl->minimum || c->value > ctrl->maximum)
-			return -ERANGE;
-		if (ctrl->menu_skip_mask & (1 << c->value))
-			return -EINVAL;
-		if (ctrl->type == V4L2_CTRL_TYPE_MENU &&
-		    ctrl->qmenu[c->value][0] == '\0')
-			return -EINVAL;
-		return 0;
-
+	case V4L2_CTRL_TYPE_MENU:
 	case V4L2_CTRL_TYPE_BITMASK:
-		c->value &= ctrl->maximum;
-		return 0;
-
+	case V4L2_CTRL_TYPE_BOOLEAN:
 	case V4L2_CTRL_TYPE_BUTTON:
 	case V4L2_CTRL_TYPE_CTRL_CLASS:
-		c->value = 0;
-		return 0;
+		ptr.p_s32 = &c->value;
+		return ctrl->type_ops->validate(ctrl, ptr);
 
-	case V4L2_CTRL_TYPE_STRING:
-		len = strlen(c->string);
-		if (len < ctrl->minimum)
-			return -ERANGE;
-		if ((len - ctrl->minimum) % ctrl->step)
-			return -ERANGE;
-		return 0;
+	case V4L2_CTRL_TYPE_INTEGER64:
+		ptr.p_s64 = &c->value64;
+		return ctrl->type_ops->validate(ctrl, ptr);
 
 	default:
-		return -EINVAL;
+		ptr.p = c->p;
+		return ctrl->type_ops->validate(ctrl, ptr);
 	}
 }
 
@@ -1636,6 +1730,7 @@ unlock:
 /* Add a new control */
 static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 			const struct v4l2_ctrl_ops *ops,
+			const struct v4l2_ctrl_type_ops *type_ops,
 			u32 id, const char *name, const char *unit,
 			enum v4l2_ctrl_type type,
 			s64 min, s64 max, u64 step, s64 def,
@@ -1647,6 +1742,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 	unsigned sz_extra;
 	void *data;
 	int err;
+	int s;
 
 	if (hdl->error)
 		return NULL;
@@ -1706,6 +1802,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 	INIT_LIST_HEAD(&ctrl->ev_subs);
 	ctrl->handler = hdl;
 	ctrl->ops = ops;
+	ctrl->type_ops = type_ops ? type_ops : &std_type_ops;
 	ctrl->id = id;
 	ctrl->name = name;
 	ctrl->unit = unit;
@@ -1727,19 +1824,16 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 	ctrl->cur.val = ctrl->val = def;
 	data = &ctrl->stores[1];
 
-	if (ctrl->is_string) {
-		ctrl->string = ctrl->new.p_char = data;
-		ctrl->stores[0].p_char = data + elem_size;
-
-		if (ctrl->minimum)
-			memset(ctrl->cur.string, ' ', ctrl->minimum);
-	} else if (ctrl->is_ptr) {
+	if (ctrl->is_ptr) {
 		ctrl->p = ctrl->new.p = data;
 		ctrl->stores[0].p = data + elem_size;
 	} else {
 		ctrl->new.p = &ctrl->val;
 		ctrl->stores[0].p = &ctrl->cur.val;
 	}
+	for (s = -1; s <= 0; s++)
+		ctrl->type_ops->init(ctrl, ctrl->stores[s]);
+
 	if (handler_new_ref(hdl, ctrl)) {
 		kfree(ctrl);
 		return NULL;
@@ -1784,7 +1878,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
 		return NULL;
 	}
 
-	ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->id, name, unit,
+	ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->type_ops, cfg->id, name, unit,
 			type, min, max,
 			is_menu ? cfg->menu_skip_mask : step,
 			def, cfg->elem_size,
@@ -1812,7 +1906,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
 		handler_set_err(hdl, -EINVAL);
 		return NULL;
 	}
-	return v4l2_ctrl_new(hdl, ops, id, name, unit, type,
+	return v4l2_ctrl_new(hdl, ops, NULL, id, name, unit, type,
 			     min, max, step, def, 0,
 			     flags, NULL, NULL, NULL);
 }
@@ -1846,7 +1940,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
 		handler_set_err(hdl, -EINVAL);
 		return NULL;
 	}
-	return v4l2_ctrl_new(hdl, ops, id, name, unit, type,
+	return v4l2_ctrl_new(hdl, ops, NULL, id, name, unit, type,
 			     0, max, mask, def, 0,
 			     flags, qmenu, qmenu_int, NULL);
 }
@@ -1879,7 +1973,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
 		handler_set_err(hdl, -EINVAL);
 		return NULL;
 	}
-	return v4l2_ctrl_new(hdl, ops, id, name, unit, type, 0, max, mask, def,
+	return v4l2_ctrl_new(hdl, ops, NULL, id, name, unit, type,
+			     0, max, mask, def,
 			     0, flags, qmenu, NULL, NULL);
 
 }
@@ -1904,7 +1999,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
 		handler_set_err(hdl, -EINVAL);
 		return NULL;
 	}
-	return v4l2_ctrl_new(hdl, ops, id, name, unit, type,
+	return v4l2_ctrl_new(hdl, ops, NULL, id, name, unit, type,
 			     0, max, 0, def, 0,
 			     flags, NULL, qmenu_int, NULL);
 }
@@ -2087,32 +2182,8 @@ static void log_ctrl(const struct v4l2_ctrl *ctrl,
 
 	pr_info("%s%s%s: ", prefix, colon, ctrl->name);
 
-	switch (ctrl->type) {
-	case V4L2_CTRL_TYPE_INTEGER:
-		pr_cont("%d", ctrl->cur.val);
-		break;
-	case V4L2_CTRL_TYPE_BOOLEAN:
-		pr_cont("%s", ctrl->cur.val ? "true" : "false");
-		break;
-	case V4L2_CTRL_TYPE_MENU:
-		pr_cont("%s", ctrl->qmenu[ctrl->cur.val]);
-		break;
-	case V4L2_CTRL_TYPE_INTEGER_MENU:
-		pr_cont("%lld", ctrl->qmenu_int[ctrl->cur.val]);
-		break;
-	case V4L2_CTRL_TYPE_BITMASK:
-		pr_cont("0x%08x", ctrl->cur.val);
-		break;
-	case V4L2_CTRL_TYPE_INTEGER64:
-		pr_cont("%lld", ctrl->cur.val64);
-		break;
-	case V4L2_CTRL_TYPE_STRING:
-		pr_cont("%s", ctrl->cur.string);
-		break;
-	default:
-		pr_cont("unknown type %d", ctrl->type);
-		break;
-	}
+	ctrl->type_ops->log(ctrl);
+
 	if (ctrl->flags & (V4L2_CTRL_FLAG_INACTIVE |
 			   V4L2_CTRL_FLAG_GRABBED |
 			   V4L2_CTRL_FLAG_VOLATILE)) {
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index e92b237..8e7fd44 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -67,6 +67,23 @@ struct v4l2_ctrl_ops {
 	int (*s_ctrl)(struct v4l2_ctrl *ctrl);
 };
 
+/** struct v4l2_ctrl_type_ops - The control type operations that the driver has to provide.
+  * @equal: return true if both values are equal.
+  * @init: initialize the value.
+  * @log: log the value.
+  * @validate: validate the value. Return 0 on success and a negative value otherwise.
+  */
+struct v4l2_ctrl_type_ops {
+	bool (*equal)(const struct v4l2_ctrl *ctrl,
+		      union v4l2_ctrl_ptr ptr1,
+		      union v4l2_ctrl_ptr ptr2);
+	void (*init)(const struct v4l2_ctrl *ctrl,
+		     union v4l2_ctrl_ptr ptr);
+	void (*log)(const struct v4l2_ctrl *ctrl);
+	int (*validate)(const struct v4l2_ctrl *ctrl,
+			union v4l2_ctrl_ptr ptr);
+};
+
 typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
 
 /** struct v4l2_ctrl - The control structure.
@@ -102,6 +119,7 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
   *		value, then the whole cluster is in manual mode. Drivers should
   *		never set this flag directly.
   * @ops:	The control ops.
+  * @type_ops:	The control type ops.
   * @id:	The control ID.
   * @name:	The control name.
   * @unit:	The control's unit. May be NULL.
@@ -151,6 +169,7 @@ struct v4l2_ctrl {
 	unsigned int manual_mode_value:8;
 
 	const struct v4l2_ctrl_ops *ops;
+	const struct v4l2_ctrl_type_ops *type_ops;
 	u32 id;
 	const char *name;
 	const char *unit;
@@ -234,6 +253,7 @@ struct v4l2_ctrl_handler {
 
 /** struct v4l2_ctrl_config - Control configuration structure.
   * @ops:	The control ops.
+  * @type_ops:	The control type ops. Only needed for complex controls.
   * @id:	The control ID.
   * @name:	The control name.
   * @unit:	The control's unit.
@@ -259,6 +279,7 @@ struct v4l2_ctrl_handler {
   */
 struct v4l2_ctrl_config {
 	const struct v4l2_ctrl_ops *ops;
+	const struct v4l2_ctrl_type_ops *type_ops;
 	u32 id;
 	const char *name;
 	const char *unit;
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 09/21] v4l2-ctrls: rewrite copy routines to operate on union v4l2_ctrl_ptr.
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
                   ` (7 preceding siblings ...)
  2014-01-20 12:46 ` [RFCv2 PATCH 08/21] v4l2-ctrls: create type_ops Hans Verkuil
@ 2014-01-20 12:46 ` Hans Verkuil
  2014-01-24 12:31   ` Sakari Ailus
  2014-01-20 12:46 ` [RFCv2 PATCH 10/21] v4l2-ctrls: compare values only once Hans Verkuil
                   ` (12 subsequent siblings)
  21 siblings, 1 reply; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:46 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

In order to implement matrix support and (for the future) configuration stores
we need to have more generic copy routines. The v4l2_ctrl_ptr union was designed
for this.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 129 +++++++++++++++--------------------
 1 file changed, 56 insertions(+), 73 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 9f97af4..c0507ed 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1266,48 +1266,64 @@ static const struct v4l2_ctrl_type_ops std_type_ops = {
 	.validate = std_validate,
 };
 
-/* Helper function: copy the current control value back to the caller */
-static int cur_to_user(struct v4l2_ext_control *c,
-		       struct v4l2_ctrl *ctrl)
+/* Helper function: copy the given control value back to the caller */
+static int ptr_to_user(struct v4l2_ext_control *c,
+		       struct v4l2_ctrl *ctrl,
+		       union v4l2_ctrl_ptr ptr)
 {
 	u32 len;
 
 	if (ctrl->is_ptr && !ctrl->is_string)
-		return copy_to_user(c->p, ctrl->cur.p, ctrl->elem_size);
+		return copy_to_user(c->p, ptr.p, ctrl->elem_size);
 
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_STRING:
-		len = strlen(ctrl->cur.string);
+		len = strlen(ptr.p_char);
 		if (c->size < len + 1) {
 			c->size = len + 1;
 			return -ENOSPC;
 		}
-		return copy_to_user(c->string, ctrl->cur.string,
-						len + 1) ? -EFAULT : 0;
+		return copy_to_user(c->string, ptr.p_char, len + 1) ?
+								-EFAULT : 0;
 	case V4L2_CTRL_TYPE_INTEGER64:
-		c->value64 = ctrl->cur.val64;
+		c->value64 = *ptr.p_s64;
 		break;
 	default:
-		c->value = ctrl->cur.val;
+		c->value = *ptr.p_s32;
 		break;
 	}
 	return 0;
 }
 
-/* Helper function: copy the caller-provider value as the new control value */
-static int user_to_new(struct v4l2_ext_control *c,
+/* Helper function: copy the current control value back to the caller */
+static int cur_to_user(struct v4l2_ext_control *c,
 		       struct v4l2_ctrl *ctrl)
 {
+	return ptr_to_user(c, ctrl, ctrl->stores[0]);
+}
+
+/* Helper function: copy the new control value back to the caller */
+static int new_to_user(struct v4l2_ext_control *c,
+		       struct v4l2_ctrl *ctrl)
+{
+	return ptr_to_user(c, ctrl, ctrl->new);
+}
+
+/* Helper function: copy the caller-provider value to the given control value */
+static int user_to_ptr(struct v4l2_ext_control *c,
+		       struct v4l2_ctrl *ctrl,
+		       union v4l2_ctrl_ptr ptr)
+{
 	int ret;
 	u32 size;
 
 	ctrl->is_new = 1;
 	if (ctrl->is_ptr && !ctrl->is_string)
-		return copy_from_user(ctrl->p, c->p, ctrl->elem_size);
+		return copy_from_user(ptr.p, c->p, ctrl->elem_size);
 
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_INTEGER64:
-		ctrl->val64 = c->value64;
+		*ptr.p_s64 = c->value64;
 		break;
 	case V4L2_CTRL_TYPE_STRING:
 		size = c->size;
@@ -1315,83 +1331,64 @@ static int user_to_new(struct v4l2_ext_control *c,
 			return -ERANGE;
 		if (size > ctrl->maximum + 1)
 			size = ctrl->maximum + 1;
-		ret = copy_from_user(ctrl->string, c->string, size);
+		ret = copy_from_user(ptr.p_char, c->string, size);
 		if (!ret) {
-			char last = ctrl->string[size - 1];
+			char last = ptr.p_char[size - 1];
 
-			ctrl->string[size - 1] = 0;
+			ptr.p_char[size - 1] = 0;
 			/* If the string was longer than ctrl->maximum,
 			   then return an error. */
-			if (strlen(ctrl->string) == ctrl->maximum && last)
+			if (strlen(ptr.p_char) == ctrl->maximum && last)
 				return -ERANGE;
 		}
 		return ret ? -EFAULT : 0;
 	default:
-		ctrl->val = c->value;
+		*ptr.p_s32 = c->value;
 		break;
 	}
 	return 0;
 }
 
-/* Helper function: copy the new control value back to the caller */
-static int new_to_user(struct v4l2_ext_control *c,
+/* Helper function: copy the caller-provider value as the new control value */
+static int user_to_new(struct v4l2_ext_control *c,
 		       struct v4l2_ctrl *ctrl)
 {
-	u32 len;
-
-	if (ctrl->is_ptr && !ctrl->is_string)
-		return copy_to_user(c->p, ctrl->p, ctrl->elem_size);
+	return user_to_ptr(c, ctrl, ctrl->new);
+}
 
+/* Copy the one value to another. */
+static void ptr_to_ptr(struct v4l2_ctrl *ctrl,
+		       union v4l2_ctrl_ptr from, union v4l2_ctrl_ptr to)
+{
+	if (ctrl == NULL)
+		return;
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_STRING:
-		len = strlen(ctrl->string);
-		if (c->size < len + 1) {
-			c->size = ctrl->maximum + 1;
-			return -ENOSPC;
-		}
-		return copy_to_user(c->string, ctrl->string,
-						len + 1) ? -EFAULT : 0;
+		/* strings are always 0-terminated */
+		strcpy(to.p_char, from.p_char);
+		break;
 	case V4L2_CTRL_TYPE_INTEGER64:
-		c->value64 = ctrl->val64;
+		*to.p_s64 = *from.p_s64;
 		break;
 	default:
-		c->value = ctrl->val;
+		if (ctrl->is_ptr)
+			memcpy(to.p, from.p, ctrl->elem_size);
+		else
+			*to.p_s32 = *from.p_s32;
 		break;
 	}
-	return 0;
 }
 
 /* Copy the new value to the current value. */
 static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags)
 {
-	bool changed = false;
+	bool changed;
 
 	if (ctrl == NULL)
 		return;
+	changed = !ctrl->type_ops->equal(ctrl, ctrl->stores[0], ctrl->new);
+	ptr_to_ptr(ctrl, ctrl->new, ctrl->stores[0]);
 
-	switch (ctrl->type) {
-	case V4L2_CTRL_TYPE_BUTTON:
-		changed = true;
-		break;
-	case V4L2_CTRL_TYPE_STRING:
-		/* strings are always 0-terminated */
-		changed = strcmp(ctrl->string, ctrl->cur.string);
-		strcpy(ctrl->cur.string, ctrl->string);
-		break;
-	case V4L2_CTRL_TYPE_INTEGER64:
-		changed = ctrl->val64 != ctrl->cur.val64;
-		ctrl->cur.val64 = ctrl->val64;
-		break;
-	default:
-		if (ctrl->is_ptr) {
-			changed = memcmp(ctrl->p, ctrl->cur.p, ctrl->elem_size);
-			memcpy(ctrl->cur.p, ctrl->p, ctrl->elem_size);
-		} else {
-			changed = ctrl->val != ctrl->cur.val;
-			ctrl->cur.val = ctrl->val;
-		}
-		break;
-	}
 	if (ch_flags & V4L2_EVENT_CTRL_CH_FLAGS) {
 		/* Note: CH_FLAGS is only set for auto clusters. */
 		ctrl->flags &=
@@ -1420,21 +1417,7 @@ static void cur_to_new(struct v4l2_ctrl *ctrl)
 {
 	if (ctrl == NULL)
 		return;
-	switch (ctrl->type) {
-	case V4L2_CTRL_TYPE_STRING:
-		/* strings are always 0-terminated */
-		strcpy(ctrl->string, ctrl->cur.string);
-		break;
-	case V4L2_CTRL_TYPE_INTEGER64:
-		ctrl->val64 = ctrl->cur.val64;
-		break;
-	default:
-		if (ctrl->is_ptr)
-			memcpy(ctrl->p, ctrl->cur.p, ctrl->elem_size);
-		else
-			ctrl->val = ctrl->cur.val;
-		break;
-	}
+	ptr_to_ptr(ctrl, ctrl->stores[0], ctrl->new);
 }
 
 /* Return non-zero if one or more of the controls in the cluster has a new
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 10/21] v4l2-ctrls: compare values only once.
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
                   ` (8 preceding siblings ...)
  2014-01-20 12:46 ` [RFCv2 PATCH 09/21] v4l2-ctrls: rewrite copy routines to operate on union v4l2_ctrl_ptr Hans Verkuil
@ 2014-01-20 12:46 ` Hans Verkuil
  2014-01-23 14:30   ` Sylwester Nawrocki
  2014-01-20 12:46 ` [RFCv2 PATCH 11/21] v4l2-ctrls: prepare for matrix support: add cols & rows fields Hans Verkuil
                   ` (11 subsequent siblings)
  21 siblings, 1 reply; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:46 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

When setting a control the control's new value is compared to the current
value twice: once by new_to_cur(), once by cluster_changed(). Not a big
deal when dealing with simple values, but it can be a problem when dealing
with compound types or matrices. So fix this: cluster_changed() sets the
has_changed flag, which is used by new_to_cur() instead of having to do
another compare.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 17 +++++++++++------
 include/media/v4l2-ctrls.h           |  3 +++
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index c0507ed..2eb5b65 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1386,8 +1386,11 @@ static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags)
 
 	if (ctrl == NULL)
 		return;
-	changed = !ctrl->type_ops->equal(ctrl, ctrl->stores[0], ctrl->new);
-	ptr_to_ptr(ctrl, ctrl->new, ctrl->stores[0]);
+
+	/* has_changed is set by cluster_changed */
+	changed = ctrl->has_changed;
+	if (changed)
+		ptr_to_ptr(ctrl, ctrl->new, ctrl->stores[0]);
 
 	if (ch_flags & V4L2_EVENT_CTRL_CH_FLAGS) {
 		/* Note: CH_FLAGS is only set for auto clusters. */
@@ -1424,17 +1427,19 @@ static void cur_to_new(struct v4l2_ctrl *ctrl)
    value that differs from the current value. */
 static int cluster_changed(struct v4l2_ctrl *master)
 {
-	int diff = 0;
+	bool changed = false;
 	int i;
 
-	for (i = 0; !diff && i < master->ncontrols; i++) {
+	for (i = 0; i < master->ncontrols; i++) {
 		struct v4l2_ctrl *ctrl = master->cluster[i];
 
 		if (ctrl == NULL)
 			continue;
-		diff = !ctrl->type_ops->equal(ctrl, ctrl->stores[0], ctrl->new);
+		ctrl->has_changed = !ctrl->type_ops->equal(ctrl,
+						ctrl->stores[0], ctrl->new);
+		changed |= ctrl->has_changed;
 	}
-	return diff;
+	return changed;
 }
 
 /* Control range checking */
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 8e7fd44..fb3aaf9 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -96,6 +96,8 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
   * @is_new:	Set when the user specified a new value for this control. It
   *		is also set when called from v4l2_ctrl_handler_setup. Drivers
   *		should never set this flag.
+  * @has_changed: Set when the current value differs from the new value. Drivers
+  *		should never use this flag.
   * @is_private: If set, then this control is private to its handler and it
   *		will not be added to any other handlers. Drivers can set
   *		this flag.
@@ -159,6 +161,7 @@ struct v4l2_ctrl {
 	unsigned int done:1;
 
 	unsigned int is_new:1;
+	unsigned int has_changed:1;
 	unsigned int is_private:1;
 	unsigned int is_auto:1;
 	unsigned int is_int:1;
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 11/21] v4l2-ctrls: prepare for matrix support: add cols & rows fields.
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
                   ` (9 preceding siblings ...)
  2014-01-20 12:46 ` [RFCv2 PATCH 10/21] v4l2-ctrls: compare values only once Hans Verkuil
@ 2014-01-20 12:46 ` Hans Verkuil
  2014-01-23 13:46   ` Sylwester Nawrocki
  2014-01-20 12:46 ` [RFCv2 PATCH 12/21] v4l2-ctrls: replace cur by a union v4l2_ctrl_ptr Hans Verkuil
                   ` (10 subsequent siblings)
  21 siblings, 1 reply; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:46 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Add cols and rows fields to the core control structures in preparation
for matrix support.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 26 +++++++++++++++++---------
 include/media/v4l2-ctrls.h           |  6 ++++++
 2 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 2eb5b65..c995439 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1722,7 +1722,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 			u32 id, const char *name, const char *unit,
 			enum v4l2_ctrl_type type,
 			s64 min, s64 max, u64 step, s64 def,
-			u32 elem_size,
+			u32 cols, u32 rows, u32 elem_size,
 			u32 flags, const char * const *qmenu,
 			const s64 *qmenu_int, void *priv)
 {
@@ -1735,6 +1735,11 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 	if (hdl->error)
 		return NULL;
 
+	if (cols == 0)
+		cols = 1;
+	if (rows == 0)
+		rows = 1;
+
 	if (type == V4L2_CTRL_TYPE_INTEGER64)
 		elem_size = sizeof(s64);
 	else if (type == V4L2_CTRL_TYPE_STRING)
@@ -1803,6 +1808,8 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 	ctrl->is_string = type == V4L2_CTRL_TYPE_STRING;
 	ctrl->is_ptr = type >= V4L2_CTRL_COMPLEX_TYPES || ctrl->is_string;
 	ctrl->is_int = !ctrl->is_ptr && type != V4L2_CTRL_TYPE_INTEGER64;
+	ctrl->cols = cols;
+	ctrl->rows = rows;
 	ctrl->elem_size = elem_size;
 	if (type == V4L2_CTRL_TYPE_MENU)
 		ctrl->qmenu = qmenu;
@@ -1868,8 +1875,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
 
 	ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->type_ops, cfg->id, name, unit,
 			type, min, max,
-			is_menu ? cfg->menu_skip_mask : step,
-			def, cfg->elem_size,
+			is_menu ? cfg->menu_skip_mask : step, def,
+			cfg->cols, cfg->rows, cfg->elem_size,
 			flags, qmenu, qmenu_int, priv);
 	if (ctrl)
 		ctrl->is_private = cfg->is_private;
@@ -1895,7 +1902,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
 		return NULL;
 	}
 	return v4l2_ctrl_new(hdl, ops, NULL, id, name, unit, type,
-			     min, max, step, def, 0,
+			     min, max, step, def, 0, 0, 0,
 			     flags, NULL, NULL, NULL);
 }
 EXPORT_SYMBOL(v4l2_ctrl_new_std);
@@ -1929,7 +1936,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
 		return NULL;
 	}
 	return v4l2_ctrl_new(hdl, ops, NULL, id, name, unit, type,
-			     0, max, mask, def, 0,
+			     0, max, mask, def, 0, 0, 0,
 			     flags, qmenu, qmenu_int, NULL);
 }
 EXPORT_SYMBOL(v4l2_ctrl_new_std_menu);
@@ -1962,8 +1969,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
 		return NULL;
 	}
 	return v4l2_ctrl_new(hdl, ops, NULL, id, name, unit, type,
-			     0, max, mask, def,
-			     0, flags, qmenu, NULL, NULL);
+			     0, max, mask, def, 0, 0, 0,
+			     flags, qmenu, NULL, NULL);
 
 }
 EXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items);
@@ -1988,7 +1995,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
 		return NULL;
 	}
 	return v4l2_ctrl_new(hdl, ops, NULL, id, name, unit, type,
-			     0, max, 0, def, 0,
+			     0, max, 0, def, 0, 0, 0,
 			     flags, NULL, qmenu_int, NULL);
 }
 EXPORT_SYMBOL(v4l2_ctrl_new_int_menu);
@@ -2327,7 +2334,8 @@ int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctr
 	qc->min.val = ctrl->minimum;
 	qc->max.val = ctrl->maximum;
 	qc->def.val = ctrl->default_value;
-	qc->cols = qc->rows = 1;
+	qc->cols = ctrl->cols;
+	qc->rows = ctrl->rows;
 	if (ctrl->type == V4L2_CTRL_TYPE_MENU
 	    || ctrl->type == V4L2_CTRL_TYPE_INTEGER_MENU)
 		qc->step.val = 1;
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index fb3aaf9..c86a071 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -129,6 +129,8 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
   * @minimum:	The control's minimum value.
   * @maximum:	The control's maximum value.
   * @default_value: The control's default value.
+  * @rows:	The number of rows in the matrix.
+  * @cols:	The number of columns in the matrix.
   * @step:	The control's step value for non-menu controls.
   * @elem_size:	The size in bytes of the control.
   * @menu_skip_mask: The control's skip mask for menu controls. This makes it
@@ -178,6 +180,7 @@ struct v4l2_ctrl {
 	const char *unit;
 	enum v4l2_ctrl_type type;
 	s64 minimum, maximum, default_value;
+	u32 rows, cols;
 	u32 elem_size;
 	union {
 		u64 step;
@@ -265,6 +268,8 @@ struct v4l2_ctrl_handler {
   * @max:	The control's maximum value.
   * @step:	The control's step value for non-menu controls.
   * @def: 	The control's default value.
+  * @rows:	The number of rows in the matrix.
+  * @cols:	The number of columns in the matrix.
   * @elem_size:	The size in bytes of the control.
   * @flags:	The control's flags.
   * @menu_skip_mask: The control's skip mask for menu controls. This makes it
@@ -291,6 +296,7 @@ struct v4l2_ctrl_config {
 	s64 max;
 	u64 step;
 	s64 def;
+	u32 rows, cols;
 	u32 elem_size;
 	u32 flags;
 	u64 menu_skip_mask;
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 12/21] v4l2-ctrls: replace cur by a union v4l2_ctrl_ptr.
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
                   ` (10 preceding siblings ...)
  2014-01-20 12:46 ` [RFCv2 PATCH 11/21] v4l2-ctrls: prepare for matrix support: add cols & rows fields Hans Verkuil
@ 2014-01-20 12:46 ` Hans Verkuil
  2014-01-23 15:47   ` Sylwester Nawrocki
  2014-01-20 12:46 ` [RFCv2 PATCH 13/21] v4l2-ctrls: use 'new' to access pointer controls Hans Verkuil
                   ` (9 subsequent siblings)
  21 siblings, 1 reply; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:46 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Instead of having to maintain the 'cur' union this patch replaces it by
a v4l2_ctrl_ptr union to be consistent with the future configuration stores,
which also use that union. The number of drivers that use 'cur' is fairly small,
so it is easy enough to convert them all.

Unfortunately, the union for the new value cannot be dropped as easily
since it is used pretty much everywhere.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 Documentation/video4linux/v4l2-controls.txt   |  4 ++--
 drivers/media/common/cx2341x.c                |  4 ++--
 drivers/media/i2c/adp1653.c                   | 10 +++++-----
 drivers/media/i2c/as3645a.c                   | 22 ++++++++++-----------
 drivers/media/i2c/lm3560.c                    |  2 +-
 drivers/media/i2c/m5mols/m5mols_controls.c    |  6 +++---
 drivers/media/i2c/msp3400-driver.c            |  4 ++--
 drivers/media/i2c/mt9p031.c                   |  4 ++--
 drivers/media/i2c/mt9t001.c                   |  4 ++--
 drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c     |  6 +++---
 drivers/media/i2c/smiapp/smiapp-core.c        | 12 ++++++------
 drivers/media/pci/cx18/cx18-av-core.c         |  2 +-
 drivers/media/pci/cx18/cx18-driver.c          | 10 +++++-----
 drivers/media/platform/exynos4-is/fimc-core.c |  6 +++---
 drivers/media/platform/vivi.c                 | 28 +++++++++++++--------------
 drivers/media/radio/radio-isa.c               |  2 +-
 drivers/media/radio/radio-sf16fmr2.c          |  4 ++--
 drivers/media/usb/gspca/conex.c               |  8 ++++----
 drivers/media/usb/gspca/sn9c20x.c             |  4 ++--
 drivers/media/usb/gspca/topro.c               |  4 ++--
 drivers/media/v4l2-core/v4l2-ctrls.c          | 16 +++++++--------
 include/media/v4l2-ctrls.h                    |  9 ++-------
 22 files changed, 83 insertions(+), 88 deletions(-)

diff --git a/Documentation/video4linux/v4l2-controls.txt b/Documentation/video4linux/v4l2-controls.txt
index 06cf3ac..1c353c2 100644
--- a/Documentation/video4linux/v4l2-controls.txt
+++ b/Documentation/video4linux/v4l2-controls.txt
@@ -362,8 +362,8 @@ will result in a deadlock since these helpers lock the handler as well.
 You can also take the handler lock yourself:
 
 	mutex_lock(&state->ctrl_handler.lock);
-	printk(KERN_INFO "String value is '%s'\n", ctrl1->cur.string);
-	printk(KERN_INFO "Integer value is '%s'\n", ctrl2->cur.val);
+	pr_info("String value is '%s'\n", ctrl1->cur.p_char);
+	pr_info("Integer value is '%d'\n", *ctrl2->cur.p_s32);
 	mutex_unlock(&state->ctrl_handler.lock);
 
 
diff --git a/drivers/media/common/cx2341x.c b/drivers/media/common/cx2341x.c
index 103ef6b..909d334 100644
--- a/drivers/media/common/cx2341x.c
+++ b/drivers/media/common/cx2341x.c
@@ -1261,10 +1261,10 @@ static int cx2341x_hdl_api(struct cx2341x_handler *hdl,
 	return hdl->func(hdl->priv, cmd, args, 0, data);
 }
 
-/* ctrl->handler->lock is held, so it is safe to access cur.val */
+/* ctrl->handler->lock is held, so it is safe to access *cur.p_s32 */
 static inline int cx2341x_neq(struct v4l2_ctrl *ctrl)
 {
-	return ctrl && ctrl->val != ctrl->cur.val;
+	return ctrl && ctrl->val != *ctrl->cur.p_s32;
 }
 
 static int cx2341x_try_ctrl(struct v4l2_ctrl *ctrl)
diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c
index 873fe19..7d478dc 100644
--- a/drivers/media/i2c/adp1653.c
+++ b/drivers/media/i2c/adp1653.c
@@ -158,16 +158,16 @@ static int adp1653_get_ctrl(struct v4l2_ctrl *ctrl)
 	if (IS_ERR_VALUE(rval))
 		return rval;
 
-	ctrl->cur.val = 0;
+	*ctrl->cur.p_s32 = 0;
 
 	if (flash->fault & ADP1653_REG_FAULT_FLT_SCP)
-		ctrl->cur.val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
+		*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
 	if (flash->fault & ADP1653_REG_FAULT_FLT_OT)
-		ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
+		*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
 	if (flash->fault & ADP1653_REG_FAULT_FLT_TMR)
-		ctrl->cur.val |= V4L2_FLASH_FAULT_TIMEOUT;
+		*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_TIMEOUT;
 	if (flash->fault & ADP1653_REG_FAULT_FLT_OV)
-		ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
+		*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
 
 	flash->fault = 0;
 
diff --git a/drivers/media/i2c/as3645a.c b/drivers/media/i2c/as3645a.c
index 301084b..4c6041c 100644
--- a/drivers/media/i2c/as3645a.c
+++ b/drivers/media/i2c/as3645a.c
@@ -334,24 +334,24 @@ static int as3645a_get_ctrl(struct v4l2_ctrl *ctrl)
 		if (value < 0)
 			return value;
 
-		ctrl->cur.val = 0;
+		*ctrl->cur.p_s32 = 0;
 		if (value & AS_FAULT_INFO_SHORT_CIRCUIT)
-			ctrl->cur.val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
+			*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
 		if (value & AS_FAULT_INFO_OVER_TEMPERATURE)
-			ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
+			*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
 		if (value & AS_FAULT_INFO_TIMEOUT)
-			ctrl->cur.val |= V4L2_FLASH_FAULT_TIMEOUT;
+			*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_TIMEOUT;
 		if (value & AS_FAULT_INFO_OVER_VOLTAGE)
-			ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
+			*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
 		if (value & AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT)
-			ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_CURRENT;
+			*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_OVER_CURRENT;
 		if (value & AS_FAULT_INFO_INDICATOR_LED)
-			ctrl->cur.val |= V4L2_FLASH_FAULT_INDICATOR;
+			*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_INDICATOR;
 		break;
 
 	case V4L2_CID_FLASH_STROBE_STATUS:
 		if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) {
-			ctrl->cur.val = 0;
+			*ctrl->cur.p_s32 = 0;
 			break;
 		}
 
@@ -359,11 +359,11 @@ static int as3645a_get_ctrl(struct v4l2_ctrl *ctrl)
 		if (value < 0)
 			return value;
 
-		ctrl->cur.val = value;
+		*ctrl->cur.p_s32 = value;
 		break;
 	}
 
-	dev_dbg(&client->dev, "G_CTRL %08x:%d\n", ctrl->id, ctrl->cur.val);
+	dev_dbg(&client->dev, "G_CTRL %08x:%d\n", ctrl->id, *ctrl->cur.p_s32);
 
 	return 0;
 }
@@ -458,7 +458,7 @@ static int as3645a_set_ctrl(struct v4l2_ctrl *ctrl)
 		if (ret < 0)
 			return ret;
 
-		if ((ctrl->val == 0) == (ctrl->cur.val == 0))
+		if ((ctrl->val == 0) == (*ctrl->cur.p_s32 == 0))
 			break;
 
 		return as3645a_set_output(flash, false);
diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c
index d98ca3a..edfe746 100644
--- a/drivers/media/i2c/lm3560.c
+++ b/drivers/media/i2c/lm3560.c
@@ -188,7 +188,7 @@ static int lm3560_get_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no)
 			fault |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
 		if (reg_val & FAULT_TIMEOUT)
 			fault |= V4L2_FLASH_FAULT_TIMEOUT;
-		ctrl->cur.val = fault;
+		*ctrl->cur.p_s32 = fault;
 	}
 
 out:
diff --git a/drivers/media/i2c/m5mols/m5mols_controls.c b/drivers/media/i2c/m5mols/m5mols_controls.c
index a60931e..7851d1f 100644
--- a/drivers/media/i2c/m5mols/m5mols_controls.c
+++ b/drivers/media/i2c/m5mols/m5mols_controls.c
@@ -191,7 +191,7 @@ static int m5mols_3a_lock(struct m5mols_info *info, struct v4l2_ctrl *ctrl)
 	bool af_lock = ctrl->val & V4L2_LOCK_FOCUS;
 	int ret = 0;
 
-	if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_EXPOSURE) {
+	if ((ctrl->val ^ *ctrl->cur.p_s32) & V4L2_LOCK_EXPOSURE) {
 		bool ae_lock = ctrl->val & V4L2_LOCK_EXPOSURE;
 
 		ret = m5mols_write(&info->sd, AE_LOCK, ae_lock ?
@@ -200,7 +200,7 @@ static int m5mols_3a_lock(struct m5mols_info *info, struct v4l2_ctrl *ctrl)
 			return ret;
 	}
 
-	if (((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_WHITE_BALANCE)
+	if (((ctrl->val ^ *ctrl->cur.p_s32) & V4L2_LOCK_WHITE_BALANCE)
 	    && info->auto_wb->val) {
 		bool awb_lock = ctrl->val & V4L2_LOCK_WHITE_BALANCE;
 
@@ -213,7 +213,7 @@ static int m5mols_3a_lock(struct m5mols_info *info, struct v4l2_ctrl *ctrl)
 	if (!info->ver.af || !af_lock)
 		return ret;
 
-	if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_FOCUS)
+	if ((ctrl->val ^ *ctrl->cur.p_s32) & V4L2_LOCK_FOCUS)
 		ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP);
 
 	return ret;
diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c
index 8190fec..151016d 100644
--- a/drivers/media/i2c/msp3400-driver.c
+++ b/drivers/media/i2c/msp3400-driver.c
@@ -411,8 +411,8 @@ void msp_update_volume(struct msp_state *state)
 {
 	/* Force an update of the volume/mute cluster */
 	v4l2_ctrl_lock(state->volume);
-	state->volume->val = state->volume->cur.val;
-	state->muted->val = state->muted->cur.val;
+	state->volume->val = *state->volume->cur.p_s32;
+	state->muted->val = *state->muted->cur.p_s32;
 	msp_s_ctrl(state->volume);
 	v4l2_ctrl_unlock(state->volume);
 }
diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c
index e5ddf47..28c17e0 100644
--- a/drivers/media/i2c/mt9p031.c
+++ b/drivers/media/i2c/mt9p031.c
@@ -670,12 +670,12 @@ static int mt9p031_s_ctrl(struct v4l2_ctrl *ctrl)
 	case V4L2_CID_TEST_PATTERN:
 		if (!ctrl->val) {
 			/* Restore the black level compensation settings. */
-			if (mt9p031->blc_auto->cur.val != 0) {
+			if (*mt9p031->blc_auto->cur.p_s32 != 0) {
 				ret = mt9p031_s_ctrl(mt9p031->blc_auto);
 				if (ret < 0)
 					return ret;
 			}
-			if (mt9p031->blc_offset->cur.val != 0) {
+			if (*mt9p031->blc_offset->cur.p_s32 != 0) {
 				ret = mt9p031_s_ctrl(mt9p031->blc_offset);
 				if (ret < 0)
 					return ret;
diff --git a/drivers/media/i2c/mt9t001.c b/drivers/media/i2c/mt9t001.c
index d41c70e..6aca05b 100644
--- a/drivers/media/i2c/mt9t001.c
+++ b/drivers/media/i2c/mt9t001.c
@@ -447,7 +447,7 @@ static int mt9t001_s_ctrl(struct v4l2_ctrl *ctrl)
 		for (i = 0, count = 0; i < 4; ++i) {
 			struct v4l2_ctrl *gain = mt9t001->gains[i];
 
-			if (gain->val != gain->cur.val)
+			if (gain->val != *gain->cur.p_s32)
 				count++;
 		}
 
@@ -461,7 +461,7 @@ static int mt9t001_s_ctrl(struct v4l2_ctrl *ctrl)
 		for (i = 0; i < 4; ++i) {
 			struct v4l2_ctrl *gain = mt9t001->gains[i];
 
-			if (gain->val == gain->cur.val)
+			if (gain->val == *gain->cur.p_s32)
 				continue;
 
 			value = mt9t001_gain_value(&gain->val);
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c b/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c
index 8001cde..cb6da84 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c
+++ b/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c
@@ -195,14 +195,14 @@ static int s5c73m3_3a_lock(struct s5c73m3 *state, struct v4l2_ctrl *ctrl)
 	bool af_lock = ctrl->val & V4L2_LOCK_FOCUS;
 	int ret = 0;
 
-	if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_EXPOSURE) {
+	if ((ctrl->val ^ *ctrl->cur.p_s32) & V4L2_LOCK_EXPOSURE) {
 		ret = s5c73m3_isp_command(state, COMM_AE_CON,
 				ae_lock ? COMM_AE_STOP : COMM_AE_START);
 		if (ret)
 			return ret;
 	}
 
-	if (((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_WHITE_BALANCE)
+	if (((ctrl->val ^ *ctrl->cur.p_s32) & V4L2_LOCK_WHITE_BALANCE)
 	    && state->ctrls.auto_wb->val) {
 		ret = s5c73m3_isp_command(state, COMM_AWB_CON,
 			awb_lock ? COMM_AWB_STOP : COMM_AWB_START);
@@ -210,7 +210,7 @@ static int s5c73m3_3a_lock(struct s5c73m3 *state, struct v4l2_ctrl *ctrl)
 			return ret;
 	}
 
-	if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_FOCUS)
+	if ((ctrl->val ^ *ctrl->cur.p_s32) & V4L2_LOCK_FOCUS)
 		ret = s5c73m3_af_run(state, ~af_lock);
 
 	return ret;
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index 8741cae..d87c5e8 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -297,8 +297,8 @@ static int smiapp_pll_update(struct smiapp_sensor *sensor)
 	if (rval < 0)
 		return rval;
 
-	sensor->pixel_rate_parray->cur.val64 = pll->vt_pix_clk_freq_hz;
-	sensor->pixel_rate_csi->cur.val64 = pll->pixel_rate_csi;
+	*sensor->pixel_rate_parray->cur.p_s64 = pll->vt_pix_clk_freq_hz;
+	*sensor->pixel_rate_csi->cur.p_s64 = pll->pixel_rate_csi;
 
 	return 0;
 }
@@ -324,8 +324,8 @@ static void __smiapp_update_exposure_limits(struct smiapp_sensor *sensor)
 		ctrl->default_value = max;
 	if (ctrl->val > max)
 		ctrl->val = max;
-	if (ctrl->cur.val > max)
-		ctrl->cur.val = max;
+	if (*ctrl->cur.p_s32 > max)
+		*ctrl->cur.p_s32 = max;
 }
 
 /*
@@ -796,7 +796,7 @@ static void smiapp_update_blanking(struct smiapp_sensor *sensor)
 			      vblank->minimum, vblank->maximum);
 	vblank->default_value = vblank->minimum;
 	vblank->val = vblank->val;
-	vblank->cur.val = vblank->val;
+	*vblank->cur.p_s32 = vblank->val;
 
 	hblank->minimum =
 		max_t(int,
@@ -811,7 +811,7 @@ static void smiapp_update_blanking(struct smiapp_sensor *sensor)
 			      hblank->minimum, hblank->maximum);
 	hblank->default_value = hblank->minimum;
 	hblank->val = hblank->val;
-	hblank->cur.val = hblank->val;
+	*hblank->cur.p_s32 = hblank->val;
 
 	__smiapp_update_exposure_limits(sensor);
 }
diff --git a/drivers/media/pci/cx18/cx18-av-core.c b/drivers/media/pci/cx18/cx18-av-core.c
index c4890a4..d230a9b 100644
--- a/drivers/media/pci/cx18/cx18-av-core.c
+++ b/drivers/media/pci/cx18/cx18-av-core.c
@@ -262,7 +262,7 @@ static void cx18_av_initialize(struct v4l2_subdev *sd)
 		cx18_av_write(cx, 0x8d4, 20);
 	}
 	default_volume = (((228 - default_volume) >> 1) + 23) << 9;
-	state->volume->cur.val = state->volume->default_value = default_volume;
+	*state->volume->cur.p_s32 = state->volume->default_value = default_volume;
 	v4l2_ctrl_handler_setup(&state->hdl);
 }
 
diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c
index 716bdc5..e4d0740 100644
--- a/drivers/media/pci/cx18/cx18-driver.c
+++ b/drivers/media/pci/cx18/cx18-driver.c
@@ -756,11 +756,11 @@ static int cx18_init_struct1(struct cx18 *cx)
 		return ret;
 	cx->v4l2_dev.ctrl_handler = &cx->cxhdl.hdl;
 
-	cx->temporal_strength = cx->cxhdl.video_temporal_filter->cur.val;
-	cx->spatial_strength = cx->cxhdl.video_spatial_filter->cur.val;
-	cx->filter_mode = cx->cxhdl.video_spatial_filter_mode->cur.val |
-		(cx->cxhdl.video_temporal_filter_mode->cur.val << 1) |
-		(cx->cxhdl.video_median_filter_type->cur.val << 2);
+	cx->temporal_strength = *cx->cxhdl.video_temporal_filter->cur.p_s32;
+	cx->spatial_strength = *cx->cxhdl.video_spatial_filter->cur.p_s32;
+	cx->filter_mode = *cx->cxhdl.video_spatial_filter_mode->cur.p_s32 |
+		(*cx->cxhdl.video_temporal_filter_mode->cur.p_s32 << 1) |
+		(*cx->cxhdl.video_median_filter_type->cur.p_s32 << 2);
 
 	init_waitqueue_head(&cx->cap_w);
 	init_waitqueue_head(&cx->mb_apu_waitq);
diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c
index a7dfd07..d399699 100644
--- a/drivers/media/platform/exynos4-is/fimc-core.c
+++ b/drivers/media/platform/exynos4-is/fimc-core.c
@@ -664,7 +664,7 @@ void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active)
 		v4l2_ctrl_activate(ctrls->alpha, active && has_alpha);
 
 	if (active) {
-		fimc_set_color_effect(ctx, ctrls->colorfx->cur.val);
+		fimc_set_color_effect(ctx, *ctrls->colorfx->cur.p_s32);
 		ctx->rotation = ctrls->rotate->val;
 		ctx->hflip    = ctrls->hflip->val;
 		ctx->vflip    = ctrls->vflip->val;
@@ -689,8 +689,8 @@ void fimc_alpha_ctrl_update(struct fimc_ctx *ctx)
 	v4l2_ctrl_lock(ctrl);
 	ctrl->maximum = fimc_get_alpha_mask(ctx->d_frame.fmt);
 
-	if (ctrl->cur.val > ctrl->maximum)
-		ctrl->cur.val = ctrl->maximum;
+	if (*ctrl->cur.p_s32 > ctrl->maximum)
+		*ctrl->cur.p_s32 = ctrl->maximum;
 
 	v4l2_ctrl_unlock(ctrl);
 }
diff --git a/drivers/media/platform/vivi.c b/drivers/media/platform/vivi.c
index 2d4e73b..2ec8511 100644
--- a/drivers/media/platform/vivi.c
+++ b/drivers/media/platform/vivi.c
@@ -642,28 +642,28 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
 	gain = v4l2_ctrl_g_ctrl(dev->gain);
 	mutex_lock(dev->ctrl_handler.lock);
 	snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ",
-			dev->brightness->cur.val,
-			dev->contrast->cur.val,
-			dev->saturation->cur.val,
-			dev->hue->cur.val);
+			*dev->brightness->cur.p_s32,
+			*dev->contrast->cur.p_s32,
+			*dev->saturation->cur.p_s32,
+			*dev->hue->cur.p_s32);
 	gen_text(dev, vbuf, line++ * 16, 16, str);
 	snprintf(str, sizeof(str), " autogain %d, gain %3d, volume %3d, alpha 0x%02x ",
-			dev->autogain->cur.val, gain, dev->volume->cur.val,
-			dev->alpha->cur.val);
+			*dev->autogain->cur.p_s32, gain, *dev->volume->cur.p_s32,
+			*dev->alpha->cur.p_s32);
 	gen_text(dev, vbuf, line++ * 16, 16, str);
 	snprintf(str, sizeof(str), " int32 %d, int64 %lld, bitmask %08x ",
-			dev->int32->cur.val,
-			dev->int64->cur.val64,
-			dev->bitmask->cur.val);
+			*dev->int32->cur.p_s32,
+			*dev->int64->cur.p_s64,
+			*dev->bitmask->cur.p_s32);
 	gen_text(dev, vbuf, line++ * 16, 16, str);
 	snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
-			dev->boolean->cur.val,
-			dev->menu->qmenu[dev->menu->cur.val],
-			dev->string->cur.string);
+			*dev->boolean->cur.p_s32,
+			dev->menu->qmenu[*dev->menu->cur.p_s32],
+			dev->string->cur.p_char);
 	gen_text(dev, vbuf, line++ * 16, 16, str);
 	snprintf(str, sizeof(str), " integer_menu %lld, value %d ",
-			dev->int_menu->qmenu_int[dev->int_menu->cur.val],
-			dev->int_menu->cur.val);
+			dev->int_menu->qmenu_int[*dev->int_menu->cur.p_s32],
+			*dev->int_menu->cur.p_s32);
 	gen_text(dev, vbuf, line++ * 16, 16, str);
 	mutex_unlock(dev->ctrl_handler.lock);
 	if (dev->button_pressed) {
diff --git a/drivers/media/radio/radio-isa.c b/drivers/media/radio/radio-isa.c
index 6ff3508..46d188d 100644
--- a/drivers/media/radio/radio-isa.c
+++ b/drivers/media/radio/radio-isa.c
@@ -294,7 +294,7 @@ static int radio_isa_common_remove(struct radio_isa_card *isa,
 {
 	const struct radio_isa_ops *ops = isa->drv->ops;
 
-	ops->s_mute_volume(isa, true, isa->volume ? isa->volume->cur.val : 0);
+	ops->s_mute_volume(isa, true, isa->volume ? *isa->volume->cur.p_s32 : 0);
 	video_unregister_device(&isa->vdev);
 	v4l2_ctrl_handler_free(&isa->hdl);
 	v4l2_device_unregister(&isa->v4l2_dev);
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index 93d864e..e393130 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -154,11 +154,11 @@ static int fmr2_s_ctrl(struct v4l2_ctrl *ctrl)
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_VOLUME:
 		volume = ctrl->val;
-		balance = fmr2->balance->cur.val;
+		balance = *fmr2->balance->cur.p_s32;
 		break;
 	case V4L2_CID_AUDIO_BALANCE:
 		balance = ctrl->val;
-		volume = fmr2->volume->cur.val;
+		volume = *fmr2->volume->cur.p_s32;
 		break;
 	default:
 		return -EINVAL;
diff --git a/drivers/media/usb/gspca/conex.c b/drivers/media/usb/gspca/conex.c
index 2e15c80..e8cfaf3 100644
--- a/drivers/media/usb/gspca/conex.c
+++ b/drivers/media/usb/gspca/conex.c
@@ -887,14 +887,14 @@ static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
 
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
-		setbrightness(gspca_dev, ctrl->val, sd->sat->cur.val);
+		setbrightness(gspca_dev, ctrl->val, *sd->sat->cur.p_s32);
 		break;
 	case V4L2_CID_CONTRAST:
-		setcontrast(gspca_dev, ctrl->val, sd->sat->cur.val);
+		setcontrast(gspca_dev, ctrl->val, *sd->sat->cur.p_s32);
 		break;
 	case V4L2_CID_SATURATION:
-		setbrightness(gspca_dev, sd->brightness->cur.val, ctrl->val);
-		setcontrast(gspca_dev, sd->contrast->cur.val, ctrl->val);
+		setbrightness(gspca_dev, *sd->brightness->cur.p_s32, ctrl->val);
+		setcontrast(gspca_dev, *sd->contrast->cur.p_s32, ctrl->val);
 		break;
 	}
 	return gspca_dev->usb_err;
diff --git a/drivers/media/usb/gspca/sn9c20x.c b/drivers/media/usb/gspca/sn9c20x.c
index 2a38621..22d93c3 100644
--- a/drivers/media/usb/gspca/sn9c20x.c
+++ b/drivers/media/usb/gspca/sn9c20x.c
@@ -2218,7 +2218,7 @@ static void transfer_check(struct gspca_dev *gspca_dev,
 			/* Note: we are in interrupt context, so we can't
 			   use v4l2_ctrl_g/s_ctrl here. Access the value
 			   directly instead. */
-			s32 curqual = sd->jpegqual->cur.val;
+			s32 curqual = *sd->jpegqual->cur.p_s32;
 			sd->nchg = 0;
 			new_qual += curqual;
 			if (new_qual < sd->jpegqual->minimum)
@@ -2226,7 +2226,7 @@ static void transfer_check(struct gspca_dev *gspca_dev,
 			else if (new_qual > sd->jpegqual->maximum)
 				new_qual = sd->jpegqual->maximum;
 			if (new_qual != curqual) {
-				sd->jpegqual->cur.val = new_qual;
+				*sd->jpegqual->cur.p_s32 = new_qual;
 				queue_work(sd->work_thread, &sd->work);
 			}
 		}
diff --git a/drivers/media/usb/gspca/topro.c b/drivers/media/usb/gspca/topro.c
index 640c2fe..4abe03b 100644
--- a/drivers/media/usb/gspca/topro.c
+++ b/drivers/media/usb/gspca/topro.c
@@ -3976,8 +3976,8 @@ static int sd_setgain(struct gspca_dev *gspca_dev)
 	s32 val = gspca_dev->gain->val;
 
 	if (sd->sensor == SENSOR_CX0342) {
-		s32 old = gspca_dev->gain->cur.val ?
-					gspca_dev->gain->cur.val : 1;
+		s32 old = *gspca_dev->gain->cur.p_s32 ?
+					*gspca_dev->gain->cur.p_s32 : 1;
 
 		sd->blue->val = sd->blue->val * val / old;
 		if (sd->blue->val > 4095)
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index c995439..f60b056 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -47,7 +47,7 @@ struct v4l2_ctrl_helper {
    mode. */
 static bool is_cur_manual(const struct v4l2_ctrl *master)
 {
-	return master->is_auto && master->cur.val == master->manual_mode_value;
+	return master->is_auto && *master->cur.p_s32 == master->manual_mode_value;
 }
 
 /* Same as above, but this checks the against the new value instead of the
@@ -1097,7 +1097,7 @@ static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 change
 	if (ctrl->is_ptr)
 		ev->u.ctrl.value64 = 0;
 	else
-		ev->u.ctrl.value64 = ctrl->cur.val64;
+		ev->u.ctrl.value64 = *ctrl->cur.p_s64;
 	ev->u.ctrl.minimum = ctrl->minimum;
 	ev->u.ctrl.maximum = ctrl->maximum;
 	if (ctrl->type == V4L2_CTRL_TYPE_MENU
@@ -1777,13 +1777,13 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 		return NULL;
 	}
 
-	sz_extra = sizeof(union v4l2_ctrl_ptr);
+	sz_extra = elem_size;
 	if (type == V4L2_CTRL_TYPE_BUTTON)
 		flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
 	else if (type == V4L2_CTRL_TYPE_CTRL_CLASS)
 		flags |= V4L2_CTRL_FLAG_READ_ONLY;
 	else if (type == V4L2_CTRL_TYPE_STRING || type >= V4L2_CTRL_COMPLEX_TYPES)
-		sz_extra += 2 * elem_size;
+		sz_extra += elem_size;
 
 	ctrl = kzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL);
 	if (ctrl == NULL) {
@@ -1816,7 +1816,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 	else if (type == V4L2_CTRL_TYPE_INTEGER_MENU)
 		ctrl->qmenu_int = qmenu_int;
 	ctrl->priv = priv;
-	ctrl->cur.val = ctrl->val = def;
+	ctrl->stores = &ctrl->cur;
 	data = &ctrl->stores[1];
 
 	if (ctrl->is_ptr) {
@@ -1824,7 +1824,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 		ctrl->stores[0].p = data + elem_size;
 	} else {
 		ctrl->new.p = &ctrl->val;
-		ctrl->stores[0].p = &ctrl->cur.val;
+		ctrl->stores[0].p = data;
 	}
 	for (s = -1; s <= 0; s++)
 		ctrl->type_ops->init(ctrl, ctrl->stores[s]);
@@ -3080,10 +3080,10 @@ int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
 	ctrl->maximum = max;
 	ctrl->step = step;
 	ctrl->default_value = def;
-	c.value = ctrl->cur.val;
+	c.value = *ctrl->cur.p_s32;
 	if (validate_new(ctrl, &c))
 		c.value = def;
-	if (c.value != ctrl->cur.val)
+	if (c.value != *ctrl->cur.p_s32)
 		ret = set_ctrl(NULL, ctrl, &c, V4L2_EVENT_CTRL_CH_RANGE);
 	else
 		send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE);
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index c86a071..27f0b7b 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -198,14 +198,9 @@ struct v4l2_ctrl {
 		char *string;
 		void *p;
 	};
-	union {
-		s32 val;
-		s64 val64;
-		char *string;
-		void *p;
-	} cur;
+	union v4l2_ctrl_ptr *stores;
 	union v4l2_ctrl_ptr new;
-	union v4l2_ctrl_ptr stores[];
+	union v4l2_ctrl_ptr cur;
 };
 
 /** struct v4l2_ctrl_ref - The control reference.
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 13/21] v4l2-ctrls: use 'new' to access pointer controls
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
                   ` (11 preceding siblings ...)
  2014-01-20 12:46 ` [RFCv2 PATCH 12/21] v4l2-ctrls: replace cur by a union v4l2_ctrl_ptr Hans Verkuil
@ 2014-01-20 12:46 ` Hans Verkuil
  2014-01-23 17:06   ` Sylwester Nawrocki
  2014-01-20 12:46 ` [RFCv2 PATCH 14/21] v4l2-ctrls: prepare for matrix support Hans Verkuil
                   ` (8 subsequent siblings)
  21 siblings, 1 reply; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:46 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Require that 'new' string and pointer values are accessed through the 'new'
field instead of through the union. This reduces the union to just val and
val64.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/radio/si4713/si4713.c                | 4 ++--
 drivers/media/v4l2-core/v4l2-ctrls.c               | 4 ++--
 drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c | 2 +-
 include/media/v4l2-ctrls.h                         | 2 --
 4 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/media/radio/si4713/si4713.c b/drivers/media/radio/si4713/si4713.c
index 07d5153..718e10d 100644
--- a/drivers/media/radio/si4713/si4713.c
+++ b/drivers/media/radio/si4713/si4713.c
@@ -1098,11 +1098,11 @@ static int si4713_s_ctrl(struct v4l2_ctrl *ctrl)
 
 		switch (ctrl->id) {
 		case V4L2_CID_RDS_TX_PS_NAME:
-			ret = si4713_set_rds_ps_name(sdev, ctrl->string);
+			ret = si4713_set_rds_ps_name(sdev, ctrl->new.p_char);
 			break;
 
 		case V4L2_CID_RDS_TX_RADIO_TEXT:
-			ret = si4713_set_rds_radio_text(sdev, ctrl->string);
+			ret = si4713_set_rds_radio_text(sdev, ctrl->new.p_char);
 			break;
 
 		case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index f60b056..d15a7dd 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1820,8 +1820,8 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 	data = &ctrl->stores[1];
 
 	if (ctrl->is_ptr) {
-		ctrl->p = ctrl->new.p = data;
-		ctrl->stores[0].p = data + elem_size;
+		for (s = -1; s <= 0; s++)
+			ctrl->stores[s].p = data + (s + 1) * elem_size;
 	} else {
 		ctrl->new.p = &ctrl->val;
 		ctrl->stores[0].p = data;
diff --git a/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c b/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c
index ce9e5aa..d19743b 100644
--- a/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c
+++ b/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c
@@ -1127,7 +1127,7 @@ static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
 		solo_motion_toggle(solo_enc, ctrl->val);
 		return 0;
 	case V4L2_CID_OSD_TEXT:
-		strcpy(solo_enc->osd_text, ctrl->string);
+		strcpy(solo_enc->osd_text, ctrl->new.p_char);
 		err = solo_osd_print(solo_enc);
 		return err;
 	default:
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 27f0b7b..885a261 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -195,8 +195,6 @@ struct v4l2_ctrl {
 	union {
 		s32 val;
 		s64 val64;
-		char *string;
-		void *p;
 	};
 	union v4l2_ctrl_ptr *stores;
 	union v4l2_ctrl_ptr new;
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 14/21] v4l2-ctrls: prepare for matrix support.
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
                   ` (12 preceding siblings ...)
  2014-01-20 12:46 ` [RFCv2 PATCH 13/21] v4l2-ctrls: use 'new' to access pointer controls Hans Verkuil
@ 2014-01-20 12:46 ` Hans Verkuil
  2014-01-20 12:46 ` [RFCv2 PATCH 15/21] v4l2-ctrls: type_ops can handle matrix elements Hans Verkuil
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:46 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Add core support for matrices.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 54 +++++++++++++++++++++++-------------
 include/media/v4l2-ctrls.h           |  8 ++++--
 2 files changed, 39 insertions(+), 23 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index d15a7dd..4968eff 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1123,7 +1123,7 @@ static void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes)
 			v4l2_event_queue_fh(sev->fh, &ev);
 }
 
-static bool std_equal(const struct v4l2_ctrl *ctrl,
+static bool std_equal(const struct v4l2_ctrl *ctrl, u32 idx,
 		      union v4l2_ctrl_ptr ptr1,
 		      union v4l2_ctrl_ptr ptr2)
 {
@@ -1142,7 +1142,7 @@ static bool std_equal(const struct v4l2_ctrl *ctrl,
 	}
 }
 
-static void std_init(const struct v4l2_ctrl *ctrl,
+static void std_init(const struct v4l2_ctrl *ctrl, u32 idx,
 		     union v4l2_ctrl_ptr ptr)
 {
 	switch (ctrl->type) {
@@ -1169,6 +1169,9 @@ static void std_log(const struct v4l2_ctrl *ctrl)
 {
 	union v4l2_ctrl_ptr ptr = ctrl->stores[0];
 
+	if (ctrl->is_matrix)
+		pr_cont("[%u][%u] ", ctrl->rows, ctrl->cols);
+
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_INTEGER:
 		pr_cont("%d", *ptr.p_s32);
@@ -1211,7 +1214,7 @@ static void std_log(const struct v4l2_ctrl *ctrl)
 })
 
 /* Validate a new control */
-static int std_validate(const struct v4l2_ctrl *ctrl,
+static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
 			union v4l2_ctrl_ptr ptr)
 {
 	size_t len;
@@ -1435,7 +1438,7 @@ static int cluster_changed(struct v4l2_ctrl *master)
 
 		if (ctrl == NULL)
 			continue;
-		ctrl->has_changed = !ctrl->type_ops->equal(ctrl,
+		ctrl->has_changed = !ctrl->type_ops->equal(ctrl, 0,
 						ctrl->stores[0], ctrl->new);
 		changed |= ctrl->has_changed;
 	}
@@ -1493,15 +1496,15 @@ static int validate_new(const struct v4l2_ctrl *ctrl,
 	case V4L2_CTRL_TYPE_BUTTON:
 	case V4L2_CTRL_TYPE_CTRL_CLASS:
 		ptr.p_s32 = &c->value;
-		return ctrl->type_ops->validate(ctrl, ptr);
+		return ctrl->type_ops->validate(ctrl, 0, ptr);
 
 	case V4L2_CTRL_TYPE_INTEGER64:
 		ptr.p_s64 = &c->value64;
-		return ctrl->type_ops->validate(ctrl, ptr);
+		return ctrl->type_ops->validate(ctrl, 0, ptr);
 
 	default:
 		ptr.p = c->p;
-		return ctrl->type_ops->validate(ctrl, ptr);
+		return ctrl->type_ops->validate(ctrl, 0, ptr);
 	}
 }
 
@@ -1727,7 +1730,8 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 			const s64 *qmenu_int, void *priv)
 {
 	struct v4l2_ctrl *ctrl;
-	unsigned sz_extra;
+	bool is_matrix;
+	unsigned sz_extra, tot_ctrl_size;
 	void *data;
 	int err;
 	int s;
@@ -1739,6 +1743,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 		cols = 1;
 	if (rows == 0)
 		rows = 1;
+	is_matrix = cols > 1 || rows > 1;
 
 	if (type == V4L2_CTRL_TYPE_INTEGER64)
 		elem_size = sizeof(s64);
@@ -1746,17 +1751,18 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 		elem_size = max + 1;
 	else if (type < V4L2_CTRL_COMPLEX_TYPES)
 		elem_size = sizeof(s32);
+	tot_ctrl_size = elem_size * cols * rows;
 
 	/* Sanity checks */
-	if (id == 0 || name == NULL || id >= V4L2_CID_PRIVATE_BASE ||
-	    elem_size == 0 ||
+	if (id == 0 || name == NULL || !elem_size ||
+	    id >= V4L2_CID_PRIVATE_BASE ||
 	    (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) ||
 	    (type == V4L2_CTRL_TYPE_INTEGER_MENU && qmenu_int == NULL)) {
 		handler_set_err(hdl, -ERANGE);
 		return NULL;
 	}
 	/* Complex controls are always hidden */
-	if (type >= V4L2_CTRL_COMPLEX_TYPES)
+	if (is_matrix || type >= V4L2_CTRL_COMPLEX_TYPES)
 		flags |= V4L2_CTRL_FLAG_HIDDEN;
 	/*
 	 * No hidden controls are allowed in the USER class
@@ -1776,14 +1782,21 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 		handler_set_err(hdl, -ERANGE);
 		return NULL;
 	}
+	if (is_matrix &&
+	    (type == V4L2_CTRL_TYPE_BUTTON ||
+	     type == V4L2_CTRL_TYPE_CTRL_CLASS)) {
+		handler_set_err(hdl, -EINVAL);
+		return NULL;
+	}
 
-	sz_extra = elem_size;
+	sz_extra = tot_ctrl_size;
 	if (type == V4L2_CTRL_TYPE_BUTTON)
 		flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
 	else if (type == V4L2_CTRL_TYPE_CTRL_CLASS)
 		flags |= V4L2_CTRL_FLAG_READ_ONLY;
-	else if (type == V4L2_CTRL_TYPE_STRING || type >= V4L2_CTRL_COMPLEX_TYPES)
-		sz_extra += elem_size;
+	else if (type == V4L2_CTRL_TYPE_STRING ||
+		 type >= V4L2_CTRL_COMPLEX_TYPES || is_matrix)
+		sz_extra += tot_ctrl_size;
 
 	ctrl = kzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL);
 	if (ctrl == NULL) {
@@ -1805,9 +1818,10 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 	ctrl->maximum = max;
 	ctrl->step = step;
 	ctrl->default_value = def;
-	ctrl->is_string = type == V4L2_CTRL_TYPE_STRING;
-	ctrl->is_ptr = type >= V4L2_CTRL_COMPLEX_TYPES || ctrl->is_string;
+	ctrl->is_string = !is_matrix && type == V4L2_CTRL_TYPE_STRING;
+	ctrl->is_ptr = is_matrix || type >= V4L2_CTRL_COMPLEX_TYPES || ctrl->is_string;
 	ctrl->is_int = !ctrl->is_ptr && type != V4L2_CTRL_TYPE_INTEGER64;
+	ctrl->is_matrix = is_matrix;
 	ctrl->cols = cols;
 	ctrl->rows = rows;
 	ctrl->elem_size = elem_size;
@@ -1821,13 +1835,13 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 
 	if (ctrl->is_ptr) {
 		for (s = -1; s <= 0; s++)
-			ctrl->stores[s].p = data + (s + 1) * elem_size;
+			ctrl->stores[s].p = data + (s + 1) * tot_ctrl_size;
 	} else {
 		ctrl->new.p = &ctrl->val;
 		ctrl->stores[0].p = data;
 	}
 	for (s = -1; s <= 0; s++)
-		ctrl->type_ops->init(ctrl, ctrl->stores[s]);
+		ctrl->type_ops->init(ctrl, 0, ctrl->stores[s]);
 
 	if (handler_new_ref(hdl, ctrl)) {
 		kfree(ctrl);
@@ -2724,7 +2738,7 @@ s64 v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl *ctrl)
 	struct v4l2_ext_control c;
 
 	/* It's a driver bug if this happens. */
-	WARN_ON(ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
+	WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
 	c.value = 0;
 	get_ctrl(ctrl, &c);
 	return c.value;
@@ -3034,7 +3048,7 @@ int v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)
 	struct v4l2_ext_control c;
 
 	/* It's a driver bug if this happens. */
-	WARN_ON(ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
+	WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
 	c.value64 = val;
 	return set_ctrl_lock(NULL, ctrl, &c);
 }
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 885a261..8756e47 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -74,13 +74,13 @@ struct v4l2_ctrl_ops {
   * @validate: validate the value. Return 0 on success and a negative value otherwise.
   */
 struct v4l2_ctrl_type_ops {
-	bool (*equal)(const struct v4l2_ctrl *ctrl,
+	bool (*equal)(const struct v4l2_ctrl *ctrl, u32 idx,
 		      union v4l2_ctrl_ptr ptr1,
 		      union v4l2_ctrl_ptr ptr2);
-	void (*init)(const struct v4l2_ctrl *ctrl,
+	void (*init)(const struct v4l2_ctrl *ctrl, u32 idx,
 		     union v4l2_ctrl_ptr ptr);
 	void (*log)(const struct v4l2_ctrl *ctrl);
-	int (*validate)(const struct v4l2_ctrl *ctrl,
+	int (*validate)(const struct v4l2_ctrl *ctrl, u32 idx,
 			union v4l2_ctrl_ptr ptr);
 };
 
@@ -111,6 +111,7 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
   * @is_ptr:	If set, then this control is a matrix and/or has type >= V4L2_CTRL_COMPLEX_TYPES
   *		and/or has type V4L2_CTRL_TYPE_STRING. In other words, struct
   *		v4l2_ext_control uses field p to point to the data.
+  * @is_matrix: If set, then this control contains a matrix.
   * @has_volatiles: If set, then one or more members of the cluster are volatile.
   *		Drivers should never touch this flag.
   * @call_notify: If set, then call the handler's notify function whenever the
@@ -169,6 +170,7 @@ struct v4l2_ctrl {
 	unsigned int is_int:1;
 	unsigned int is_string:1;
 	unsigned int is_ptr:1;
+	unsigned int is_matrix:1;
 	unsigned int has_volatiles:1;
 	unsigned int call_notify:1;
 	unsigned int manual_mode_value:8;
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 15/21] v4l2-ctrls: type_ops can handle matrix elements.
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
                   ` (13 preceding siblings ...)
  2014-01-20 12:46 ` [RFCv2 PATCH 14/21] v4l2-ctrls: prepare for matrix support Hans Verkuil
@ 2014-01-20 12:46 ` Hans Verkuil
  2014-01-20 12:46 ` [RFCv2 PATCH 16/21] v4l2-ctrls: add matrix support Hans Verkuil
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:46 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Extend the control type operations to handle matrix elements.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 40 ++++++++++++++++++++----------------
 1 file changed, 22 insertions(+), 18 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 4968eff..913ea7c 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1131,14 +1131,16 @@ static bool std_equal(const struct v4l2_ctrl *ctrl, u32 idx,
 	case V4L2_CTRL_TYPE_BUTTON:
 		return false;
 	case V4L2_CTRL_TYPE_STRING:
+		idx *= ctrl->elem_size;
 		/* strings are always 0-terminated */
-		return !strcmp(ptr1.p_char, ptr2.p_char);
+		return !strcmp(ptr1.p_char + idx, ptr2.p_char + idx);
 	case V4L2_CTRL_TYPE_INTEGER64:
-		return *ptr1.p_s64 == *ptr2.p_s64;
+		return ptr1.p_s64[idx] == ptr2.p_s64[idx];
 	default:
-		if (ctrl->is_ptr)
-			return !memcmp(ptr1.p, ptr2.p, ctrl->elem_size);
-		return *ptr1.p_s32 == *ptr2.p_s32;
+		if (ctrl->is_int)
+			return ptr1.p_s32[idx] == ptr2.p_s32[idx];
+		idx *= ctrl->elem_size;
+		return !memcmp(ptr1.p + idx, ptr2.p + idx, ctrl->elem_size);
 	}
 }
 
@@ -1147,18 +1149,19 @@ static void std_init(const struct v4l2_ctrl *ctrl, u32 idx,
 {
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_STRING:
-		memset(ptr.p_char, ' ', ctrl->minimum);
-		ptr.p_char[ctrl->minimum] = '\0';
+		idx *= ctrl->elem_size;
+		memset(ptr.p_char + idx, ' ', ctrl->minimum);
+		ptr.p_char[idx + ctrl->minimum] = '\0';
 		break;
 	case V4L2_CTRL_TYPE_INTEGER64:
-		*ptr.p_s64 = ctrl->default_value;
+		ptr.p_s64[idx] = ctrl->default_value;
 		break;
 	case V4L2_CTRL_TYPE_INTEGER:
 	case V4L2_CTRL_TYPE_INTEGER_MENU:
 	case V4L2_CTRL_TYPE_MENU:
 	case V4L2_CTRL_TYPE_BITMASK:
 	case V4L2_CTRL_TYPE_BOOLEAN:
-		*ptr.p_s32 = ctrl->default_value;
+		ptr.p_s32[idx] = ctrl->default_value;
 		break;
 	default:
 		break;
@@ -1221,36 +1224,37 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
 
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_INTEGER:
-		return ROUND_TO_RANGE(*ptr.p_s32, u32, ctrl);
+		return ROUND_TO_RANGE(ptr.p_s32[idx], u32, ctrl);
 	case V4L2_CTRL_TYPE_INTEGER64:
-		return ROUND_TO_RANGE(*ptr.p_s64, u64, ctrl);
+		return ROUND_TO_RANGE(ptr.p_s64[idx], u64, ctrl);
 
 	case V4L2_CTRL_TYPE_BOOLEAN:
-		*ptr.p_s32 = !!*ptr.p_s32;
+		ptr.p_s32[idx] = !!ptr.p_s32[idx];
 		return 0;
 
 	case V4L2_CTRL_TYPE_MENU:
 	case V4L2_CTRL_TYPE_INTEGER_MENU:
-		if (*ptr.p_s32 < ctrl->minimum || *ptr.p_s32 > ctrl->maximum)
+		if (ptr.p_s32[idx] < ctrl->minimum || ptr.p_s32[idx] > ctrl->maximum)
 			return -ERANGE;
-		if (ctrl->menu_skip_mask & (1 << *ptr.p_s32))
+		if (ctrl->menu_skip_mask & (1 << ptr.p_s32[idx]))
 			return -EINVAL;
 		if (ctrl->type == V4L2_CTRL_TYPE_MENU &&
-		    ctrl->qmenu[*ptr.p_s32][0] == '\0')
+		    ctrl->qmenu[ptr.p_s32[idx]][0] == '\0')
 			return -EINVAL;
 		return 0;
 
 	case V4L2_CTRL_TYPE_BITMASK:
-		*ptr.p_s32 &= ctrl->maximum;
+		ptr.p_s32[idx] &= ctrl->maximum;
 		return 0;
 
 	case V4L2_CTRL_TYPE_BUTTON:
 	case V4L2_CTRL_TYPE_CTRL_CLASS:
-		*ptr.p_s32 = 0;
+		ptr.p_s32[idx] = 0;
 		return 0;
 
 	case V4L2_CTRL_TYPE_STRING:
-		len = strlen(ptr.p_char);
+		idx *= ctrl->elem_size;
+		len = strlen(ptr.p_char + idx);
 		if (len < ctrl->minimum)
 			return -ERANGE;
 		if ((len - ctrl->minimum) % ctrl->step)
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 16/21] v4l2-ctrls: add matrix support.
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
                   ` (14 preceding siblings ...)
  2014-01-20 12:46 ` [RFCv2 PATCH 15/21] v4l2-ctrls: type_ops can handle matrix elements Hans Verkuil
@ 2014-01-20 12:46 ` Hans Verkuil
  2014-01-20 12:46 ` [RFCv2 PATCH 17/21] v4l2-ctrls.c: return elem_size instead of strlen Hans Verkuil
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:46 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Finish the userspace-facing matrix support.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 106 ++++++++++++++++++++---------------
 1 file changed, 61 insertions(+), 45 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 913ea7c..0559c1b 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1164,6 +1164,8 @@ static void std_init(const struct v4l2_ctrl *ctrl, u32 idx,
 		ptr.p_s32[idx] = ctrl->default_value;
 		break;
 	default:
+		idx *= ctrl->elem_size;
+		memset(ptr.p + idx, 0, ctrl->elem_size);
 		break;
 	}
 }
@@ -1281,7 +1283,7 @@ static int ptr_to_user(struct v4l2_ext_control *c,
 	u32 len;
 
 	if (ctrl->is_ptr && !ctrl->is_string)
-		return copy_to_user(c->p, ptr.p, ctrl->elem_size);
+		return copy_to_user(c->p, ptr.p, c->size);
 
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_STRING:
@@ -1325,8 +1327,17 @@ static int user_to_ptr(struct v4l2_ext_control *c,
 	u32 size;
 
 	ctrl->is_new = 1;
-	if (ctrl->is_ptr && !ctrl->is_string)
-		return copy_from_user(ptr.p, c->p, ctrl->elem_size);
+	if (ctrl->is_ptr && !ctrl->is_string) {
+		unsigned idx;
+
+		ret = copy_from_user(ptr.p, c->p, c->size);
+		if (ret || !ctrl->is_matrix)
+			return ret;
+		for (idx = c->size / ctrl->elem_size;
+		     idx < ctrl->rows * ctrl->cols; idx++)
+			ctrl->type_ops->init(ctrl, idx, ptr);
+		return 0;
+	}
 
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_INTEGER64:
@@ -1369,21 +1380,7 @@ static void ptr_to_ptr(struct v4l2_ctrl *ctrl,
 {
 	if (ctrl == NULL)
 		return;
-	switch (ctrl->type) {
-	case V4L2_CTRL_TYPE_STRING:
-		/* strings are always 0-terminated */
-		strcpy(to.p_char, from.p_char);
-		break;
-	case V4L2_CTRL_TYPE_INTEGER64:
-		*to.p_s64 = *from.p_s64;
-		break;
-	default:
-		if (ctrl->is_ptr)
-			memcpy(to.p, from.p, ctrl->elem_size);
-		else
-			*to.p_s32 = *from.p_s32;
-		break;
-	}
+	memcpy(to.p, from.p, ctrl->rows * ctrl->cols * ctrl->elem_size);
 }
 
 /* Copy the new value to the current value. */
@@ -1435,15 +1432,19 @@ static void cur_to_new(struct v4l2_ctrl *ctrl)
 static int cluster_changed(struct v4l2_ctrl *master)
 {
 	bool changed = false;
+	unsigned idx;
 	int i;
 
 	for (i = 0; i < master->ncontrols; i++) {
 		struct v4l2_ctrl *ctrl = master->cluster[i];
+		bool ctrl_changed = false;
 
 		if (ctrl == NULL)
 			continue;
-		ctrl->has_changed = !ctrl->type_ops->equal(ctrl, 0,
+		for (idx = 0; idx < ctrl->rows * ctrl->cols; idx++)
+			ctrl_changed |= !ctrl->type_ops->equal(ctrl, idx,
 						ctrl->stores[0], ctrl->new);
+		ctrl->has_changed = ctrl_changed;
 		changed |= ctrl->has_changed;
 	}
 	return changed;
@@ -1490,26 +1491,32 @@ static int validate_new(const struct v4l2_ctrl *ctrl,
 			struct v4l2_ext_control *c)
 {
 	union v4l2_ctrl_ptr ptr;
-
-	switch (ctrl->type) {
-	case V4L2_CTRL_TYPE_INTEGER:
-	case V4L2_CTRL_TYPE_INTEGER_MENU:
-	case V4L2_CTRL_TYPE_MENU:
-	case V4L2_CTRL_TYPE_BITMASK:
-	case V4L2_CTRL_TYPE_BOOLEAN:
-	case V4L2_CTRL_TYPE_BUTTON:
-	case V4L2_CTRL_TYPE_CTRL_CLASS:
-		ptr.p_s32 = &c->value;
-		return ctrl->type_ops->validate(ctrl, 0, ptr);
-
-	case V4L2_CTRL_TYPE_INTEGER64:
-		ptr.p_s64 = &c->value64;
-		return ctrl->type_ops->validate(ctrl, 0, ptr);
-
-	default:
-		ptr.p = c->p;
-		return ctrl->type_ops->validate(ctrl, 0, ptr);
+	unsigned idx;
+	int err = 0;
+
+	if (!ctrl->is_ptr) {
+		switch (ctrl->type) {
+		case V4L2_CTRL_TYPE_INTEGER:
+		case V4L2_CTRL_TYPE_INTEGER_MENU:
+		case V4L2_CTRL_TYPE_MENU:
+		case V4L2_CTRL_TYPE_BITMASK:
+		case V4L2_CTRL_TYPE_BOOLEAN:
+		case V4L2_CTRL_TYPE_BUTTON:
+		case V4L2_CTRL_TYPE_CTRL_CLASS:
+			ptr.p_s32 = &c->value;
+			return ctrl->type_ops->validate(ctrl, 0, ptr);
+
+		case V4L2_CTRL_TYPE_INTEGER64:
+			ptr.p_s64 = &c->value64;
+			return ctrl->type_ops->validate(ctrl, 0, ptr);
+		default:
+			break;
+		}
 	}
+	ptr.p = c->p;
+	for (idx = 0; !err && idx < c->size / ctrl->elem_size; idx++)
+		err = ctrl->type_ops->validate(ctrl, idx, ptr);
+	return err;
 }
 
 static inline u32 node2id(struct list_head *node)
@@ -1736,6 +1743,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 	struct v4l2_ctrl *ctrl;
 	bool is_matrix;
 	unsigned sz_extra, tot_ctrl_size;
+	unsigned idx;
 	void *data;
 	int err;
 	int s;
@@ -1845,7 +1853,8 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 		ctrl->stores[0].p = data;
 	}
 	for (s = -1; s <= 0; s++)
-		ctrl->type_ops->init(ctrl, 0, ctrl->stores[s]);
+		for (idx = 0; idx < rows * cols; idx++)
+			ctrl->type_ops->init(ctrl, idx, ctrl->stores[s]);
 
 	if (handler_new_ref(hdl, ctrl)) {
 		kfree(ctrl);
@@ -2532,12 +2541,16 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
 			have_clusters = true;
 		if (ctrl->cluster[0] != ctrl)
 			ref = find_ref_lock(hdl, ctrl->cluster[0]->id);
-		if (ctrl->is_ptr && !ctrl->is_string && c->size < ctrl->elem_size) {
-			if (get) {
-				c->size = ctrl->elem_size;
-				return -ENOSPC;
+		if (ctrl->is_ptr && !ctrl->is_string) {
+			if (c->size == 0 || c->size % ctrl->elem_size) {
+				if (get) {
+					c->size = ctrl->rows * ctrl->cols * ctrl->elem_size;
+					return -ENOSPC;
+				}
+				return -EFAULT;
 			}
-			return -EFAULT;
+			if (c->size > ctrl->rows * ctrl->cols * ctrl->elem_size)
+				c->size = ctrl->rows * ctrl->cols * ctrl->elem_size;
 		}
 		/* Store the ref to the master control of the cluster */
 		h->mref = ref;
@@ -3077,7 +3090,7 @@ EXPORT_SYMBOL(v4l2_ctrl_notify);
 int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
 			s64 min, s64 max, u64 step, s64 def)
 {
-	int ret = check_range(ctrl->type, min, max, step, def);
+	int ret;
 	struct v4l2_ext_control c;
 
 	switch (ctrl->type) {
@@ -3087,6 +3100,9 @@ int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
 	case V4L2_CTRL_TYPE_MENU:
 	case V4L2_CTRL_TYPE_INTEGER_MENU:
 	case V4L2_CTRL_TYPE_BITMASK:
+		if (ctrl->is_matrix)
+			return -EINVAL;
+		ret = check_range(ctrl->type, min, max, step, def);
 		if (ret)
 			return ret;
 		break;
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 17/21] v4l2-ctrls.c: return elem_size instead of strlen
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
                   ` (15 preceding siblings ...)
  2014-01-20 12:46 ` [RFCv2 PATCH 16/21] v4l2-ctrls: add matrix support Hans Verkuil
@ 2014-01-20 12:46 ` Hans Verkuil
  2014-01-23 13:46   ` Sylwester Nawrocki
  2014-01-20 12:46 ` [RFCv2 PATCH 18/21] DocBook media: document VIDIOC_QUERY_EXT_CTRL Hans Verkuil
                   ` (4 subsequent siblings)
  21 siblings, 1 reply; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:46 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

When getting a string and the size given by the application is too
short return the max length the string can have (elem_size) instead
of the string length + 1. That makes more sense.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 0559c1b..a226b5d 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1289,7 +1289,7 @@ static int ptr_to_user(struct v4l2_ext_control *c,
 	case V4L2_CTRL_TYPE_STRING:
 		len = strlen(ptr.p_char);
 		if (c->size < len + 1) {
-			c->size = len + 1;
+			c->size = ctrl->elem_size;
 			return -ENOSPC;
 		}
 		return copy_to_user(c->string, ptr.p_char, len + 1) ?
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 18/21] DocBook media: document VIDIOC_QUERY_EXT_CTRL.
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
                   ` (16 preceding siblings ...)
  2014-01-20 12:46 ` [RFCv2 PATCH 17/21] v4l2-ctrls.c: return elem_size instead of strlen Hans Verkuil
@ 2014-01-20 12:46 ` Hans Verkuil
  2014-01-23 17:24   ` Sylwester Nawrocki
  2014-01-20 12:46 ` [RFCv2 PATCH 19/21] DocBook media: update VIDIOC_G/S/TRY_EXT_CTRLS Hans Verkuil
                   ` (3 subsequent siblings)
  21 siblings, 1 reply; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:46 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 .../DocBook/media/v4l/vidioc-queryctrl.xml         | 223 +++++++++++++++++----
 1 file changed, 189 insertions(+), 34 deletions(-)

diff --git a/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml b/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
index e6645b9..5e93c30 100644
--- a/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
@@ -1,11 +1,12 @@
 <refentry id="vidioc-queryctrl">
   <refmeta>
-    <refentrytitle>ioctl VIDIOC_QUERYCTRL, VIDIOC_QUERYMENU</refentrytitle>
+    <refentrytitle>ioctl VIDIOC_QUERYCTRL, VIDIOC_QUERY_EXT_CTRL, VIDIOC_QUERYMENU</refentrytitle>
     &manvol;
   </refmeta>
 
   <refnamediv>
     <refname>VIDIOC_QUERYCTRL</refname>
+    <refname>VIDIOC_QUERY_EXT_CTRL</refname>
     <refname>VIDIOC_QUERYMENU</refname>
     <refpurpose>Enumerate controls and menu control items</refpurpose>
   </refnamediv>
@@ -24,6 +25,14 @@
 	<funcdef>int <function>ioctl</function></funcdef>
 	<paramdef>int <parameter>fd</parameter></paramdef>
 	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct v4l2_query_ext_ctrl *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
 	<paramdef>struct v4l2_querymenu *<parameter>argp</parameter></paramdef>
       </funcprototype>
     </funcsynopsis>
@@ -42,7 +51,7 @@
       <varlistentry>
 	<term><parameter>request</parameter></term>
 	<listitem>
-	  <para>VIDIOC_QUERYCTRL, VIDIOC_QUERYMENU</para>
+	  <para>VIDIOC_QUERYCTRL, VIDIOC_QUERY_EXT_CTRL, VIDIOC_QUERYMENU</para>
 	</listitem>
       </varlistentry>
       <varlistentry>
@@ -91,7 +100,26 @@ prematurely end the enumeration).</para></footnote></para>
 <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> the driver returns the
 next supported control, or <errorcode>EINVAL</errorcode> if there is
 none. Drivers which do not support this flag yet always return
-<errorcode>EINVAL</errorcode>.</para>
+<errorcode>EINVAL</errorcode>. Hidden controls (i.e. controls
+with the <constant>V4L2_CTRL_FLAG_HIDDEN</constant> flag set) are
+skipped when using the <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant>
+flag. Use the <constant>VIDIOC_QUERY_EXT_CTRL</constant> for that.</para>
+
+    <para>The <constant>VIDIOC_QUERY_EXT_CTRL</constant> ioctl was
+introduced in order to better support controls that can use complex
+types, and to expose addition control information that cannot be
+returned in &v4l2-queryctrl; since that structure is full.</para>
+
+    <para><constant>VIDIOC_QUERY_EXT_CTRL</constant> is used in the
+same way as <constant>VIDIOC_QUERYCTRL</constant>, except that the
+<structfield>reserved</structfield> array must be zeroed as well.
+In addition, the <constant>V4L2_CTRL_FLAG_NEXT_HIDDEN</constant> flag
+can be specified to enumerate all hidden controls (i.e. controls
+with the <constant>V4L2_CTRL_FLAG_HIDDEN</constant> flag set which
+includes all controls with complex types). Specify both
+<constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> and
+<constant>V4L2_CTRL_FLAG_NEXT_HIDDEN</constant> in order to enumerate
+all controls, hidden or not.</para>
 
     <para>Additional information is required for menu controls: the
 names of the menu items. To query them applications set the
@@ -142,38 +170,23 @@ string. This information is intended for the user.</entry>
 	    <entry>__s32</entry>
 	    <entry><structfield>minimum</structfield></entry>
 	    <entry>Minimum value, inclusive. This field gives a lower
-bound for <constant>V4L2_CTRL_TYPE_INTEGER</constant> controls and the
-lowest valid index for <constant>V4L2_CTRL_TYPE_MENU</constant> controls.
-For <constant>V4L2_CTRL_TYPE_STRING</constant> controls the minimum value
-gives the minimum length of the string. This length <emphasis>does not include the terminating
-zero</emphasis>. It may not be valid for any other type of control, including
-<constant>V4L2_CTRL_TYPE_INTEGER64</constant> controls. Note that this is a
-signed value.</entry>
+bound for the control. See &v4l2-ctrl-type; how the minimum value is to
+be used for each possible control type. Note that this a signed 32-bit value.</entry>
 	  </row>
 	  <row>
 	    <entry>__s32</entry>
 	    <entry><structfield>maximum</structfield></entry>
 	    <entry>Maximum value, inclusive. This field gives an upper
-bound for <constant>V4L2_CTRL_TYPE_INTEGER</constant> controls and the
-highest valid index for <constant>V4L2_CTRL_TYPE_MENU</constant>
-controls. For <constant>V4L2_CTRL_TYPE_BITMASK</constant> controls it is the
-set of usable bits.
-For <constant>V4L2_CTRL_TYPE_STRING</constant> controls the maximum value
-gives the maximum length of the string. This length <emphasis>does not include the terminating
-zero</emphasis>. It may not be valid for any other type of control, including
-<constant>V4L2_CTRL_TYPE_INTEGER64</constant> controls. Note that this is a
-signed value.</entry>
+bound for the control. See &v4l2-ctrl-type; how the maximum value is to
+be used for each possible control type. Note that this a signed 32-bit value.</entry>
 	  </row>
 	  <row>
 	    <entry>__s32</entry>
 	    <entry><structfield>step</structfield></entry>
-	    <entry><para>This field gives a step size for
-<constant>V4L2_CTRL_TYPE_INTEGER</constant> controls. For
-<constant>V4L2_CTRL_TYPE_STRING</constant> controls this field refers to
-the string length that has to be a multiple of this step size.
-It may not be valid for any other type of control, including
-<constant>V4L2_CTRL_TYPE_INTEGER64</constant>
-controls.</para><para>Generally drivers should not scale hardware
+	    <entry><para>This field gives a step size for the control.
+See &v4l2-ctrl-type; how the step value is to be used for each possible
+control type. Note that this an unsigned 32-bit value.
+</para><para>Generally drivers should not scale hardware
 control values. It may be necessary for example when the
 <structfield>name</structfield> or <structfield>id</structfield> imply
 a particular unit and the hardware actually accepts only multiples of
@@ -192,10 +205,11 @@ be always positive.</para></entry>
 	    <entry><structfield>default_value</structfield></entry>
 	    <entry>The default value of a
 <constant>V4L2_CTRL_TYPE_INTEGER</constant>,
-<constant>_BOOLEAN</constant> or <constant>_MENU</constant> control.
-Not valid for other types of controls. Drivers reset controls only
-when the driver is loaded, not later, in particular not when the
-func-open; is called.</entry>
+<constant>_BOOLEAN</constant>, <constant>_BITMASK</constant>,
+<constant>_MENU</constant> or <constant>_INTEGER_MENU</constant> control.
+Not valid for other types of controls.
+Note that drivers reset controls to their default value only when the
+driver is first loaded, never afterwards.</entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
@@ -213,6 +227,129 @@ the array to zero.</entry>
       </tgroup>
     </table>
 
+    <table pgwide="1" frame="none" id="v4l2-query-ext-ctrl">
+      <title>struct <structname>v4l2_query_ext_ctrl</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>id</structfield></entry>
+	    <entry>Identifies the control, set by the application. See
+<xref linkend="control-id" /> for predefined IDs. When the ID is ORed
+with <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> the driver clears the
+flag and returns the first non-hidden control with a higher ID. When the
+ID is ORed with <constant>V4L2_CTRL_FLAG_NEXT_HIDDEN</constant> the driver
+clears the flag and returns the first hidden control with a higher ID.
+Set both to get the first control (hidden or not) with a higher ID.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>type</structfield></entry>
+	    <entry>Type of control, see <xref
+		linkend="v4l2-ctrl-type" />.</entry>
+	  </row>
+	  <row>
+	    <entry>char</entry>
+	    <entry><structfield>name</structfield>[32]</entry>
+	    <entry>Name of the control, a NUL-terminated ASCII
+string. This information is intended for the user.</entry>
+	  </row>
+	  <row>
+	    <entry>char</entry>
+	    <entry><structfield>unit</structfield>[32]</entry>
+	    <entry>The name of the unit of the control's value, a NUL-terminated ASCII
+string. This information is intended for the user. This may be an empty string if no
+unit is known or if it is not applicable to this particular control.</entry>
+	  </row>
+	  <row>
+	    <entry>__s64</entry>
+	    <entry><structfield>minimum</structfield></entry>
+	    <entry>Minimum value, inclusive. This field gives a lower
+bound for the control. See &v4l2-ctrl-type; how the minimum value is to
+be used for each possible control type. Note that this a signed 64-bit value.</entry>
+	  </row>
+	  <row>
+	    <entry>__s64</entry>
+	    <entry><structfield>maximum</structfield></entry>
+	    <entry>Maximum value, inclusive. This field gives an upper
+bound for the control. See &v4l2-ctrl-type; how the maximum value is to
+be used for each possible control type. Note that this a signed 64-bit value.</entry>
+	  </row>
+	  <row>
+	    <entry>__u64</entry>
+	    <entry><structfield>step</structfield></entry>
+	    <entry><para>This field gives a step size for the control.
+See &v4l2-ctrl-type; how the step value is to be used for each possible
+control type. Note that this an unsigned 64-bit value.
+</para><para>Generally drivers should not scale hardware
+control values. It may be necessary for example when the
+<structfield>name</structfield> or <structfield>id</structfield> imply
+a particular unit and the hardware actually accepts only multiples of
+said unit. If so, drivers must take care values are properly rounded
+when scaling, such that errors will not accumulate on repeated
+read-write cycles.</para><para>This field gives the smallest change of
+an integer control actually affecting hardware. Often the information
+is needed when the user can change controls by keyboard or GUI
+buttons, rather than a slider. When for example a hardware register
+accepts values 0-511 and the driver reports 0-65535, step should be
+128.</para></entry>
+	  </row>
+	  <row>
+	    <entry>__s64</entry>
+	    <entry><structfield>default_value</structfield></entry>
+	    <entry>The default value of a
+<constant>V4L2_CTRL_TYPE_INTEGER</constant>, <constant>_INTEGER64</constant>,
+<constant>_BOOLEAN</constant>, <constant>_BITMASK</constant>,
+<constant>_MENU</constant> or <constant>_INTEGER_MENU</constant> control.
+Not valid for other types of controls.
+Note that drivers reset controls to their default value only when the
+driver is first loaded, never afterwards.
+</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>flags</structfield></entry>
+	    <entry>Control flags, see <xref
+		linkend="control-flags" />.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>cols</structfield></entry>
+	    <entry>The number of columns in the matrix. If this control
+is not a matrix, then both <structfield>cols</structfield> and
+<structfield>rows</structfield> are 1. <structfield>cols</structfield>
+can never be 0.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>rows</structfield></entry>
+	    <entry>The number of rows in the matrix. If this control
+is not a matrix, then both <structfield>cols</structfield> and
+<structfield>rows</structfield> are 1. <structfield>rows</structfield>
+can never be 0.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>elem_size</structfield></entry>
+	    <entry>The size in bytes of a single element of the matrix.
+Given a char pointer <constant>p</constant> to the matrix you can find the
+position of cell <constant>(y, x)</constant> as follows:
+<constant>p + (y * cols + x) * elem_size</constant>. <structfield>elem_size</structfield>
+is always valid, also when the control isn't a matrix. For string controls
+<structfield>elem_size</structfield> is equal to <structfield>maximum + 1</structfield>.
+</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[17]</entry>
+	    <entry>Reserved for future extensions. Applications and drivers
+must set the array to zero.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
     <table pgwide="1" frame="none" id="v4l2-querymenu">
       <title>struct <structname>v4l2_querymenu</structname></title>
       <tgroup cols="4">
@@ -347,11 +484,14 @@ Drivers must ignore the value passed with
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_CTRL_TYPE_INTEGER64</constant></entry>
-	    <entry>n/a</entry>
-	    <entry>n/a</entry>
-	    <entry>n/a</entry>
+	    <entry>any</entry>
+	    <entry>any</entry>
+	    <entry>any</entry>
 	    <entry>A 64-bit integer valued control. Minimum, maximum
-and step size cannot be queried.</entry>
+and step size cannot be queried using <constant>VIDIOC_QUERYCTRL</constant>.
+Only <constant>VIDIOC_QUERY_EXT_CTRL</constant> can retrieve the 64-bit
+min/max/step values, they should be interpreted as n/a when using
+<constant>VIDIOC_QUERYCTRL</constant>.</entry>
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_CTRL_TYPE_STRING</constant></entry>
@@ -450,6 +590,21 @@ is in auto-gain mode. In such a case the hardware calculates the gain value base
 the lighting conditions which can change over time. Note that setting a new value for
 a volatile control will have no effect. The new value will just be ignored.</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_CTRL_FLAG_HIDDEN</constant></entry>
+	    <entry>0x0100</entry>
+	    <entry>This control is hidden and should not be shown in a GUI application.
+Hidden controls are skipped when enumerating them using <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant>,
+and they can only be enumerated by using the <constant>V4L2_CTRL_FLAG_NEXT_HIDDEN</constant>
+flag. All controls that have a complex type have this flag set.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_CTRL_FLAG_IS_PTR</constant></entry>
+	    <entry>0x0200</entry>
+	    <entry>This control has a pointer type, so its value has to be accessed
+using one of the pointer fields of &v4l2-ext-control;. This flag is set for controls
+that are a matrix, string, or have a complex type.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 19/21] DocBook media: update VIDIOC_G/S/TRY_EXT_CTRLS.
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
                   ` (17 preceding siblings ...)
  2014-01-20 12:46 ` [RFCv2 PATCH 18/21] DocBook media: document VIDIOC_QUERY_EXT_CTRL Hans Verkuil
@ 2014-01-20 12:46 ` Hans Verkuil
  2014-01-23 13:46   ` Sylwester Nawrocki
  2014-01-20 12:46 ` [RFCv2 PATCH 20/21] DocBook media: update control section Hans Verkuil
                   ` (2 subsequent siblings)
  21 siblings, 1 reply; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:46 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 .../DocBook/media/v4l/vidioc-g-ext-ctrls.xml       | 43 ++++++++++++++++++----
 1 file changed, 35 insertions(+), 8 deletions(-)

diff --git a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
index b3bb957..bb383b9 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
@@ -72,23 +72,30 @@ initialize the <structfield>id</structfield>,
 <structfield>size</structfield> and <structfield>reserved2</structfield> fields
 of each &v4l2-ext-control; and call the
 <constant>VIDIOC_G_EXT_CTRLS</constant> ioctl. String controls controls
-must also set the <structfield>string</structfield> field.</para>
+must also set the <structfield>string</structfield> field. Controls
+of complex types (<constant>V4L2_CTRL_FLAG_IS_PTR</constant> is set)
+must set the <structfield>p</structfield> field.</para>
 
     <para>If the <structfield>size</structfield> is too small to
 receive the control result (only relevant for pointer-type controls
 like strings), then the driver will set <structfield>size</structfield>
 to a valid value and return an &ENOSPC;. You should re-allocate the
-string memory to this new size and try again. It is possible that the
-same issue occurs again if the string has grown in the meantime. It is
+memory to this new size and try again. For the string type it is possible that
+the same issue occurs again if the string has grown in the meantime. It is
 recommended to call &VIDIOC-QUERYCTRL; first and use
 <structfield>maximum</structfield>+1 as the new <structfield>size</structfield>
 value. It is guaranteed that that is sufficient memory.
 </para>
 
+    <para>For matrices it is possible to only get the first <constant>X</constant>
+elements by setting size to <constant>X * elem_size</constant>, where
+<structfield>elem_size</structfield> is obtained by calling &VIDIOC-QUERY-EXT-CTRL;.
+Matrix elements are returned row-by-row.</para>
+
     <para>To change the value of a set of controls applications
 initialize the <structfield>id</structfield>, <structfield>size</structfield>,
 <structfield>reserved2</structfield> and
-<structfield>value/string</structfield> fields of each &v4l2-ext-control; and
+<structfield>value/value64/string/p</structfield> fields of each &v4l2-ext-control; and
 call the <constant>VIDIOC_S_EXT_CTRLS</constant> ioctl. The controls
 will only be set if <emphasis>all</emphasis> control values are
 valid.</para>
@@ -96,11 +103,17 @@ valid.</para>
     <para>To check if a set of controls have correct values applications
 initialize the <structfield>id</structfield>, <structfield>size</structfield>,
 <structfield>reserved2</structfield> and
-<structfield>value/string</structfield> fields of each &v4l2-ext-control; and
+<structfield>value/value64/string/p</structfield> fields of each &v4l2-ext-control; and
 call the <constant>VIDIOC_TRY_EXT_CTRLS</constant> ioctl. It is up to
 the driver whether wrong values are automatically adjusted to a valid
 value or if an error is returned.</para>
 
+    <para>For matrices it is possible to only set or check only the first
+<constant>X</constant> elements by setting size to <constant>X * elem_size</constant>,
+where <structfield>elem_size</structfield> is obtained by calling &VIDIOC-QUERY-EXT-CTRL;.
+Matrix elements are set row-by-row. Matrix elements that are not explicitly
+set will be initialized to their default value.</para>
+
     <para>When the <structfield>id</structfield> or
 <structfield>ctrl_class</structfield> is invalid drivers return an
 &EINVAL;. When the value is out of bounds drivers can choose to take
@@ -158,19 +171,33 @@ applications must set the array to zero.</entry>
 	    <entry></entry>
 	    <entry>__s32</entry>
 	    <entry><structfield>value</structfield></entry>
-	    <entry>New value or current value.</entry>
+	    <entry>New value or current value. Valid if this control is not of
+type <constant>V4L2_CTRL_TYPE_INTEGER64</constant> and
+<constant>V4L2_CTRL_FLAG_IS_PTR</constant> is not set.</entry>
 	  </row>
 	  <row>
 	    <entry></entry>
 	    <entry>__s64</entry>
 	    <entry><structfield>value64</structfield></entry>
-	    <entry>New value or current value.</entry>
+	    <entry>New value or current value. Valid if this control is of
+type <constant>V4L2_CTRL_TYPE_INTEGER64</constant> and
+<constant>V4L2_CTRL_FLAG_IS_PTR</constant> is not set.</entry>
 	  </row>
 	  <row>
 	    <entry></entry>
 	    <entry>char *</entry>
 	    <entry><structfield>string</structfield></entry>
-	    <entry>A pointer to a string.</entry>
+	    <entry>A pointer to a string. Valid if this control is of
+type <constant>V4L2_CTRL_TYPE_STRING</constant>.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>void *</entry>
+	    <entry><structfield>p</structfield></entry>
+	    <entry>A pointer to a complex type which can be a matrix and/or a
+complex type (the control's type is >= <constant>V4L2_CTRL_COMPLEX_TYPES</constant>).
+Valid if <constant>V4L2_CTRL_FLAG_IS_PTR</constant> is set for this control.
+</entry>
 	  </row>
 	</tbody>
       </tgroup>
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 20/21] DocBook media: update control section.
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
                   ` (18 preceding siblings ...)
  2014-01-20 12:46 ` [RFCv2 PATCH 19/21] DocBook media: update VIDIOC_G/S/TRY_EXT_CTRLS Hans Verkuil
@ 2014-01-20 12:46 ` Hans Verkuil
  2014-01-23 15:34   ` Sylwester Nawrocki
  2014-01-20 12:46 ` [RFCv2 PATCH 21/21] v4l2-controls.txt: update to the new way of accessing controls Hans Verkuil
  2014-01-22 22:44 ` [RFCv2 PATCH 00/21] Add support for complex controls Sylwester Nawrocki
  21 siblings, 1 reply; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:46 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Document the support for complex types in controls.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 Documentation/DocBook/media/v4l/controls.xml | 185 +++++++++++++++++----------
 1 file changed, 118 insertions(+), 67 deletions(-)

diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index a5a3188..85d78d4 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -13,6 +13,19 @@ correctly with any device.</para>
     <para>All controls are accessed using an ID value. V4L2 defines
 several IDs for specific purposes. Drivers can also implement their
 own custom controls using <constant>V4L2_CID_PRIVATE_BASE</constant>
+<footnote><para>The use of <constant>V4L2_CID_PRIVATE_BASE</constant>
+is problematic because different drivers may use the same
+<constant>V4L2_CID_PRIVATE_BASE</constant> ID for different controls.
+This makes it hard to programatically set such controls since the meaning
+of the control with that ID is driver dependent. In order to resolve this
+drivers use unique IDs and the <constant>V4L2_CID_PRIVATE_BASE</constant>
+IDs are mapped to those unique IDs by the kernel. Consider these
+<constant>V4L2_CID_PRIVATE_BASE</constant> IDs as aliases to the real
+IDs.</para>
+<para>Many applications today still use the <constant>V4L2_CID_PRIVATE_BASE</constant>
+IDs instead of using &VIDIOC-QUERYCTRL; with the <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant>
+flag to enumerate all IDs, so support for <constant>V4L2_CID_PRIVATE_BASE</constant>
+is still around.</para></footnote>
 and higher values. The pre-defined control IDs have the prefix
 <constant>V4L2_CID_</constant>, and are listed in <xref
 linkend="control-id" />. The ID is used when querying the attributes of
@@ -31,25 +44,22 @@ the current video input or output, tuner or modulator, or audio input
 or output. Different in the sense of other bounds, another default and
 current value, step size or other menu items. A control with a certain
 <emphasis>custom</emphasis> ID can also change name and
-type.<footnote>
-	<para>It will be more convenient for applications if drivers
-make use of the <constant>V4L2_CTRL_FLAG_DISABLED</constant> flag, but
-that was never required.</para>
-      </footnote> Control values are stored globally, they do not
+type.</para>
+
+    <para>If a control is not applicable to the current configuration
+of the device (for example, it doesn't apply to the current video input)
+drivers set the <constant>V4L2_CTRL_FLAG_INACTIVE</constant> flag.</para>
+
+    <para>Control values are stored globally, they do not
 change when switching except to stay within the reported bounds. They
 also do not change &eg; when the device is opened or closed, when the
 tuner radio frequency is changed or generally never without
-application request. Since V4L2 specifies no event mechanism, panel
-applications intended to cooperate with other panel applications (be
-they built into a larger application, as a TV viewer) may need to
-regularly poll control values to update their user
-interface.<footnote>
-	<para>Applications could call an ioctl to request events.
-After another process called &VIDIOC-S-CTRL; or another ioctl changing
-shared properties the &func-select; function would indicate
-readability until any ioctl (querying the properties) is
-called.</para>
-      </footnote></para>
+application request.</para>
+
+    <para>V4L2 specifies an event mechanism to notify applications
+when controls change value (see &VIDIOC-SUBSCRIBE-EVENT;, event
+<constant>V4L2_EVENT_CTRL</constant>), panel applications might want to make
+use of that in order to always reflect the correct control value.</para>
 
     <para>
       All controls use machine endianness.
@@ -434,127 +444,152 @@ Drivers must implement <constant>VIDIOC_QUERYCTRL</constant>,
 controls, <constant>VIDIOC_QUERYMENU</constant> when it has one or
 more menu type controls.</para>
 
-    <example>
-      <title>Enumerating all controls</title>
+    <example id="enum_all_controls">
+      <title>Enumerating all user controls</title>
 
       <programlisting>
 &v4l2-queryctrl; queryctrl;
 &v4l2-querymenu; querymenu;
 
-static void
-enumerate_menu (void)
+static void enumerate_menu(void)
 {
-	printf ("  Menu items:\n");
+	printf("  Menu items:\n");
 
-	memset (&amp;querymenu, 0, sizeof (querymenu));
+	memset(&amp;querymenu, 0, sizeof(querymenu));
 	querymenu.id = queryctrl.id;
 
 	for (querymenu.index = queryctrl.minimum;
 	     querymenu.index &lt;= queryctrl.maximum;
-	      querymenu.index++) {
-		if (0 == ioctl (fd, &VIDIOC-QUERYMENU;, &amp;querymenu)) {
-			printf ("  %s\n", querymenu.name);
+	     querymenu.index++) {
+		if (0 == ioctl(fd, &VIDIOC-QUERYMENU;, &amp;querymenu)) {
+			printf("  %s\n", querymenu.name);
 		}
 	}
 }
 
-memset (&amp;queryctrl, 0, sizeof (queryctrl));
+memset(&amp;queryctrl, 0, sizeof(queryctrl));
 
 for (queryctrl.id = V4L2_CID_BASE;
      queryctrl.id &lt; V4L2_CID_LASTP1;
      queryctrl.id++) {
-	if (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
+	if (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
 		if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
 			continue;
 
-		printf ("Control %s\n", queryctrl.name);
+		printf("Control %s\n", queryctrl.name);
 
 		if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
-			enumerate_menu ();
+			enumerate_menu();
 	} else {
 		if (errno == EINVAL)
 			continue;
 
-		perror ("VIDIOC_QUERYCTRL");
-		exit (EXIT_FAILURE);
+		perror("VIDIOC_QUERYCTRL");
+		exit(EXIT_FAILURE);
 	}
 }
 
 for (queryctrl.id = V4L2_CID_PRIVATE_BASE;;
      queryctrl.id++) {
-	if (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
+	if (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
 		if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
 			continue;
 
-		printf ("Control %s\n", queryctrl.name);
+		printf("Control %s\n", queryctrl.name);
 
 		if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
-			enumerate_menu ();
+			enumerate_menu();
 	} else {
 		if (errno == EINVAL)
 			break;
 
-		perror ("VIDIOC_QUERYCTRL");
-		exit (EXIT_FAILURE);
+		perror("VIDIOC_QUERYCTRL");
+		exit(EXIT_FAILURE);
 	}
 }
 </programlisting>
     </example>
 
     <example>
+      <title>Enumerating all user controls (alternative)</title>
+	<programlisting>
+memset(&amp;queryctrl, 0, sizeof(queryctrl));
+
+queryctrl.id = V4L2_CTRL_CLASS_USER | V4L2_CTRL_FLAG_NEXT_CTRL;
+while (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
+	if (V4L2_CTRL_ID2CLASS(queryctrl.id) != V4L2_CTRL_CLASS_USER)
+		break;
+	if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
+		continue;
+
+	printf("Control %s\n", queryctrl.name);
+
+	if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
+		enumerate_menu();
+
+	queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
+}
+if (errno != EINVAL) {
+	perror("VIDIOC_QUERYCTRL");
+	exit(EXIT_FAILURE);
+}
+</programlisting>
+    </example>
+
+    <example>
       <title>Changing controls</title>
 
       <programlisting>
 &v4l2-queryctrl; queryctrl;
 &v4l2-control; control;
 
-memset (&amp;queryctrl, 0, sizeof (queryctrl));
+memset(&amp;queryctrl, 0, sizeof(queryctrl));
 queryctrl.id = V4L2_CID_BRIGHTNESS;
 
-if (-1 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
+if (-1 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
 	if (errno != EINVAL) {
-		perror ("VIDIOC_QUERYCTRL");
-		exit (EXIT_FAILURE);
+		perror("VIDIOC_QUERYCTRL");
+		exit(EXIT_FAILURE);
 	} else {
-		printf ("V4L2_CID_BRIGHTNESS is not supported\n");
+		printf("V4L2_CID_BRIGHTNESS is not supported\n");
 	}
 } else if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED) {
-	printf ("V4L2_CID_BRIGHTNESS is not supported\n");
+	printf("V4L2_CID_BRIGHTNESS is not supported\n");
 } else {
-	memset (&amp;control, 0, sizeof (control));
+	memset(&amp;control, 0, sizeof (control));
 	control.id = V4L2_CID_BRIGHTNESS;
 	control.value = queryctrl.default_value;
 
-	if (-1 == ioctl (fd, &VIDIOC-S-CTRL;, &amp;control)) {
-		perror ("VIDIOC_S_CTRL");
-		exit (EXIT_FAILURE);
+	if (-1 == ioctl(fd, &VIDIOC-S-CTRL;, &amp;control)) {
+		perror("VIDIOC_S_CTRL");
+		exit(EXIT_FAILURE);
 	}
 }
 
-memset (&amp;control, 0, sizeof (control));
+memset(&amp;control, 0, sizeof(control));
 control.id = V4L2_CID_CONTRAST;
 
-if (0 == ioctl (fd, &VIDIOC-G-CTRL;, &amp;control)) {
+if (0 == ioctl(fd, &VIDIOC-G-CTRL;, &amp;control)) {
 	control.value += 1;
 
 	/* The driver may clamp the value or return ERANGE, ignored here */
 
-	if (-1 == ioctl (fd, &VIDIOC-S-CTRL;, &amp;control)
+	if (-1 == ioctl(fd, &VIDIOC-S-CTRL;, &amp;control)
 	    &amp;&amp; errno != ERANGE) {
-		perror ("VIDIOC_S_CTRL");
-		exit (EXIT_FAILURE);
+		perror("VIDIOC_S_CTRL");
+		exit(EXIT_FAILURE);
 	}
 /* Ignore if V4L2_CID_CONTRAST is unsupported */
 } else if (errno != EINVAL) {
-	perror ("VIDIOC_G_CTRL");
-	exit (EXIT_FAILURE);
+	perror("VIDIOC_G_CTRL");
+	exit(EXIT_FAILURE);
 }
 
 control.id = V4L2_CID_AUDIO_MUTE;
-control.value = TRUE; /* silence */
+control.value = 1; /* silence */
 
 /* Errors ignored */
-ioctl (fd, VIDIOC_S_CTRL, &amp;control);
+ioctl(fd, VIDIOC_S_CTRL, &amp;control);
 </programlisting>
     </example>
   </section>
@@ -625,16 +660,32 @@ supported.</para>
 &v4l2-control;, except for the fact that it also allows for 64-bit
 values and pointers to be passed.</para>
 
+      <para>Since the &v4l2-ext-control; supports pointers it is now
+also possible to have controls with complex types such as arrays/matrices
+and/or structures. All such complex controls will have the
+<constant>V4L2_CTRL_FLAG_HIDDEN</constant> set since such controls cannot
+be displayed in control panel applications. Nor can they be used in the
+user class (for backwards compatibility reasons), and you need to specify
+the <constant>V4L2_CTRL_FLAG_NEXT_HIDDEN</constant> when enumerating controls
+to actually be able to see such hidden controls. In other words, these
+controls with complex types should only be used programmatically.</para>
+
+      <para>Since such complex controls need to expose more information
+about themselves than is possible with &VIDIOC-QUERYCTRL; the
+&VIDIOC-QUERY-EXT-CTRL; ioctl was added. In particular, this ioctl gives
+the size of the matrix if this control consists of more than
+one element.</para>
+
       <para>It is important to realize that due to the flexibility of
 controls it is necessary to check whether the control you want to set
 actually is supported in the driver and what the valid range of values
-is. So use the &VIDIOC-QUERYCTRL; and &VIDIOC-QUERYMENU; ioctls to
-check this. Also note that it is possible that some of the menu
-indices in a control of type <constant>V4L2_CTRL_TYPE_MENU</constant>
-may not be supported (<constant>VIDIOC_QUERYMENU</constant> will
-return an error). A good example is the list of supported MPEG audio
-bitrates. Some drivers only support one or two bitrates, others
-support a wider range.</para>
+is. So use the &VIDIOC-QUERYCTRL; (or &VIDIOC-QUERY-EXT-CTRL;) and
+&VIDIOC-QUERYMENU; ioctls to check this. Also note that it is possible
+that some of the menu indices in a control of type
+<constant>V4L2_CTRL_TYPE_MENU</constant> may not be supported
+(<constant>VIDIOC_QUERYMENU</constant> will return an error). A good
+example is the list of supported MPEG audio bitrates. Some drivers only
+support one or two bitrates, others support a wider range.</para>
 
       <para>
 	All controls use machine endianness.
@@ -675,12 +726,12 @@ control class is found:</para>
       <informalexample>
 	<programlisting>
 qctrl.id = V4L2_CTRL_CLASS_MPEG | V4L2_CTRL_FLAG_NEXT_CTRL;
-while (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;qctrl)) {
-	if (V4L2_CTRL_ID2CLASS (qctrl.id) != V4L2_CTRL_CLASS_MPEG)
+while (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;qctrl)) {
+	if (V4L2_CTRL_ID2CLASS(qctrl.id) != V4L2_CTRL_CLASS_MPEG)
 		break;
 		/* ... */
-		qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
-	}
+	qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
+}
 </programlisting>
       </informalexample>
 
@@ -700,7 +751,7 @@ ID based on a control ID.</para>
 <constant>VIDIOC_QUERYCTRL</constant> will fail when used in
 combination with <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant>. In
 that case the old method of enumerating control should be used (see
-1.8). But if it is supported, then it is guaranteed to enumerate over
+<xref linkend="enum_all_controls" />). But if it is supported, then it is guaranteed to enumerate over
 all controls, including driver-private controls.</para>
     </section>
 
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFCv2 PATCH 21/21] v4l2-controls.txt: update to the new way of accessing controls.
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
                   ` (19 preceding siblings ...)
  2014-01-20 12:46 ` [RFCv2 PATCH 20/21] DocBook media: update control section Hans Verkuil
@ 2014-01-20 12:46 ` Hans Verkuil
  2014-01-23 15:50   ` Sylwester Nawrocki
  2014-01-22 22:44 ` [RFCv2 PATCH 00/21] Add support for complex controls Sylwester Nawrocki
  21 siblings, 1 reply; 56+ messages in thread
From: Hans Verkuil @ 2014-01-20 12:46 UTC (permalink / raw)
  To: linux-media; +Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

The way current and new values are accessed has changed. Update the
document to bring it up to date with the code.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 Documentation/video4linux/v4l2-controls.txt | 46 +++++++++++++++++++----------
 1 file changed, 31 insertions(+), 15 deletions(-)

diff --git a/Documentation/video4linux/v4l2-controls.txt b/Documentation/video4linux/v4l2-controls.txt
index 1c353c2..f94dcfd 100644
--- a/Documentation/video4linux/v4l2-controls.txt
+++ b/Documentation/video4linux/v4l2-controls.txt
@@ -77,9 +77,9 @@ Basic usage for V4L2 and sub-device drivers
 
   Where foo->v4l2_dev is of type struct v4l2_device.
 
-  Finally, remove all control functions from your v4l2_ioctl_ops:
-  vidioc_queryctrl, vidioc_querymenu, vidioc_g_ctrl, vidioc_s_ctrl,
-  vidioc_g_ext_ctrls, vidioc_try_ext_ctrls and vidioc_s_ext_ctrls.
+  Finally, remove all control functions from your v4l2_ioctl_ops (if any):
+  vidioc_queryctrl, vidioc_query_ext_ctrl, vidioc_querymenu, vidioc_g_ctrl,
+  vidioc_s_ctrl, vidioc_g_ext_ctrls, vidioc_try_ext_ctrls and vidioc_s_ext_ctrls.
   Those are now no longer needed.
 
 1.3.2) For sub-device drivers do this:
@@ -258,8 +258,8 @@ The new control value has already been validated, so all you need to do is
 to actually update the hardware registers.
 
 You're done! And this is sufficient for most of the drivers we have. No need
-to do any validation of control values, or implement QUERYCTRL/QUERYMENU. And
-G/S_CTRL as well as G/TRY/S_EXT_CTRLS are automatically supported.
+to do any validation of control values, or implement QUERYCTRL, QUERY_EXT_CTRL
+and QUERYMENU. And G/S_CTRL as well as G/TRY/S_EXT_CTRLS are automatically supported.
 
 
 ==============================================================================
@@ -288,24 +288,40 @@ of v4l2_device.
 Accessing Control Values
 ========================
 
-The v4l2_ctrl struct contains these two unions:
+The following union is used inside the control framework to access control
+values:
 
-	/* The current control value. */
-	union {
-		s32 val;
-		s64 val64;
-		char *string;
-	} cur;
+union v4l2_ctrl_ptr {
+	s32 *p_s32;
+	s64 *p_s64;
+	char *p_char;
+	void *p;
+};
+
+The v4l2_ctrl struct contains these fields that can be used to access both
+current and new values:
 
-	/* The new control value. */
 	union {
 		s32 val;
 		s64 val64;
-		char *string;
 	};
+	union v4l2_ctrl_ptr new;
+	union v4l2_ctrl_ptr cur;
+
+If the control has a simple s32 type or s64 type, then:
+
+	&ctrl->val == ctrl->new.p_s32
+
+or:
+
+	&ctrl->val64 == ctrl->new.p_s64
+
+For all other types use ctrl->new.p<something> instead of ctrl->val/val64.
+Basically the val and val64 fields can be considered aliases since these
+are used so often.
 
 Within the control ops you can freely use these. The val and val64 speak for
-themselves. The string pointers point to character buffers of length
+themselves. The p_char pointers point to character buffers of length
 ctrl->maximum + 1, and are always 0-terminated.
 
 In most cases 'cur' contains the current cached control value. When you create
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 00/21] Add support for complex controls
  2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
                   ` (20 preceding siblings ...)
  2014-01-20 12:46 ` [RFCv2 PATCH 21/21] v4l2-controls.txt: update to the new way of accessing controls Hans Verkuil
@ 2014-01-22 22:44 ` Sylwester Nawrocki
  2014-01-23 11:49   ` Hans Verkuil
  21 siblings, 1 reply; 56+ messages in thread
From: Sylwester Nawrocki @ 2014-01-22 22:44 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, m.chehab, laurent.pinchart, t.stanislaws

Hello Hans,

On 01/20/2014 01:45 PM, Hans Verkuil wrote:
> This patch series adds support for complex controls (aka 'Properties') to
> the control framework. It is the first part of a larger patch series that
> adds support for configuration stores, motion detection matrix controls and
> support for 'Multiple Selections'.
>
> This patch series is based on this RFC:
>
> http://permalink.gmane.org/gmane.linux.drivers.video-input-infrastructure/71822
>
> A more complete patch series (including configuration store support and the
> motion detection work) can be found here:
>
> http://git.linuxtv.org/hverkuil/media_tree.git/shortlog/refs/heads/propapi-doc
>
> This patch series is a revision of this series:
>
> http://www.spinics.net/lists/linux-media/msg71281.html
>
> Changes since RFCv1 are:
>
> - dropped configuration store support for now (there is no driver at the moment
>    that needs it).
> - dropped the term 'property', instead call it a 'control with a complex type'
>    or 'complex control' for short.
> - added DocBook documentation.
>
> The API changes required to support complex controls are minimal:
>
> - A new V4L2_CTRL_FLAG_HIDDEN has been added: any control with this flag (and
>    complex controls will always have this flag) will never be shown by control
>    panel GUIs. The only way to discover them is to pass the new _FLAG_NEXT_HIDDEN
>    flag to QUERYCTRL.

I had issues with using _HIDDEN for this at first but after thinking a 
bit more
it seems sensible.

> - A new VIDIOC_QUERY_EXT_CTRL ioctl has been added: needed to get the number of elements
>    stored in the control (rows by columns) and the size in byte of each element.
>    As a bonus feature a unit string has also been added as this has been requested
>    in the past. In addition min/max/step/def values are now 64-bit.
>
> - A new 'p' field is added to struct v4l2_ext_control to set/get complex values.
>
> - A helper flag V4L2_CTRL_FLAG_IS_PTR has been added to tell apps whether the
>    'value' or 'value64' fields of the v4l2_ext_control struct can be used (bit
>    is cleared) or if the 'p' pointer can be used (bit it set).
>
> There is one open item: if a complex control is a matrix, then it is possible
> to set only the first N elements of that matrix (starting at the first row).
> Currently the API will initialize the remaining elements to their default
> value. The idea was that if you have an array of, say, selection
> rectangles, then if you just set the first one the others will be automatically
> zeroed (i.e. set to unused). Without that you would be forced to set the whole
> array unless you are certain that they are already zeroed.
>
> It also has the advantage that when you set a control you know that all elements
> are set, even if you don't specify them all.
>
> Should I support the ability to set only the first N elements of a matrix at all?
>
> I see three options:
>
> 1) allow getting/setting only the first N elements and (when setting) initialize
>     the remaining elements to their default value.
> 2) allow getting/setting only the first N elements and leave the remaining
>     elements to their old value.
> 3) always set the full matrix.
>
> I am actually leaning towards 3 as that is the only unambiguous option. If there
> is a good use case in the future support for 1 or 2 can always be added later.

My feeling is that setting/getting only part of the matrix might be a useful
feature. Weren't you using struct v4l2_rect to select part of the matrix ?
Anyway, if there is no real need for {s,g}etting only part of the matrix yet
and adding it later won't be troublesome it seems reasonable to just start
with 3) for now.

Regards,
Sylwester

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 01/21] v4l2-ctrls: increase internal min/max/step/def to 64 bit
  2014-01-20 12:45 ` [RFCv2 PATCH 01/21] v4l2-ctrls: increase internal min/max/step/def to 64 bit Hans Verkuil
@ 2014-01-22 22:45   ` Sylwester Nawrocki
  0 siblings, 0 replies; 56+ messages in thread
From: Sylwester Nawrocki @ 2014-01-22 22:45 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-media, m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 01/20/2014 01:45 PM, Hans Verkuil wrote:
> From: Hans Verkuil<hans.verkuil@cisco.com>
>
> While VIDIOC_QUERYCTRL is limited to 32 bit min/max/step/def values
> for controls, the upcoming VIDIOC_QUERY_EXT_CTRL isn't. So increase
> the internal representation to 64 bits in preparation.
>
> Signed-off-by: Hans Verkuil<hans.verkuil@cisco.com>

Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 02/21] v4l2-ctrls: add unit string.
  2014-01-20 12:45 ` [RFCv2 PATCH 02/21] v4l2-ctrls: add unit string Hans Verkuil
@ 2014-01-22 22:47   ` Sylwester Nawrocki
  2014-01-24 10:35   ` Sakari Ailus
  1 sibling, 0 replies; 56+ messages in thread
From: Sylwester Nawrocki @ 2014-01-22 22:47 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-media, m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 01/20/2014 01:45 PM, Hans Verkuil wrote:
> From: Hans Verkuil<hans.verkuil@cisco.com>
>
> The upcoming VIDIOC_QUERY_EXT_CTRL adds support for a unit string. This
> allows userspace to show the unit belonging to a particular control.
>
> This patch adds support for the unit string to the control framework.
>
> Signed-off-by: Hans Verkuil<hans.verkuil@cisco.com>

Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 03/21] v4l2-ctrls: use pr_info/cont instead of printk.
  2014-01-20 12:45 ` [RFCv2 PATCH 03/21] v4l2-ctrls: use pr_info/cont instead of printk Hans Verkuil
@ 2014-01-22 22:48   ` Sylwester Nawrocki
  0 siblings, 0 replies; 56+ messages in thread
From: Sylwester Nawrocki @ 2014-01-22 22:48 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-media, m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 01/20/2014 01:45 PM, Hans Verkuil wrote:
> From: Hans Verkuil<hans.verkuil@cisco.com>
>
> Codingstyle fix.
>
> Signed-off-by: Hans Verkuil<hans.verkuil@cisco.com>

Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 04/21] videodev2.h: add initial support for complex controls.
  2014-01-20 12:45 ` [RFCv2 PATCH 04/21] videodev2.h: add initial support for complex controls Hans Verkuil
@ 2014-01-22 22:55   ` Sylwester Nawrocki
  0 siblings, 0 replies; 56+ messages in thread
From: Sylwester Nawrocki @ 2014-01-22 22:55 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-media, m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 01/20/2014 01:45 PM, Hans Verkuil wrote:
> From: Hans Verkuil<hans.verkuil@cisco.com>
>
> Complex controls are controls that can be used for compound and array
> types. This allows for more complex datastructures to be used with the
                                           ^
(missing whitespace)

> control framework.
>
> Such controls always have the V4L2_CTRL_FLAG_HIDDEN flag set. Note that
> 'simple' controls can also set that flag.
>
> The existing V4L2_CTRL_FLAG_NEXT_CTRL flag will only enumerate controls
> that do not have the HIDDEN flag, so a new V4L2_CTRL_FLAG_NEXT_HIDDEN flag
> is added to enumerate hidden controls. Set both flags to enumerate any
> controls (hidden or not).
>
> Complex control types will start at V4L2_CTRL_COMPLEX_TYPES. In addition, any
> control that uses the new 'p' field or the existing 'string' field will have
> flag V4L2_CTRL_FLAG_IS_PTR set.
>
> While not strictly necessary, adding that flag makes life for applications
> a lot simpler. If the flag is not set, then the control value is set
> through the value or value64 fields of struct v4l2_ext_control, otherwise
> a pointer points to the value.
>
> Signed-off-by: Hans Verkuil<hans.verkuil@cisco.com>

Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 05/21] videodev2.h: add struct v4l2_query_ext_ctrl and VIDIOC_QUERY_EXT_CTRL.
  2014-01-20 12:45 ` [RFCv2 PATCH 05/21] videodev2.h: add struct v4l2_query_ext_ctrl and VIDIOC_QUERY_EXT_CTRL Hans Verkuil
@ 2014-01-22 23:02   ` Sylwester Nawrocki
  2014-01-23 14:23     ` Hans Verkuil
  2014-01-24 11:28   ` Sakari Ailus
  1 sibling, 1 reply; 56+ messages in thread
From: Sylwester Nawrocki @ 2014-01-22 23:02 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-media, m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 01/20/2014 01:45 PM, Hans Verkuil wrote:
> From: Hans Verkuil<hans.verkuil@cisco.com>
>
> Add a new struct and ioctl to extend the amount of information you can
> get for a control.
>
> It gives back a unit string, the range is now a s64 type, and the matrix
> and element size can be reported through cols/rows/elem_size.
>
> Signed-off-by: Hans Verkuil<hans.verkuil@cisco.com>
> ---
>   include/uapi/linux/videodev2.h | 30 ++++++++++++++++++++++++++++++
>   1 file changed, 30 insertions(+)
>
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index 4d7782a..9e5b7d4 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -1272,6 +1272,34 @@ struct v4l2_queryctrl {
>   	__u32		     reserved[2];
>   };
>
> +/*  Used in the VIDIOC_QUERY_EXT_CTRL ioctl for querying extended controls */
> +struct v4l2_query_ext_ctrl {
> +	__u32		     id;
> +	__u32		     type;
> +	char		     name[32];
> +	char		     unit[32];

> +	union {
> +		__s64 val;
> +		__u32 reserved[4];
> +	} min;
> +	union {
> +		__s64 val;
> +		__u32 reserved[4];
> +	} max;
> +	union {
> +		__u64 val;
> +		__u32 reserved[4];
> +	} step;
> +	union {
> +		__s64 val;
> +		__u32 reserved[4];
> +	} def;

Are these reserved[] arrays of any use ?

> +	__u32                flags;
> +	__u32                cols, rows;

nit: I would put them on separate lines and use full words.

> +	__u32                elem_size;
> +	__u32		     reserved[17];
> +};
> +
>   /*  Used in the VIDIOC_QUERYMENU ioctl for querying menu items */
>   struct v4l2_querymenu {
>   	__u32		id;
> @@ -1965,6 +1993,8 @@ struct v4l2_create_buffers {
>      Never use these in applications! */
>   #define VIDIOC_DBG_G_CHIP_INFO  _IOWR('V', 102, struct v4l2_dbg_chip_info)
>
> +#define VIDIOC_QUERY_EXT_CTRL	_IOWR('V', 103, struct v4l2_query_ext_ctrl)
> +
>   /* Reminder: when adding new ioctls please add support for them to
>      drivers/media/video/v4l2-compat-ioctl32.c as well! */

--
Regards,
Sylwester

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 06/21] v4l2-ctrls: add support for complex types.
  2014-01-20 12:45 ` [RFCv2 PATCH 06/21] v4l2-ctrls: add support for complex types Hans Verkuil
@ 2014-01-23 11:44   ` Sylwester Nawrocki
  2014-01-24 15:44   ` Sakari Ailus
  1 sibling, 0 replies; 56+ messages in thread
From: Sylwester Nawrocki @ 2014-01-23 11:44 UTC (permalink / raw)
  To: Hans Verkuil, linux-media
  Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 20/01/14 13:45, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> This patch implements initial support for complex types.
> 
> For the most part the changes are fairly obvious (basic support for is_ptr
> types, the type_is_int function is replaced by a is_int bitfield, and
> v4l2_query_ext_ctrl is added), but one change needs more explanation:
> 
> The v4l2_ctrl struct adds a 'new' field and a 'stores' array at the end
> of the struct. This is in preparation for future patches where each control
> can have multiple configuration stores. The idea is that stores[0] is the current
> control value, stores[1] etc. are the control values for each configuration store
> and the 'new' value can be accessed through 'stores[-1]', i.e. the 'new' field.
> However, for now only stores[-1] and stores[0] is used.

I guess it implies an assumption that (maximum) number of configuration stores
is known before creating the control ?

Regarding the negative array indexes, I guess I would just stick with using 
the 'new' field :-)

> These new fields use the v4l2_ctrl_ptr union, which is a pointer to a control
> value.
> 
> Note that these two new fields are not yet actually used.
> 
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>

Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>

--
Regards,
Sylwester



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 07/21] v4l2: integrate support for VIDIOC_QUERY_EXT_CTRL.
  2014-01-20 12:46 ` [RFCv2 PATCH 07/21] v4l2: integrate support for VIDIOC_QUERY_EXT_CTRL Hans Verkuil
@ 2014-01-23 11:44   ` Sylwester Nawrocki
  0 siblings, 0 replies; 56+ messages in thread
From: Sylwester Nawrocki @ 2014-01-23 11:44 UTC (permalink / raw)
  To: Hans Verkuil, linux-media
  Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 20/01/14 13:46, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>

Perhaps we can have a bit more information than this in commit
description.

Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 00/21] Add support for complex controls
  2014-01-22 22:44 ` [RFCv2 PATCH 00/21] Add support for complex controls Sylwester Nawrocki
@ 2014-01-23 11:49   ` Hans Verkuil
  0 siblings, 0 replies; 56+ messages in thread
From: Hans Verkuil @ 2014-01-23 11:49 UTC (permalink / raw)
  To: Sylwester Nawrocki; +Cc: linux-media, m.chehab, laurent.pinchart, t.stanislaws

On 01/22/14 23:44, Sylwester Nawrocki wrote:
> Hello Hans,
> 
> On 01/20/2014 01:45 PM, Hans Verkuil wrote:
>> This patch series adds support for complex controls (aka 'Properties') to
>> the control framework. It is the first part of a larger patch series that
>> adds support for configuration stores, motion detection matrix controls and
>> support for 'Multiple Selections'.
>>
>> This patch series is based on this RFC:
>>
>> http://permalink.gmane.org/gmane.linux.drivers.video-input-infrastructure/71822
>>
>> A more complete patch series (including configuration store support and the
>> motion detection work) can be found here:
>>
>> http://git.linuxtv.org/hverkuil/media_tree.git/shortlog/refs/heads/propapi-doc
>>
>> This patch series is a revision of this series:
>>
>> http://www.spinics.net/lists/linux-media/msg71281.html
>>
>> Changes since RFCv1 are:
>>
>> - dropped configuration store support for now (there is no driver at the moment
>>    that needs it).
>> - dropped the term 'property', instead call it a 'control with a complex type'
>>    or 'complex control' for short.
>> - added DocBook documentation.
>>
>> The API changes required to support complex controls are minimal:
>>
>> - A new V4L2_CTRL_FLAG_HIDDEN has been added: any control with this flag (and
>>    complex controls will always have this flag) will never be shown by control
>>    panel GUIs. The only way to discover them is to pass the new _FLAG_NEXT_HIDDEN
>>    flag to QUERYCTRL.
> 
> I had issues with using _HIDDEN for this at first but after thinking a bit more
> it seems sensible.
> 
>> - A new VIDIOC_QUERY_EXT_CTRL ioctl has been added: needed to get the number of elements
>>    stored in the control (rows by columns) and the size in byte of each element.
>>    As a bonus feature a unit string has also been added as this has been requested
>>    in the past. In addition min/max/step/def values are now 64-bit.
>>
>> - A new 'p' field is added to struct v4l2_ext_control to set/get complex values.
>>
>> - A helper flag V4L2_CTRL_FLAG_IS_PTR has been added to tell apps whether the
>>    'value' or 'value64' fields of the v4l2_ext_control struct can be used (bit
>>    is cleared) or if the 'p' pointer can be used (bit it set).
>>
>> There is one open item: if a complex control is a matrix, then it is possible
>> to set only the first N elements of that matrix (starting at the first row).
>> Currently the API will initialize the remaining elements to their default
>> value. The idea was that if you have an array of, say, selection
>> rectangles, then if you just set the first one the others will be automatically
>> zeroed (i.e. set to unused). Without that you would be forced to set the whole
>> array unless you are certain that they are already zeroed.
>>
>> It also has the advantage that when you set a control you know that all elements
>> are set, even if you don't specify them all.
>>
>> Should I support the ability to set only the first N elements of a matrix at all?
>>
>> I see three options:
>>
>> 1) allow getting/setting only the first N elements and (when setting) initialize
>>     the remaining elements to their default value.
>> 2) allow getting/setting only the first N elements and leave the remaining
>>     elements to their old value.
>> 3) always set the full matrix.
>>
>> I am actually leaning towards 3 as that is the only unambiguous option. If there
>> is a good use case in the future support for 1 or 2 can always be added later.
> 
> My feeling is that setting/getting only part of the matrix might be a useful
> feature. Weren't you using struct v4l2_rect to select part of the matrix ?

Yes, in an earlier version of this project. However, it became too complex.
It suffered from the same problem as with initializing the first N elements,
but in addition it made the API and internal implementation overly complex.

The reality is that the only use-case where this would be useful is for large
matrices where you often need to update a sub-rectangle.

I do have large matrices (motion detection regions and thresholds), but you
typically set those up only once and you rarely change those on-the-fly.

> Anyway, if there is no real need for {s,g}etting only part of the matrix yet
> and adding it later won't be troublesome it seems reasonable to just start
> with 3) for now.

Yeah, the more I think about it, the more I believe that that's the best
approach.

Regards,

	Hans

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 19/21] DocBook media: update VIDIOC_G/S/TRY_EXT_CTRLS.
  2014-01-20 12:46 ` [RFCv2 PATCH 19/21] DocBook media: update VIDIOC_G/S/TRY_EXT_CTRLS Hans Verkuil
@ 2014-01-23 13:46   ` Sylwester Nawrocki
  2014-01-23 14:16     ` Hans Verkuil
  0 siblings, 1 reply; 56+ messages in thread
From: Sylwester Nawrocki @ 2014-01-23 13:46 UTC (permalink / raw)
  To: Hans Verkuil, linux-media
  Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 20/01/14 13:46, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> ---
>  .../DocBook/media/v4l/vidioc-g-ext-ctrls.xml       | 43 ++++++++++++++++++----
>  1 file changed, 35 insertions(+), 8 deletions(-)
> 
> diff --git a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
> index b3bb957..bb383b9 100644
> --- a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
> +++ b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
> @@ -72,23 +72,30 @@ initialize the <structfield>id</structfield>,
>  <structfield>size</structfield> and <structfield>reserved2</structfield> fields
>  of each &v4l2-ext-control; and call the
>  <constant>VIDIOC_G_EXT_CTRLS</constant> ioctl. String controls controls
> -must also set the <structfield>string</structfield> field.</para>
> +must also set the <structfield>string</structfield> field. Controls
> +of complex types (<constant>V4L2_CTRL_FLAG_IS_PTR</constant> is set)
> +must set the <structfield>p</structfield> field.</para>
>  
>      <para>If the <structfield>size</structfield> is too small to
>  receive the control result (only relevant for pointer-type controls
>  like strings), then the driver will set <structfield>size</structfield>
>  to a valid value and return an &ENOSPC;. You should re-allocate the
> -string memory to this new size and try again. It is possible that the
> -same issue occurs again if the string has grown in the meantime. It is
> +memory to this new size and try again. For the string type it is possible that
> +the same issue occurs again if the string has grown in the meantime. It is
>  recommended to call &VIDIOC-QUERYCTRL; first and use
>  <structfield>maximum</structfield>+1 as the new <structfield>size</structfield>
>  value. It is guaranteed that that is sufficient memory.
>  </para>
>  
> +    <para>For matrices it is possible to only get the first <constant>X</constant>
> +elements by setting size to <constant>X * elem_size</constant>, where
> +<structfield>elem_size</structfield> is obtained by calling &VIDIOC-QUERY-EXT-CTRL;.
> +Matrix elements are returned row-by-row.</para>
> +
>      <para>To change the value of a set of controls applications
>  initialize the <structfield>id</structfield>, <structfield>size</structfield>,
>  <structfield>reserved2</structfield> and
> -<structfield>value/string</structfield> fields of each &v4l2-ext-control; and
> +<structfield>value/value64/string/p</structfield> fields of each &v4l2-ext-control; and
>  call the <constant>VIDIOC_S_EXT_CTRLS</constant> ioctl. The controls
>  will only be set if <emphasis>all</emphasis> control values are
>  valid.</para>
> @@ -96,11 +103,17 @@ valid.</para>
>      <para>To check if a set of controls have correct values applications
>  initialize the <structfield>id</structfield>, <structfield>size</structfield>,
>  <structfield>reserved2</structfield> and
> -<structfield>value/string</structfield> fields of each &v4l2-ext-control; and
> +<structfield>value/value64/string/p</structfield> fields of each &v4l2-ext-control; and
>  call the <constant>VIDIOC_TRY_EXT_CTRLS</constant> ioctl. It is up to
>  the driver whether wrong values are automatically adjusted to a valid
>  value or if an error is returned.</para>
>  
> +    <para>For matrices it is possible to only set or check only the first
> +<constant>X</constant> elements by setting size to <constant>X * elem_size</constant>,
> +where <structfield>elem_size</structfield> is obtained by calling &VIDIOC-QUERY-EXT-CTRL;.
> +Matrix elements are set row-by-row. Matrix elements that are not explicitly
> +set will be initialized to their default value.</para>

Presumably this could be more problematic than leaving the remaining part
of the matrix unchanged. I assume this paragraph is going to be removed ?

>      <para>When the <structfield>id</structfield> or
>  <structfield>ctrl_class</structfield> is invalid drivers return an
>  &EINVAL;. When the value is out of bounds drivers can choose to take
> @@ -158,19 +171,33 @@ applications must set the array to zero.</entry>
>  	    <entry></entry>
>  	    <entry>__s32</entry>
>  	    <entry><structfield>value</structfield></entry>
> -	    <entry>New value or current value.</entry>
> +	    <entry>New value or current value. Valid if this control is not of
> +type <constant>V4L2_CTRL_TYPE_INTEGER64</constant> and
> +<constant>V4L2_CTRL_FLAG_IS_PTR</constant> is not set.</entry>
>  	  </row>
>  	  <row>
>  	    <entry></entry>
>  	    <entry>__s64</entry>
>  	    <entry><structfield>value64</structfield></entry>
> -	    <entry>New value or current value.</entry>
> +	    <entry>New value or current value. Valid if this control is of
> +type <constant>V4L2_CTRL_TYPE_INTEGER64</constant> and
> +<constant>V4L2_CTRL_FLAG_IS_PTR</constant> is not set.</entry>
>  	  </row>
>  	  <row>
>  	    <entry></entry>
>  	    <entry>char *</entry>
>  	    <entry><structfield>string</structfield></entry>
> -	    <entry>A pointer to a string.</entry>
> +	    <entry>A pointer to a string. Valid if this control is of
> +type <constant>V4L2_CTRL_TYPE_STRING</constant>.</entry>
> +	  </row>
> +	  <row>
> +	    <entry></entry>
> +	    <entry>void *</entry>
> +	    <entry><structfield>p</structfield></entry>
> +	    <entry>A pointer to a complex type which can be a matrix and/or a
> +complex type (the control's type is >= <constant>V4L2_CTRL_COMPLEX_TYPES</constant>).
> +Valid if <constant>V4L2_CTRL_FLAG_IS_PTR</constant> is set for this control.
> +</entry>
>  	  </row>
>  	</tbody>
>        </tgroup>

--
Regards,
Sylwester

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 11/21] v4l2-ctrls: prepare for matrix support: add cols & rows fields.
  2014-01-20 12:46 ` [RFCv2 PATCH 11/21] v4l2-ctrls: prepare for matrix support: add cols & rows fields Hans Verkuil
@ 2014-01-23 13:46   ` Sylwester Nawrocki
  0 siblings, 0 replies; 56+ messages in thread
From: Sylwester Nawrocki @ 2014-01-23 13:46 UTC (permalink / raw)
  To: Hans Verkuil, linux-media
  Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 20/01/14 13:46, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> Add cols and rows fields to the core control structures in preparation
> for matrix support.
> 
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>

Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 17/21] v4l2-ctrls.c: return elem_size instead of strlen
  2014-01-20 12:46 ` [RFCv2 PATCH 17/21] v4l2-ctrls.c: return elem_size instead of strlen Hans Verkuil
@ 2014-01-23 13:46   ` Sylwester Nawrocki
  0 siblings, 0 replies; 56+ messages in thread
From: Sylwester Nawrocki @ 2014-01-23 13:46 UTC (permalink / raw)
  To: Hans Verkuil, linux-media
  Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 20/01/14 13:46, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> When getting a string and the size given by the application is too
> short return the max length the string can have (elem_size) instead
> of the string length + 1. That makes more sense.
> 
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>

Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 19/21] DocBook media: update VIDIOC_G/S/TRY_EXT_CTRLS.
  2014-01-23 13:46   ` Sylwester Nawrocki
@ 2014-01-23 14:16     ` Hans Verkuil
  0 siblings, 0 replies; 56+ messages in thread
From: Hans Verkuil @ 2014-01-23 14:16 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: linux-media, m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 01/23/2014 02:46 PM, Sylwester Nawrocki wrote:
> On 20/01/14 13:46, Hans Verkuil wrote:
>> From: Hans Verkuil <hans.verkuil@cisco.com>
>>
>> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
>> ---
>>  .../DocBook/media/v4l/vidioc-g-ext-ctrls.xml       | 43 ++++++++++++++++++----
>>  1 file changed, 35 insertions(+), 8 deletions(-)
>>
>> diff --git a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
>> index b3bb957..bb383b9 100644
>> --- a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
>> +++ b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
>> @@ -72,23 +72,30 @@ initialize the <structfield>id</structfield>,
>>  <structfield>size</structfield> and <structfield>reserved2</structfield> fields
>>  of each &v4l2-ext-control; and call the
>>  <constant>VIDIOC_G_EXT_CTRLS</constant> ioctl. String controls controls
>> -must also set the <structfield>string</structfield> field.</para>
>> +must also set the <structfield>string</structfield> field. Controls
>> +of complex types (<constant>V4L2_CTRL_FLAG_IS_PTR</constant> is set)
>> +must set the <structfield>p</structfield> field.</para>
>>  
>>      <para>If the <structfield>size</structfield> is too small to
>>  receive the control result (only relevant for pointer-type controls
>>  like strings), then the driver will set <structfield>size</structfield>
>>  to a valid value and return an &ENOSPC;. You should re-allocate the
>> -string memory to this new size and try again. It is possible that the
>> -same issue occurs again if the string has grown in the meantime. It is
>> +memory to this new size and try again. For the string type it is possible that
>> +the same issue occurs again if the string has grown in the meantime. It is
>>  recommended to call &VIDIOC-QUERYCTRL; first and use
>>  <structfield>maximum</structfield>+1 as the new <structfield>size</structfield>
>>  value. It is guaranteed that that is sufficient memory.
>>  </para>
>>  
>> +    <para>For matrices it is possible to only get the first <constant>X</constant>
>> +elements by setting size to <constant>X * elem_size</constant>, where
>> +<structfield>elem_size</structfield> is obtained by calling &VIDIOC-QUERY-EXT-CTRL;.
>> +Matrix elements are returned row-by-row.</para>
>> +
>>      <para>To change the value of a set of controls applications
>>  initialize the <structfield>id</structfield>, <structfield>size</structfield>,
>>  <structfield>reserved2</structfield> and
>> -<structfield>value/string</structfield> fields of each &v4l2-ext-control; and
>> +<structfield>value/value64/string/p</structfield> fields of each &v4l2-ext-control; and
>>  call the <constant>VIDIOC_S_EXT_CTRLS</constant> ioctl. The controls
>>  will only be set if <emphasis>all</emphasis> control values are
>>  valid.</para>
>> @@ -96,11 +103,17 @@ valid.</para>
>>      <para>To check if a set of controls have correct values applications
>>  initialize the <structfield>id</structfield>, <structfield>size</structfield>,
>>  <structfield>reserved2</structfield> and
>> -<structfield>value/string</structfield> fields of each &v4l2-ext-control; and
>> +<structfield>value/value64/string/p</structfield> fields of each &v4l2-ext-control; and
>>  call the <constant>VIDIOC_TRY_EXT_CTRLS</constant> ioctl. It is up to
>>  the driver whether wrong values are automatically adjusted to a valid
>>  value or if an error is returned.</para>
>>  
>> +    <para>For matrices it is possible to only set or check only the first
>> +<constant>X</constant> elements by setting size to <constant>X * elem_size</constant>,
>> +where <structfield>elem_size</structfield> is obtained by calling &VIDIOC-QUERY-EXT-CTRL;.
>> +Matrix elements are set row-by-row. Matrix elements that are not explicitly
>> +set will be initialized to their default value.</para>
> 
> Presumably this could be more problematic than leaving the remaining part
> of the matrix unchanged. I assume this paragraph is going to be removed ?

Yes, that's going away.

Regards,

	Hans

> 
>>      <para>When the <structfield>id</structfield> or
>>  <structfield>ctrl_class</structfield> is invalid drivers return an
>>  &EINVAL;. When the value is out of bounds drivers can choose to take
>> @@ -158,19 +171,33 @@ applications must set the array to zero.</entry>
>>  	    <entry></entry>
>>  	    <entry>__s32</entry>
>>  	    <entry><structfield>value</structfield></entry>
>> -	    <entry>New value or current value.</entry>
>> +	    <entry>New value or current value. Valid if this control is not of
>> +type <constant>V4L2_CTRL_TYPE_INTEGER64</constant> and
>> +<constant>V4L2_CTRL_FLAG_IS_PTR</constant> is not set.</entry>
>>  	  </row>
>>  	  <row>
>>  	    <entry></entry>
>>  	    <entry>__s64</entry>
>>  	    <entry><structfield>value64</structfield></entry>
>> -	    <entry>New value or current value.</entry>
>> +	    <entry>New value or current value. Valid if this control is of
>> +type <constant>V4L2_CTRL_TYPE_INTEGER64</constant> and
>> +<constant>V4L2_CTRL_FLAG_IS_PTR</constant> is not set.</entry>
>>  	  </row>
>>  	  <row>
>>  	    <entry></entry>
>>  	    <entry>char *</entry>
>>  	    <entry><structfield>string</structfield></entry>
>> -	    <entry>A pointer to a string.</entry>
>> +	    <entry>A pointer to a string. Valid if this control is of
>> +type <constant>V4L2_CTRL_TYPE_STRING</constant>.</entry>
>> +	  </row>
>> +	  <row>
>> +	    <entry></entry>
>> +	    <entry>void *</entry>
>> +	    <entry><structfield>p</structfield></entry>
>> +	    <entry>A pointer to a complex type which can be a matrix and/or a
>> +complex type (the control's type is >= <constant>V4L2_CTRL_COMPLEX_TYPES</constant>).
>> +Valid if <constant>V4L2_CTRL_FLAG_IS_PTR</constant> is set for this control.
>> +</entry>
>>  	  </row>
>>  	</tbody>
>>        </tgroup>
> 
> --
> Regards,
> Sylwester
> 


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 08/21] v4l2-ctrls: create type_ops.
  2014-01-20 12:46 ` [RFCv2 PATCH 08/21] v4l2-ctrls: create type_ops Hans Verkuil
@ 2014-01-23 14:23   ` Sylwester Nawrocki
  2014-01-24 15:46   ` Sakari Ailus
  1 sibling, 0 replies; 56+ messages in thread
From: Sylwester Nawrocki @ 2014-01-23 14:23 UTC (permalink / raw)
  To: Hans Verkuil, linux-media
  Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 20/01/14 13:46, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> Since complex controls can have non-standard types we need to be able to do
> type-specific checks etc. In order to make that easy type operations are added.
> There are four operations:
> 
> - equal: check if two values are equal
> - init: initialize a value
> - log: log the value
> - validate: validate a new value
> 
> This patch uses the v4l2_ctrl_ptr union for the first time.
> 
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>

Looks good.

Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>

-- 
Sylwester Nawrocki
Samsung R&D Institute Poland

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 05/21] videodev2.h: add struct v4l2_query_ext_ctrl and VIDIOC_QUERY_EXT_CTRL.
  2014-01-22 23:02   ` Sylwester Nawrocki
@ 2014-01-23 14:23     ` Hans Verkuil
  2014-01-23 15:05       ` Sylwester Nawrocki
  0 siblings, 1 reply; 56+ messages in thread
From: Hans Verkuil @ 2014-01-23 14:23 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: linux-media, m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 01/23/2014 12:02 AM, Sylwester Nawrocki wrote:
> On 01/20/2014 01:45 PM, Hans Verkuil wrote:
>> From: Hans Verkuil<hans.verkuil@cisco.com>
>>
>> Add a new struct and ioctl to extend the amount of information you can
>> get for a control.
>>
>> It gives back a unit string, the range is now a s64 type, and the matrix
>> and element size can be reported through cols/rows/elem_size.
>>
>> Signed-off-by: Hans Verkuil<hans.verkuil@cisco.com>
>> ---
>>   include/uapi/linux/videodev2.h | 30 ++++++++++++++++++++++++++++++
>>   1 file changed, 30 insertions(+)
>>
>> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
>> index 4d7782a..9e5b7d4 100644
>> --- a/include/uapi/linux/videodev2.h
>> +++ b/include/uapi/linux/videodev2.h
>> @@ -1272,6 +1272,34 @@ struct v4l2_queryctrl {
>>   	__u32		     reserved[2];
>>   };
>>
>> +/*  Used in the VIDIOC_QUERY_EXT_CTRL ioctl for querying extended controls */
>> +struct v4l2_query_ext_ctrl {
>> +	__u32		     id;
>> +	__u32		     type;
>> +	char		     name[32];
>> +	char		     unit[32];
> 
>> +	union {
>> +		__s64 val;
>> +		__u32 reserved[4];
>> +	} min;
>> +	union {
>> +		__s64 val;
>> +		__u32 reserved[4];
>> +	} max;
>> +	union {
>> +		__u64 val;
>> +		__u32 reserved[4];
>> +	} step;
>> +	union {
>> +		__s64 val;
>> +		__u32 reserved[4];
>> +	} def;
> 
> Are these reserved[] arrays of any use ?

Excellent question. I'd like to know as well :-)

The idea is that if the type of the control is complex, then for certain types
it might still make sense to have a range. E.g. say that the type is v4l2_rect,
then you can define min/max/step/def v4l2_rect entries in the unions. Ditto
for a v4l2_fract (it would be nice to be able to specify the min/max allowed
scaling factors, for example).

The question is, am I over-engineering or is this the best idea since sliced
bread? Without the 'reserved' part this idea will be impossible to implement,
and I don't think it hurts to have it in.

> 
>> +	__u32                flags;
>> +	__u32                cols, rows;
> 
> nit: I would put them on separate lines and use full words.

Separate lines: no problem, but do I really have to write 'columns' in full? :-(

Regards,

	Hans

> 
>> +	__u32                elem_size;
>> +	__u32		     reserved[17];
>> +};
>> +
>>   /*  Used in the VIDIOC_QUERYMENU ioctl for querying menu items */
>>   struct v4l2_querymenu {
>>   	__u32		id;
>> @@ -1965,6 +1993,8 @@ struct v4l2_create_buffers {
>>      Never use these in applications! */
>>   #define VIDIOC_DBG_G_CHIP_INFO  _IOWR('V', 102, struct v4l2_dbg_chip_info)
>>
>> +#define VIDIOC_QUERY_EXT_CTRL	_IOWR('V', 103, struct v4l2_query_ext_ctrl)
>> +
>>   /* Reminder: when adding new ioctls please add support for them to
>>      drivers/media/video/v4l2-compat-ioctl32.c as well! */
> 
> --
> Regards,
> Sylwester
> 


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 10/21] v4l2-ctrls: compare values only once.
  2014-01-20 12:46 ` [RFCv2 PATCH 10/21] v4l2-ctrls: compare values only once Hans Verkuil
@ 2014-01-23 14:30   ` Sylwester Nawrocki
  0 siblings, 0 replies; 56+ messages in thread
From: Sylwester Nawrocki @ 2014-01-23 14:30 UTC (permalink / raw)
  To: Hans Verkuil, linux-media
  Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 20/01/14 13:46, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> When setting a control the control's new value is compared to the current
> value twice: once by new_to_cur(), once by cluster_changed(). Not a big
> deal when dealing with simple values, but it can be a problem when dealing
> with compound types or matrices. So fix this: cluster_changed() sets the
> has_changed flag, which is used by new_to_cur() instead of having to do
> another compare.
> 
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>

Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 05/21] videodev2.h: add struct v4l2_query_ext_ctrl and VIDIOC_QUERY_EXT_CTRL.
  2014-01-23 14:23     ` Hans Verkuil
@ 2014-01-23 15:05       ` Sylwester Nawrocki
  0 siblings, 0 replies; 56+ messages in thread
From: Sylwester Nawrocki @ 2014-01-23 15:05 UTC (permalink / raw)
  To: Hans Verkuil, Sylwester Nawrocki
  Cc: linux-media, m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 23/01/14 15:23, Hans Verkuil wrote:
> On 01/23/2014 12:02 AM, Sylwester Nawrocki wrote:
>> On 01/20/2014 01:45 PM, Hans Verkuil wrote:
>>> From: Hans Verkuil<hans.verkuil@cisco.com>
>>>
>>> Add a new struct and ioctl to extend the amount of information you can
>>> get for a control.
>>>
>>> It gives back a unit string, the range is now a s64 type, and the matrix
>>> and element size can be reported through cols/rows/elem_size.
>>>
>>> Signed-off-by: Hans Verkuil<hans.verkuil@cisco.com>
>>> ---
>>>   include/uapi/linux/videodev2.h | 30 ++++++++++++++++++++++++++++++
>>>   1 file changed, 30 insertions(+)
>>>
>>> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
>>> index 4d7782a..9e5b7d4 100644
>>> --- a/include/uapi/linux/videodev2.h
>>> +++ b/include/uapi/linux/videodev2.h
>>> @@ -1272,6 +1272,34 @@ struct v4l2_queryctrl {
>>>   	__u32		     reserved[2];
>>>   };
>>>
>>> +/*  Used in the VIDIOC_QUERY_EXT_CTRL ioctl for querying extended controls */
>>> +struct v4l2_query_ext_ctrl {
>>> +	__u32		     id;
>>> +	__u32		     type;
>>> +	char		     name[32];
>>> +	char		     unit[32];
>>
>>> +	union {
>>> +		__s64 val;
>>> +		__u32 reserved[4];
>>> +	} min;
>>> +	union {
>>> +		__s64 val;
>>> +		__u32 reserved[4];
>>> +	} max;
>>> +	union {
>>> +		__u64 val;
>>> +		__u32 reserved[4];
>>> +	} step;
>>> +	union {
>>> +		__s64 val;
>>> +		__u32 reserved[4];
>>> +	} def;
>>
>> Are these reserved[] arrays of any use ?
> 
> Excellent question. I'd like to know as well :-)
> 
> The idea is that if the type of the control is complex, then for certain types
> it might still make sense to have a range. E.g. say that the type is v4l2_rect,
> then you can define min/max/step/def v4l2_rect entries in the unions. Ditto
> for a v4l2_fract (it would be nice to be able to specify the min/max allowed
> scaling factors, for example).

Huh, sorry, I misread the patch. Please ignore this comment.

Certainly we need an ability to query other compound control types as well.
16 bytes seems a reasonable size, I guess it is going to be sufficient for
most cases. If not we could add a pointer member to the union...?

> The question is, am I over-engineering or is this the best idea since sliced
> bread? Without the 'reserved' part this idea will be impossible to implement,
> and I don't think it hurts to have it in.

Yes, that's how I imagined it as well, I didn't mean questioning the union
idea at all.

>>> +	__u32                flags;
>>> +	__u32                cols, rows;
>>
>> nit: I would put them on separate lines and use full words.
> 
> Separate lines: no problem, but do I really have to write 'columns' in full? :-(

Yes, sorry, one shall abide by the rules! :-)

Really, it's up to you - as the author, I think you're entitled to decide
about such details. ;) The short version looks probably neater anyway.

--
Regards,
Sylwester

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 20/21] DocBook media: update control section.
  2014-01-20 12:46 ` [RFCv2 PATCH 20/21] DocBook media: update control section Hans Verkuil
@ 2014-01-23 15:34   ` Sylwester Nawrocki
  0 siblings, 0 replies; 56+ messages in thread
From: Sylwester Nawrocki @ 2014-01-23 15:34 UTC (permalink / raw)
  To: Hans Verkuil, linux-media
  Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 20/01/14 13:46, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> Document the support for complex types in controls.
> 
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> ---
>  Documentation/DocBook/media/v4l/controls.xml | 185 +++++++++++++++++----------
>  1 file changed, 118 insertions(+), 67 deletions(-)
> 
> diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
> index a5a3188..85d78d4 100644
> --- a/Documentation/DocBook/media/v4l/controls.xml
> +++ b/Documentation/DocBook/media/v4l/controls.xml
> @@ -13,6 +13,19 @@ correctly with any device.</para>
>      <para>All controls are accessed using an ID value. V4L2 defines
>  several IDs for specific purposes. Drivers can also implement their
>  own custom controls using <constant>V4L2_CID_PRIVATE_BASE</constant>
> +<footnote><para>The use of <constant>V4L2_CID_PRIVATE_BASE</constant>
> +is problematic because different drivers may use the same
> +<constant>V4L2_CID_PRIVATE_BASE</constant> ID for different controls.
> +This makes it hard to programatically set such controls since the meaning
> +of the control with that ID is driver dependent. In order to resolve this
> +drivers use unique IDs and the <constant>V4L2_CID_PRIVATE_BASE</constant>
> +IDs are mapped to those unique IDs by the kernel. Consider these
> +<constant>V4L2_CID_PRIVATE_BASE</constant> IDs as aliases to the real
> +IDs.</para>
> +<para>Many applications today still use the <constant>V4L2_CID_PRIVATE_BASE</constant>
> +IDs instead of using &VIDIOC-QUERYCTRL; with the <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant>
> +flag to enumerate all IDs, so support for <constant>V4L2_CID_PRIVATE_BASE</constant>
> +is still around.</para></footnote>
>  and higher values. The pre-defined control IDs have the prefix
>  <constant>V4L2_CID_</constant>, and are listed in <xref
>  linkend="control-id" />. The ID is used when querying the attributes of
> @@ -31,25 +44,22 @@ the current video input or output, tuner or modulator, or audio input
>  or output. Different in the sense of other bounds, another default and
>  current value, step size or other menu items. A control with a certain
>  <emphasis>custom</emphasis> ID can also change name and
> -type.<footnote>
> -	<para>It will be more convenient for applications if drivers
> -make use of the <constant>V4L2_CTRL_FLAG_DISABLED</constant> flag, but
> -that was never required.</para>
> -      </footnote> Control values are stored globally, they do not
> +type.</para>
> +
> +    <para>If a control is not applicable to the current configuration
> +of the device (for example, it doesn't apply to the current video input)
> +drivers set the <constant>V4L2_CTRL_FLAG_INACTIVE</constant> flag.</para>
> +
> +    <para>Control values are stored globally, they do not
>  change when switching except to stay within the reported bounds. They
>  also do not change &eg; when the device is opened or closed, when the
>  tuner radio frequency is changed or generally never without
> -application request. Since V4L2 specifies no event mechanism, panel
> -applications intended to cooperate with other panel applications (be
> -they built into a larger application, as a TV viewer) may need to
> -regularly poll control values to update their user
> -interface.<footnote>
> -	<para>Applications could call an ioctl to request events.
> -After another process called &VIDIOC-S-CTRL; or another ioctl changing
> -shared properties the &func-select; function would indicate
> -readability until any ioctl (querying the properties) is
> -called.</para>
> -      </footnote></para>
> +application request.</para>
> +
> +    <para>V4L2 specifies an event mechanism to notify applications
> +when controls change value (see &VIDIOC-SUBSCRIBE-EVENT;, event
> +<constant>V4L2_EVENT_CTRL</constant>), panel applications might want to make
> +use of that in order to always reflect the correct control value.</para>
>  
>      <para>
>        All controls use machine endianness.
> @@ -434,127 +444,152 @@ Drivers must implement <constant>VIDIOC_QUERYCTRL</constant>,
>  controls, <constant>VIDIOC_QUERYMENU</constant> when it has one or
>  more menu type controls.</para>
>  
> -    <example>
> -      <title>Enumerating all controls</title>
> +    <example id="enum_all_controls">
> +      <title>Enumerating all user controls</title>
>  
>        <programlisting>
>  &v4l2-queryctrl; queryctrl;
>  &v4l2-querymenu; querymenu;
>  
> -static void
> -enumerate_menu (void)
> +static void enumerate_menu(void)
>  {
> -	printf ("  Menu items:\n");
> +	printf("  Menu items:\n");
>  
> -	memset (&amp;querymenu, 0, sizeof (querymenu));
> +	memset(&amp;querymenu, 0, sizeof(querymenu));
>  	querymenu.id = queryctrl.id;
>  
>  	for (querymenu.index = queryctrl.minimum;
>  	     querymenu.index &lt;= queryctrl.maximum;
> -	      querymenu.index++) {
> -		if (0 == ioctl (fd, &VIDIOC-QUERYMENU;, &amp;querymenu)) {
> -			printf ("  %s\n", querymenu.name);
> +	     querymenu.index++) {
> +		if (0 == ioctl(fd, &VIDIOC-QUERYMENU;, &amp;querymenu)) {
> +			printf("  %s\n", querymenu.name);
>  		}
>  	}
>  }
>  
> -memset (&amp;queryctrl, 0, sizeof (queryctrl));
> +memset(&amp;queryctrl, 0, sizeof(queryctrl));
>  
>  for (queryctrl.id = V4L2_CID_BASE;
>       queryctrl.id &lt; V4L2_CID_LASTP1;
>       queryctrl.id++) {
> -	if (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
> +	if (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
>  		if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
>  			continue;
>  
> -		printf ("Control %s\n", queryctrl.name);
> +		printf("Control %s\n", queryctrl.name);
>  
>  		if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
> -			enumerate_menu ();
> +			enumerate_menu();
>  	} else {
>  		if (errno == EINVAL)
>  			continue;
>  
> -		perror ("VIDIOC_QUERYCTRL");
> -		exit (EXIT_FAILURE);
> +		perror("VIDIOC_QUERYCTRL");
> +		exit(EXIT_FAILURE);
>  	}
>  }
>  
>  for (queryctrl.id = V4L2_CID_PRIVATE_BASE;;
>       queryctrl.id++) {
> -	if (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
> +	if (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
>  		if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
>  			continue;
>  
> -		printf ("Control %s\n", queryctrl.name);
> +		printf("Control %s\n", queryctrl.name);
>  
>  		if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
> -			enumerate_menu ();
> +			enumerate_menu();
>  	} else {
>  		if (errno == EINVAL)
>  			break;
>  
> -		perror ("VIDIOC_QUERYCTRL");
> -		exit (EXIT_FAILURE);
> +		perror("VIDIOC_QUERYCTRL");
> +		exit(EXIT_FAILURE);
>  	}
>  }
>  </programlisting>
>      </example>
>  
>      <example>
> +      <title>Enumerating all user controls (alternative)</title>
> +	<programlisting>
> +memset(&amp;queryctrl, 0, sizeof(queryctrl));
> +
> +queryctrl.id = V4L2_CTRL_CLASS_USER | V4L2_CTRL_FLAG_NEXT_CTRL;
> +while (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
> +	if (V4L2_CTRL_ID2CLASS(queryctrl.id) != V4L2_CTRL_CLASS_USER)
> +		break;
> +	if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
> +		continue;
> +
> +	printf("Control %s\n", queryctrl.name);
> +
> +	if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
> +		enumerate_menu();
> +
> +	queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
> +}
> +if (errno != EINVAL) {
> +	perror("VIDIOC_QUERYCTRL");
> +	exit(EXIT_FAILURE);
> +}
> +</programlisting>
> +    </example>
> +
> +    <example>
>        <title>Changing controls</title>
>  
>        <programlisting>
>  &v4l2-queryctrl; queryctrl;
>  &v4l2-control; control;
>  
> -memset (&amp;queryctrl, 0, sizeof (queryctrl));
> +memset(&amp;queryctrl, 0, sizeof(queryctrl));
>  queryctrl.id = V4L2_CID_BRIGHTNESS;
>  
> -if (-1 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
> +if (-1 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
>  	if (errno != EINVAL) {
> -		perror ("VIDIOC_QUERYCTRL");
> -		exit (EXIT_FAILURE);
> +		perror("VIDIOC_QUERYCTRL");
> +		exit(EXIT_FAILURE);
>  	} else {
> -		printf ("V4L2_CID_BRIGHTNESS is not supported\n");
> +		printf("V4L2_CID_BRIGHTNESS is not supported\n");
>  	}
>  } else if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED) {
> -	printf ("V4L2_CID_BRIGHTNESS is not supported\n");
> +	printf("V4L2_CID_BRIGHTNESS is not supported\n");
>  } else {
> -	memset (&amp;control, 0, sizeof (control));
> +	memset(&amp;control, 0, sizeof (control));
>  	control.id = V4L2_CID_BRIGHTNESS;
>  	control.value = queryctrl.default_value;
>  
> -	if (-1 == ioctl (fd, &VIDIOC-S-CTRL;, &amp;control)) {
> -		perror ("VIDIOC_S_CTRL");
> -		exit (EXIT_FAILURE);
> +	if (-1 == ioctl(fd, &VIDIOC-S-CTRL;, &amp;control)) {
> +		perror("VIDIOC_S_CTRL");
> +		exit(EXIT_FAILURE);
>  	}
>  }
>  
> -memset (&amp;control, 0, sizeof (control));
> +memset(&amp;control, 0, sizeof(control));
>  control.id = V4L2_CID_CONTRAST;
>  
> -if (0 == ioctl (fd, &VIDIOC-G-CTRL;, &amp;control)) {
> +if (0 == ioctl(fd, &VIDIOC-G-CTRL;, &amp;control)) {
>  	control.value += 1;
>  
>  	/* The driver may clamp the value or return ERANGE, ignored here */
>  
> -	if (-1 == ioctl (fd, &VIDIOC-S-CTRL;, &amp;control)
> +	if (-1 == ioctl(fd, &VIDIOC-S-CTRL;, &amp;control)
>  	    &amp;&amp; errno != ERANGE) {
> -		perror ("VIDIOC_S_CTRL");
> -		exit (EXIT_FAILURE);
> +		perror("VIDIOC_S_CTRL");
> +		exit(EXIT_FAILURE);
>  	}
>  /* Ignore if V4L2_CID_CONTRAST is unsupported */
>  } else if (errno != EINVAL) {
> -	perror ("VIDIOC_G_CTRL");
> -	exit (EXIT_FAILURE);
> +	perror("VIDIOC_G_CTRL");
> +	exit(EXIT_FAILURE);
>  }
>  
>  control.id = V4L2_CID_AUDIO_MUTE;
> -control.value = TRUE; /* silence */
> +control.value = 1; /* silence */
>  
>  /* Errors ignored */
> -ioctl (fd, VIDIOC_S_CTRL, &amp;control);
> +ioctl(fd, VIDIOC_S_CTRL, &amp;control);
>  </programlisting>
>      </example>
>    </section>
> @@ -625,16 +660,32 @@ supported.</para>
>  &v4l2-control;, except for the fact that it also allows for 64-bit
>  values and pointers to be passed.</para>
>  
> +      <para>Since the &v4l2-ext-control; supports pointers it is now
> +also possible to have controls with complex types such as arrays/matrices
> +and/or structures. All such complex controls will have the
> +<constant>V4L2_CTRL_FLAG_HIDDEN</constant> set since such controls cannot
> +be displayed in control panel applications. Nor can they be used in the
> +user class (for backwards compatibility reasons), and you need to specify
> +the <constant>V4L2_CTRL_FLAG_NEXT_HIDDEN</constant> when enumerating controls
> +to actually be able to see such hidden controls. In other words, these
> +controls with complex types should only be used programmatically.</para>
> +
> +      <para>Since such complex controls need to expose more information
> +about themselves than is possible with &VIDIOC-QUERYCTRL; the
> +&VIDIOC-QUERY-EXT-CTRL; ioctl was added. In particular, this ioctl gives
> +the size of the matrix if this control consists of more than
> +one element.</para>
> +
>        <para>It is important to realize that due to the flexibility of
>  controls it is necessary to check whether the control you want to set
>  actually is supported in the driver and what the valid range of values
> -is. So use the &VIDIOC-QUERYCTRL; and &VIDIOC-QUERYMENU; ioctls to
> -check this. Also note that it is possible that some of the menu
> -indices in a control of type <constant>V4L2_CTRL_TYPE_MENU</constant>
> -may not be supported (<constant>VIDIOC_QUERYMENU</constant> will
> -return an error). A good example is the list of supported MPEG audio
> -bitrates. Some drivers only support one or two bitrates, others
> -support a wider range.</para>
> +is. So use the &VIDIOC-QUERYCTRL; (or &VIDIOC-QUERY-EXT-CTRL;) and
> +&VIDIOC-QUERYMENU; ioctls to check this. Also note that it is possible
> +that some of the menu indices in a control of type
> +<constant>V4L2_CTRL_TYPE_MENU</constant> may not be supported
> +(<constant>VIDIOC_QUERYMENU</constant> will return an error). A good
> +example is the list of supported MPEG audio bitrates. Some drivers only
> +support one or two bitrates, others support a wider range.</para>
>  
>        <para>
>  	All controls use machine endianness.
> @@ -675,12 +726,12 @@ control class is found:</para>
>        <informalexample>
>  	<programlisting>
>  qctrl.id = V4L2_CTRL_CLASS_MPEG | V4L2_CTRL_FLAG_NEXT_CTRL;
> -while (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;qctrl)) {
> -	if (V4L2_CTRL_ID2CLASS (qctrl.id) != V4L2_CTRL_CLASS_MPEG)
> +while (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;qctrl)) {
> +	if (V4L2_CTRL_ID2CLASS(qctrl.id) != V4L2_CTRL_CLASS_MPEG)
>  		break;
>  		/* ... */
> -		qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
> -	}
> +	qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
> +}
>  </programlisting>
>        </informalexample>
>  
> @@ -700,7 +751,7 @@ ID based on a control ID.</para>
>  <constant>VIDIOC_QUERYCTRL</constant> will fail when used in
>  combination with <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant>. In
>  that case the old method of enumerating control should be used (see
> -1.8). But if it is supported, then it is guaranteed to enumerate over
> +<xref linkend="enum_all_controls" />). But if it is supported, then it is guaranteed to enumerate over
>  all controls, including driver-private controls.</para>
>      </section>

It would have been easier to review if the whitespace changes were in
a separate patch.

Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>


I guess we want a note somewhere the V4L2_CTRL_FLAG_DISABLED flag
is deprecated ? It seems to be used in very few drivers.

--
Regards,
Sylwester

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 12/21] v4l2-ctrls: replace cur by a union v4l2_ctrl_ptr.
  2014-01-20 12:46 ` [RFCv2 PATCH 12/21] v4l2-ctrls: replace cur by a union v4l2_ctrl_ptr Hans Verkuil
@ 2014-01-23 15:47   ` Sylwester Nawrocki
  0 siblings, 0 replies; 56+ messages in thread
From: Sylwester Nawrocki @ 2014-01-23 15:47 UTC (permalink / raw)
  To: Hans Verkuil, linux-media
  Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 20/01/14 13:46, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> Instead of having to maintain the 'cur' union this patch replaces it by
> a v4l2_ctrl_ptr union to be consistent with the future configuration stores,
> which also use that union. The number of drivers that use 'cur' is fairly small,
> so it is easy enough to convert them all.
> 
> Unfortunately, the union for the new value cannot be dropped as easily
> since it is used pretty much everywhere.
> 
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> ---
>  Documentation/video4linux/v4l2-controls.txt   |  4 ++--
>  drivers/media/common/cx2341x.c                |  4 ++--
>  drivers/media/i2c/adp1653.c                   | 10 +++++-----
>  drivers/media/i2c/as3645a.c                   | 22 ++++++++++-----------
>  drivers/media/i2c/lm3560.c                    |  2 +-
>  drivers/media/i2c/m5mols/m5mols_controls.c    |  6 +++---
>  drivers/media/i2c/msp3400-driver.c            |  4 ++--
>  drivers/media/i2c/mt9p031.c                   |  4 ++--
>  drivers/media/i2c/mt9t001.c                   |  4 ++--
>  drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c     |  6 +++---
>  drivers/media/i2c/smiapp/smiapp-core.c        | 12 ++++++------
>  drivers/media/pci/cx18/cx18-av-core.c         |  2 +-
>  drivers/media/pci/cx18/cx18-driver.c          | 10 +++++-----
>  drivers/media/platform/exynos4-is/fimc-core.c |  6 +++---
>  drivers/media/platform/vivi.c                 | 28 +++++++++++++--------------
>  drivers/media/radio/radio-isa.c               |  2 +-
>  drivers/media/radio/radio-sf16fmr2.c          |  4 ++--
>  drivers/media/usb/gspca/conex.c               |  8 ++++----
>  drivers/media/usb/gspca/sn9c20x.c             |  4 ++--
>  drivers/media/usb/gspca/topro.c               |  4 ++--
>  drivers/media/v4l2-core/v4l2-ctrls.c          | 16 +++++++--------
>  include/media/v4l2-ctrls.h                    |  9 ++-------
>  22 files changed, 83 insertions(+), 88 deletions(-)
> 
> diff --git a/Documentation/video4linux/v4l2-controls.txt b/Documentation/video4linux/v4l2-controls.txt
> index 06cf3ac..1c353c2 100644
> --- a/Documentation/video4linux/v4l2-controls.txt
> +++ b/Documentation/video4linux/v4l2-controls.txt
> @@ -362,8 +362,8 @@ will result in a deadlock since these helpers lock the handler as well.
>  You can also take the handler lock yourself:
>  
>  	mutex_lock(&state->ctrl_handler.lock);
> -	printk(KERN_INFO "String value is '%s'\n", ctrl1->cur.string);
> -	printk(KERN_INFO "Integer value is '%s'\n", ctrl2->cur.val);
> +	pr_info("String value is '%s'\n", ctrl1->cur.p_char);
> +	pr_info("Integer value is '%d'\n", *ctrl2->cur.p_s32);
>  	mutex_unlock(&state->ctrl_handler.lock);
>  
>  
> diff --git a/drivers/media/common/cx2341x.c b/drivers/media/common/cx2341x.c
> index 103ef6b..909d334 100644
> --- a/drivers/media/common/cx2341x.c
> +++ b/drivers/media/common/cx2341x.c
> @@ -1261,10 +1261,10 @@ static int cx2341x_hdl_api(struct cx2341x_handler *hdl,
>  	return hdl->func(hdl->priv, cmd, args, 0, data);
>  }
>  
> -/* ctrl->handler->lock is held, so it is safe to access cur.val */
> +/* ctrl->handler->lock is held, so it is safe to access *cur.p_s32 */
>  static inline int cx2341x_neq(struct v4l2_ctrl *ctrl)
>  {
> -	return ctrl && ctrl->val != ctrl->cur.val;
> +	return ctrl && ctrl->val != *ctrl->cur.p_s32;
>  }
>  
>  static int cx2341x_try_ctrl(struct v4l2_ctrl *ctrl)
> diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c
> index 873fe19..7d478dc 100644
> --- a/drivers/media/i2c/adp1653.c
> +++ b/drivers/media/i2c/adp1653.c
> @@ -158,16 +158,16 @@ static int adp1653_get_ctrl(struct v4l2_ctrl *ctrl)
>  	if (IS_ERR_VALUE(rval))
>  		return rval;
>  
> -	ctrl->cur.val = 0;
> +	*ctrl->cur.p_s32 = 0;
>  
>  	if (flash->fault & ADP1653_REG_FAULT_FLT_SCP)
> -		ctrl->cur.val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
> +		*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
>  	if (flash->fault & ADP1653_REG_FAULT_FLT_OT)
> -		ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
> +		*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
>  	if (flash->fault & ADP1653_REG_FAULT_FLT_TMR)
> -		ctrl->cur.val |= V4L2_FLASH_FAULT_TIMEOUT;
> +		*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_TIMEOUT;
>  	if (flash->fault & ADP1653_REG_FAULT_FLT_OV)
> -		ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
> +		*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
>  
>  	flash->fault = 0;
>  
> diff --git a/drivers/media/i2c/as3645a.c b/drivers/media/i2c/as3645a.c
> index 301084b..4c6041c 100644
> --- a/drivers/media/i2c/as3645a.c
> +++ b/drivers/media/i2c/as3645a.c
> @@ -334,24 +334,24 @@ static int as3645a_get_ctrl(struct v4l2_ctrl *ctrl)
>  		if (value < 0)
>  			return value;
>  
> -		ctrl->cur.val = 0;
> +		*ctrl->cur.p_s32 = 0;
>  		if (value & AS_FAULT_INFO_SHORT_CIRCUIT)
> -			ctrl->cur.val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
> +			*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
>  		if (value & AS_FAULT_INFO_OVER_TEMPERATURE)
> -			ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
> +			*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
>  		if (value & AS_FAULT_INFO_TIMEOUT)
> -			ctrl->cur.val |= V4L2_FLASH_FAULT_TIMEOUT;
> +			*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_TIMEOUT;
>  		if (value & AS_FAULT_INFO_OVER_VOLTAGE)
> -			ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
> +			*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
>  		if (value & AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT)
> -			ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_CURRENT;
> +			*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_OVER_CURRENT;
>  		if (value & AS_FAULT_INFO_INDICATOR_LED)
> -			ctrl->cur.val |= V4L2_FLASH_FAULT_INDICATOR;
> +			*ctrl->cur.p_s32 |= V4L2_FLASH_FAULT_INDICATOR;
>  		break;
>  
>  	case V4L2_CID_FLASH_STROBE_STATUS:
>  		if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) {
> -			ctrl->cur.val = 0;
> +			*ctrl->cur.p_s32 = 0;
>  			break;
>  		}
>  
> @@ -359,11 +359,11 @@ static int as3645a_get_ctrl(struct v4l2_ctrl *ctrl)
>  		if (value < 0)
>  			return value;
>  
> -		ctrl->cur.val = value;
> +		*ctrl->cur.p_s32 = value;
>  		break;
>  	}
>  
> -	dev_dbg(&client->dev, "G_CTRL %08x:%d\n", ctrl->id, ctrl->cur.val);
> +	dev_dbg(&client->dev, "G_CTRL %08x:%d\n", ctrl->id, *ctrl->cur.p_s32);
>  
>  	return 0;
>  }
> @@ -458,7 +458,7 @@ static int as3645a_set_ctrl(struct v4l2_ctrl *ctrl)
>  		if (ret < 0)
>  			return ret;
>  
> -		if ((ctrl->val == 0) == (ctrl->cur.val == 0))
> +		if ((ctrl->val == 0) == (*ctrl->cur.p_s32 == 0))
>  			break;
>  
>  		return as3645a_set_output(flash, false);
> diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c
> index d98ca3a..edfe746 100644
> --- a/drivers/media/i2c/lm3560.c
> +++ b/drivers/media/i2c/lm3560.c
> @@ -188,7 +188,7 @@ static int lm3560_get_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no)
>  			fault |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
>  		if (reg_val & FAULT_TIMEOUT)
>  			fault |= V4L2_FLASH_FAULT_TIMEOUT;
> -		ctrl->cur.val = fault;
> +		*ctrl->cur.p_s32 = fault;
>  	}
>  
>  out:
> diff --git a/drivers/media/i2c/m5mols/m5mols_controls.c b/drivers/media/i2c/m5mols/m5mols_controls.c
> index a60931e..7851d1f 100644
> --- a/drivers/media/i2c/m5mols/m5mols_controls.c
> +++ b/drivers/media/i2c/m5mols/m5mols_controls.c
> @@ -191,7 +191,7 @@ static int m5mols_3a_lock(struct m5mols_info *info, struct v4l2_ctrl *ctrl)
>  	bool af_lock = ctrl->val & V4L2_LOCK_FOCUS;
>  	int ret = 0;
>  
> -	if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_EXPOSURE) {
> +	if ((ctrl->val ^ *ctrl->cur.p_s32) & V4L2_LOCK_EXPOSURE) {
>  		bool ae_lock = ctrl->val & V4L2_LOCK_EXPOSURE;
>  
>  		ret = m5mols_write(&info->sd, AE_LOCK, ae_lock ?
> @@ -200,7 +200,7 @@ static int m5mols_3a_lock(struct m5mols_info *info, struct v4l2_ctrl *ctrl)
>  			return ret;
>  	}
>  
> -	if (((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_WHITE_BALANCE)
> +	if (((ctrl->val ^ *ctrl->cur.p_s32) & V4L2_LOCK_WHITE_BALANCE)
>  	    && info->auto_wb->val) {
>  		bool awb_lock = ctrl->val & V4L2_LOCK_WHITE_BALANCE;
>  
> @@ -213,7 +213,7 @@ static int m5mols_3a_lock(struct m5mols_info *info, struct v4l2_ctrl *ctrl)
>  	if (!info->ver.af || !af_lock)
>  		return ret;
>  
> -	if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_FOCUS)
> +	if ((ctrl->val ^ *ctrl->cur.p_s32) & V4L2_LOCK_FOCUS)
>  		ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP);
>  
>  	return ret;
> diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c
> index 8190fec..151016d 100644
> --- a/drivers/media/i2c/msp3400-driver.c
> +++ b/drivers/media/i2c/msp3400-driver.c
> @@ -411,8 +411,8 @@ void msp_update_volume(struct msp_state *state)
>  {
>  	/* Force an update of the volume/mute cluster */
>  	v4l2_ctrl_lock(state->volume);
> -	state->volume->val = state->volume->cur.val;
> -	state->muted->val = state->muted->cur.val;
> +	state->volume->val = *state->volume->cur.p_s32;
> +	state->muted->val = *state->muted->cur.p_s32;
>  	msp_s_ctrl(state->volume);
>  	v4l2_ctrl_unlock(state->volume);
>  }
> diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c
> index e5ddf47..28c17e0 100644
> --- a/drivers/media/i2c/mt9p031.c
> +++ b/drivers/media/i2c/mt9p031.c
> @@ -670,12 +670,12 @@ static int mt9p031_s_ctrl(struct v4l2_ctrl *ctrl)
>  	case V4L2_CID_TEST_PATTERN:
>  		if (!ctrl->val) {
>  			/* Restore the black level compensation settings. */
> -			if (mt9p031->blc_auto->cur.val != 0) {
> +			if (*mt9p031->blc_auto->cur.p_s32 != 0) {
>  				ret = mt9p031_s_ctrl(mt9p031->blc_auto);
>  				if (ret < 0)
>  					return ret;
>  			}
> -			if (mt9p031->blc_offset->cur.val != 0) {
> +			if (*mt9p031->blc_offset->cur.p_s32 != 0) {
>  				ret = mt9p031_s_ctrl(mt9p031->blc_offset);
>  				if (ret < 0)
>  					return ret;
> diff --git a/drivers/media/i2c/mt9t001.c b/drivers/media/i2c/mt9t001.c
> index d41c70e..6aca05b 100644
> --- a/drivers/media/i2c/mt9t001.c
> +++ b/drivers/media/i2c/mt9t001.c
> @@ -447,7 +447,7 @@ static int mt9t001_s_ctrl(struct v4l2_ctrl *ctrl)
>  		for (i = 0, count = 0; i < 4; ++i) {
>  			struct v4l2_ctrl *gain = mt9t001->gains[i];
>  
> -			if (gain->val != gain->cur.val)
> +			if (gain->val != *gain->cur.p_s32)
>  				count++;
>  		}
>  
> @@ -461,7 +461,7 @@ static int mt9t001_s_ctrl(struct v4l2_ctrl *ctrl)
>  		for (i = 0; i < 4; ++i) {
>  			struct v4l2_ctrl *gain = mt9t001->gains[i];
>  
> -			if (gain->val == gain->cur.val)
> +			if (gain->val == *gain->cur.p_s32)
>  				continue;
>  
>  			value = mt9t001_gain_value(&gain->val);
> diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c b/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c
> index 8001cde..cb6da84 100644
> --- a/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c
> +++ b/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c
> @@ -195,14 +195,14 @@ static int s5c73m3_3a_lock(struct s5c73m3 *state, struct v4l2_ctrl *ctrl)
>  	bool af_lock = ctrl->val & V4L2_LOCK_FOCUS;
>  	int ret = 0;
>  
> -	if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_EXPOSURE) {
> +	if ((ctrl->val ^ *ctrl->cur.p_s32) & V4L2_LOCK_EXPOSURE) {
>  		ret = s5c73m3_isp_command(state, COMM_AE_CON,
>  				ae_lock ? COMM_AE_STOP : COMM_AE_START);
>  		if (ret)
>  			return ret;
>  	}
>  
> -	if (((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_WHITE_BALANCE)
> +	if (((ctrl->val ^ *ctrl->cur.p_s32) & V4L2_LOCK_WHITE_BALANCE)
>  	    && state->ctrls.auto_wb->val) {
>  		ret = s5c73m3_isp_command(state, COMM_AWB_CON,
>  			awb_lock ? COMM_AWB_STOP : COMM_AWB_START);
> @@ -210,7 +210,7 @@ static int s5c73m3_3a_lock(struct s5c73m3 *state, struct v4l2_ctrl *ctrl)
>  			return ret;
>  	}
>  
> -	if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_FOCUS)
> +	if ((ctrl->val ^ *ctrl->cur.p_s32) & V4L2_LOCK_FOCUS)
>  		ret = s5c73m3_af_run(state, ~af_lock);
>  
>  	return ret;
> diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
> index 8741cae..d87c5e8 100644
> --- a/drivers/media/i2c/smiapp/smiapp-core.c
> +++ b/drivers/media/i2c/smiapp/smiapp-core.c
> @@ -297,8 +297,8 @@ static int smiapp_pll_update(struct smiapp_sensor *sensor)
>  	if (rval < 0)
>  		return rval;
>  
> -	sensor->pixel_rate_parray->cur.val64 = pll->vt_pix_clk_freq_hz;
> -	sensor->pixel_rate_csi->cur.val64 = pll->pixel_rate_csi;
> +	*sensor->pixel_rate_parray->cur.p_s64 = pll->vt_pix_clk_freq_hz;
> +	*sensor->pixel_rate_csi->cur.p_s64 = pll->pixel_rate_csi;
>  
>  	return 0;
>  }
> @@ -324,8 +324,8 @@ static void __smiapp_update_exposure_limits(struct smiapp_sensor *sensor)
>  		ctrl->default_value = max;
>  	if (ctrl->val > max)
>  		ctrl->val = max;
> -	if (ctrl->cur.val > max)
> -		ctrl->cur.val = max;
> +	if (*ctrl->cur.p_s32 > max)
> +		*ctrl->cur.p_s32 = max;
>  }
>  
>  /*
> @@ -796,7 +796,7 @@ static void smiapp_update_blanking(struct smiapp_sensor *sensor)
>  			      vblank->minimum, vblank->maximum);
>  	vblank->default_value = vblank->minimum;
>  	vblank->val = vblank->val;
> -	vblank->cur.val = vblank->val;
> +	*vblank->cur.p_s32 = vblank->val;
>  
>  	hblank->minimum =
>  		max_t(int,
> @@ -811,7 +811,7 @@ static void smiapp_update_blanking(struct smiapp_sensor *sensor)
>  			      hblank->minimum, hblank->maximum);
>  	hblank->default_value = hblank->minimum;
>  	hblank->val = hblank->val;
> -	hblank->cur.val = hblank->val;
> +	*hblank->cur.p_s32 = hblank->val;
>  
>  	__smiapp_update_exposure_limits(sensor);
>  }
> diff --git a/drivers/media/pci/cx18/cx18-av-core.c b/drivers/media/pci/cx18/cx18-av-core.c
> index c4890a4..d230a9b 100644
> --- a/drivers/media/pci/cx18/cx18-av-core.c
> +++ b/drivers/media/pci/cx18/cx18-av-core.c
> @@ -262,7 +262,7 @@ static void cx18_av_initialize(struct v4l2_subdev *sd)
>  		cx18_av_write(cx, 0x8d4, 20);
>  	}
>  	default_volume = (((228 - default_volume) >> 1) + 23) << 9;
> -	state->volume->cur.val = state->volume->default_value = default_volume;
> +	*state->volume->cur.p_s32 = state->volume->default_value = default_volume;
>  	v4l2_ctrl_handler_setup(&state->hdl);
>  }
>  
> diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c
> index 716bdc5..e4d0740 100644
> --- a/drivers/media/pci/cx18/cx18-driver.c
> +++ b/drivers/media/pci/cx18/cx18-driver.c
> @@ -756,11 +756,11 @@ static int cx18_init_struct1(struct cx18 *cx)
>  		return ret;
>  	cx->v4l2_dev.ctrl_handler = &cx->cxhdl.hdl;
>  
> -	cx->temporal_strength = cx->cxhdl.video_temporal_filter->cur.val;
> -	cx->spatial_strength = cx->cxhdl.video_spatial_filter->cur.val;
> -	cx->filter_mode = cx->cxhdl.video_spatial_filter_mode->cur.val |
> -		(cx->cxhdl.video_temporal_filter_mode->cur.val << 1) |
> -		(cx->cxhdl.video_median_filter_type->cur.val << 2);
> +	cx->temporal_strength = *cx->cxhdl.video_temporal_filter->cur.p_s32;
> +	cx->spatial_strength = *cx->cxhdl.video_spatial_filter->cur.p_s32;
> +	cx->filter_mode = *cx->cxhdl.video_spatial_filter_mode->cur.p_s32 |
> +		(*cx->cxhdl.video_temporal_filter_mode->cur.p_s32 << 1) |
> +		(*cx->cxhdl.video_median_filter_type->cur.p_s32 << 2);
>  
>  	init_waitqueue_head(&cx->cap_w);
>  	init_waitqueue_head(&cx->mb_apu_waitq);
> diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c
> index a7dfd07..d399699 100644
> --- a/drivers/media/platform/exynos4-is/fimc-core.c
> +++ b/drivers/media/platform/exynos4-is/fimc-core.c
> @@ -664,7 +664,7 @@ void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active)
>  		v4l2_ctrl_activate(ctrls->alpha, active && has_alpha);
>  
>  	if (active) {
> -		fimc_set_color_effect(ctx, ctrls->colorfx->cur.val);
> +		fimc_set_color_effect(ctx, *ctrls->colorfx->cur.p_s32);
>  		ctx->rotation = ctrls->rotate->val;
>  		ctx->hflip    = ctrls->hflip->val;
>  		ctx->vflip    = ctrls->vflip->val;
> @@ -689,8 +689,8 @@ void fimc_alpha_ctrl_update(struct fimc_ctx *ctx)
>  	v4l2_ctrl_lock(ctrl);
>  	ctrl->maximum = fimc_get_alpha_mask(ctx->d_frame.fmt);
>  
> -	if (ctrl->cur.val > ctrl->maximum)
> -		ctrl->cur.val = ctrl->maximum;
> +	if (*ctrl->cur.p_s32 > ctrl->maximum)
> +		*ctrl->cur.p_s32 = ctrl->maximum;
>  
>  	v4l2_ctrl_unlock(ctrl);
>  }
> diff --git a/drivers/media/platform/vivi.c b/drivers/media/platform/vivi.c
> index 2d4e73b..2ec8511 100644
> --- a/drivers/media/platform/vivi.c
> +++ b/drivers/media/platform/vivi.c
> @@ -642,28 +642,28 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
>  	gain = v4l2_ctrl_g_ctrl(dev->gain);
>  	mutex_lock(dev->ctrl_handler.lock);
>  	snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ",
> -			dev->brightness->cur.val,
> -			dev->contrast->cur.val,
> -			dev->saturation->cur.val,
> -			dev->hue->cur.val);
> +			*dev->brightness->cur.p_s32,
> +			*dev->contrast->cur.p_s32,
> +			*dev->saturation->cur.p_s32,
> +			*dev->hue->cur.p_s32);
>  	gen_text(dev, vbuf, line++ * 16, 16, str);
>  	snprintf(str, sizeof(str), " autogain %d, gain %3d, volume %3d, alpha 0x%02x ",
> -			dev->autogain->cur.val, gain, dev->volume->cur.val,
> -			dev->alpha->cur.val);
> +			*dev->autogain->cur.p_s32, gain, *dev->volume->cur.p_s32,
> +			*dev->alpha->cur.p_s32);
>  	gen_text(dev, vbuf, line++ * 16, 16, str);
>  	snprintf(str, sizeof(str), " int32 %d, int64 %lld, bitmask %08x ",
> -			dev->int32->cur.val,
> -			dev->int64->cur.val64,
> -			dev->bitmask->cur.val);
> +			*dev->int32->cur.p_s32,
> +			*dev->int64->cur.p_s64,
> +			*dev->bitmask->cur.p_s32);
>  	gen_text(dev, vbuf, line++ * 16, 16, str);
>  	snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
> -			dev->boolean->cur.val,
> -			dev->menu->qmenu[dev->menu->cur.val],
> -			dev->string->cur.string);
> +			*dev->boolean->cur.p_s32,
> +			dev->menu->qmenu[*dev->menu->cur.p_s32],
> +			dev->string->cur.p_char);
>  	gen_text(dev, vbuf, line++ * 16, 16, str);
>  	snprintf(str, sizeof(str), " integer_menu %lld, value %d ",
> -			dev->int_menu->qmenu_int[dev->int_menu->cur.val],
> -			dev->int_menu->cur.val);
> +			dev->int_menu->qmenu_int[*dev->int_menu->cur.p_s32],
> +			*dev->int_menu->cur.p_s32);
>  	gen_text(dev, vbuf, line++ * 16, 16, str);
>  	mutex_unlock(dev->ctrl_handler.lock);
>  	if (dev->button_pressed) {
> diff --git a/drivers/media/radio/radio-isa.c b/drivers/media/radio/radio-isa.c
> index 6ff3508..46d188d 100644
> --- a/drivers/media/radio/radio-isa.c
> +++ b/drivers/media/radio/radio-isa.c
> @@ -294,7 +294,7 @@ static int radio_isa_common_remove(struct radio_isa_card *isa,
>  {
>  	const struct radio_isa_ops *ops = isa->drv->ops;
>  
> -	ops->s_mute_volume(isa, true, isa->volume ? isa->volume->cur.val : 0);
> +	ops->s_mute_volume(isa, true, isa->volume ? *isa->volume->cur.p_s32 : 0);
>  	video_unregister_device(&isa->vdev);
>  	v4l2_ctrl_handler_free(&isa->hdl);
>  	v4l2_device_unregister(&isa->v4l2_dev);
> diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
> index 93d864e..e393130 100644
> --- a/drivers/media/radio/radio-sf16fmr2.c
> +++ b/drivers/media/radio/radio-sf16fmr2.c
> @@ -154,11 +154,11 @@ static int fmr2_s_ctrl(struct v4l2_ctrl *ctrl)
>  	switch (ctrl->id) {
>  	case V4L2_CID_AUDIO_VOLUME:
>  		volume = ctrl->val;
> -		balance = fmr2->balance->cur.val;
> +		balance = *fmr2->balance->cur.p_s32;
>  		break;
>  	case V4L2_CID_AUDIO_BALANCE:
>  		balance = ctrl->val;
> -		volume = fmr2->volume->cur.val;
> +		volume = *fmr2->volume->cur.p_s32;
>  		break;
>  	default:
>  		return -EINVAL;
> diff --git a/drivers/media/usb/gspca/conex.c b/drivers/media/usb/gspca/conex.c
> index 2e15c80..e8cfaf3 100644
> --- a/drivers/media/usb/gspca/conex.c
> +++ b/drivers/media/usb/gspca/conex.c
> @@ -887,14 +887,14 @@ static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
>  
>  	switch (ctrl->id) {
>  	case V4L2_CID_BRIGHTNESS:
> -		setbrightness(gspca_dev, ctrl->val, sd->sat->cur.val);
> +		setbrightness(gspca_dev, ctrl->val, *sd->sat->cur.p_s32);
>  		break;
>  	case V4L2_CID_CONTRAST:
> -		setcontrast(gspca_dev, ctrl->val, sd->sat->cur.val);
> +		setcontrast(gspca_dev, ctrl->val, *sd->sat->cur.p_s32);
>  		break;
>  	case V4L2_CID_SATURATION:
> -		setbrightness(gspca_dev, sd->brightness->cur.val, ctrl->val);
> -		setcontrast(gspca_dev, sd->contrast->cur.val, ctrl->val);
> +		setbrightness(gspca_dev, *sd->brightness->cur.p_s32, ctrl->val);
> +		setcontrast(gspca_dev, *sd->contrast->cur.p_s32, ctrl->val);
>  		break;
>  	}
>  	return gspca_dev->usb_err;
> diff --git a/drivers/media/usb/gspca/sn9c20x.c b/drivers/media/usb/gspca/sn9c20x.c
> index 2a38621..22d93c3 100644
> --- a/drivers/media/usb/gspca/sn9c20x.c
> +++ b/drivers/media/usb/gspca/sn9c20x.c
> @@ -2218,7 +2218,7 @@ static void transfer_check(struct gspca_dev *gspca_dev,
>  			/* Note: we are in interrupt context, so we can't
>  			   use v4l2_ctrl_g/s_ctrl here. Access the value
>  			   directly instead. */
> -			s32 curqual = sd->jpegqual->cur.val;
> +			s32 curqual = *sd->jpegqual->cur.p_s32;
>  			sd->nchg = 0;
>  			new_qual += curqual;
>  			if (new_qual < sd->jpegqual->minimum)
> @@ -2226,7 +2226,7 @@ static void transfer_check(struct gspca_dev *gspca_dev,
>  			else if (new_qual > sd->jpegqual->maximum)
>  				new_qual = sd->jpegqual->maximum;
>  			if (new_qual != curqual) {
> -				sd->jpegqual->cur.val = new_qual;
> +				*sd->jpegqual->cur.p_s32 = new_qual;
>  				queue_work(sd->work_thread, &sd->work);
>  			}
>  		}
> diff --git a/drivers/media/usb/gspca/topro.c b/drivers/media/usb/gspca/topro.c
> index 640c2fe..4abe03b 100644
> --- a/drivers/media/usb/gspca/topro.c
> +++ b/drivers/media/usb/gspca/topro.c
> @@ -3976,8 +3976,8 @@ static int sd_setgain(struct gspca_dev *gspca_dev)
>  	s32 val = gspca_dev->gain->val;
>  
>  	if (sd->sensor == SENSOR_CX0342) {
> -		s32 old = gspca_dev->gain->cur.val ?
> -					gspca_dev->gain->cur.val : 1;
> +		s32 old = *gspca_dev->gain->cur.p_s32 ?
> +					*gspca_dev->gain->cur.p_s32 : 1;
>  
>  		sd->blue->val = sd->blue->val * val / old;
>  		if (sd->blue->val > 4095)
> diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
> index c995439..f60b056 100644
> --- a/drivers/media/v4l2-core/v4l2-ctrls.c
> +++ b/drivers/media/v4l2-core/v4l2-ctrls.c
> @@ -47,7 +47,7 @@ struct v4l2_ctrl_helper {
>     mode. */
>  static bool is_cur_manual(const struct v4l2_ctrl *master)
>  {
> -	return master->is_auto && master->cur.val == master->manual_mode_value;
> +	return master->is_auto && *master->cur.p_s32 == master->manual_mode_value;
>  }
>  
>  /* Same as above, but this checks the against the new value instead of the
> @@ -1097,7 +1097,7 @@ static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 change
>  	if (ctrl->is_ptr)
>  		ev->u.ctrl.value64 = 0;
>  	else
> -		ev->u.ctrl.value64 = ctrl->cur.val64;
> +		ev->u.ctrl.value64 = *ctrl->cur.p_s64;
>  	ev->u.ctrl.minimum = ctrl->minimum;
>  	ev->u.ctrl.maximum = ctrl->maximum;
>  	if (ctrl->type == V4L2_CTRL_TYPE_MENU
> @@ -1777,13 +1777,13 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
>  		return NULL;
>  	}
>  
> -	sz_extra = sizeof(union v4l2_ctrl_ptr);
> +	sz_extra = elem_size;
>  	if (type == V4L2_CTRL_TYPE_BUTTON)
>  		flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
>  	else if (type == V4L2_CTRL_TYPE_CTRL_CLASS)
>  		flags |= V4L2_CTRL_FLAG_READ_ONLY;
>  	else if (type == V4L2_CTRL_TYPE_STRING || type >= V4L2_CTRL_COMPLEX_TYPES)
> -		sz_extra += 2 * elem_size;
> +		sz_extra += elem_size;
>  
>  	ctrl = kzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL);
>  	if (ctrl == NULL) {
> @@ -1816,7 +1816,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
>  	else if (type == V4L2_CTRL_TYPE_INTEGER_MENU)
>  		ctrl->qmenu_int = qmenu_int;
>  	ctrl->priv = priv;
> -	ctrl->cur.val = ctrl->val = def;
> +	ctrl->stores = &ctrl->cur;
>  	data = &ctrl->stores[1];
>  
>  	if (ctrl->is_ptr) {
> @@ -1824,7 +1824,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
>  		ctrl->stores[0].p = data + elem_size;
>  	} else {
>  		ctrl->new.p = &ctrl->val;
> -		ctrl->stores[0].p = &ctrl->cur.val;
> +		ctrl->stores[0].p = data;
>  	}
>  	for (s = -1; s <= 0; s++)
>  		ctrl->type_ops->init(ctrl, ctrl->stores[s]);
> @@ -3080,10 +3080,10 @@ int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
>  	ctrl->maximum = max;
>  	ctrl->step = step;
>  	ctrl->default_value = def;
> -	c.value = ctrl->cur.val;
> +	c.value = *ctrl->cur.p_s32;
>  	if (validate_new(ctrl, &c))
>  		c.value = def;
> -	if (c.value != ctrl->cur.val)
> +	if (c.value != *ctrl->cur.p_s32)
>  		ret = set_ctrl(NULL, ctrl, &c, V4L2_EVENT_CTRL_CH_RANGE);
>  	else
>  		send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE);
> diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
> index c86a071..27f0b7b 100644
> --- a/include/media/v4l2-ctrls.h
> +++ b/include/media/v4l2-ctrls.h
> @@ -198,14 +198,9 @@ struct v4l2_ctrl {
>  		char *string;
>  		void *p;
>  	};
> -	union {
> -		s32 val;
> -		s64 val64;
> -		char *string;
> -		void *p;
> -	} cur;
> +	union v4l2_ctrl_ptr *stores;
>  	union v4l2_ctrl_ptr new;
> -	union v4l2_ctrl_ptr stores[];

This change seems a bit surprising to me, there is nothing in the patch
description about it ?

> +	union v4l2_ctrl_ptr cur;
>  };
>  
>  /** struct v4l2_ctrl_ref - The control reference.
> 

--
Regards,
Sylwester

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 21/21] v4l2-controls.txt: update to the new way of accessing controls.
  2014-01-20 12:46 ` [RFCv2 PATCH 21/21] v4l2-controls.txt: update to the new way of accessing controls Hans Verkuil
@ 2014-01-23 15:50   ` Sylwester Nawrocki
  0 siblings, 0 replies; 56+ messages in thread
From: Sylwester Nawrocki @ 2014-01-23 15:50 UTC (permalink / raw)
  To: Hans Verkuil, linux-media
  Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 20/01/14 13:46, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> The way current and new values are accessed has changed. Update the
> document to bring it up to date with the code.
> 
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>

Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 13/21] v4l2-ctrls: use 'new' to access pointer controls
  2014-01-20 12:46 ` [RFCv2 PATCH 13/21] v4l2-ctrls: use 'new' to access pointer controls Hans Verkuil
@ 2014-01-23 17:06   ` Sylwester Nawrocki
  0 siblings, 0 replies; 56+ messages in thread
From: Sylwester Nawrocki @ 2014-01-23 17:06 UTC (permalink / raw)
  To: Hans Verkuil, linux-media
  Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 20/01/14 13:46, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> Require that 'new' string and pointer values are accessed through the 'new'
> field instead of through the union. This reduces the union to just val and
> val64.
> 
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>

Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 18/21] DocBook media: document VIDIOC_QUERY_EXT_CTRL.
  2014-01-20 12:46 ` [RFCv2 PATCH 18/21] DocBook media: document VIDIOC_QUERY_EXT_CTRL Hans Verkuil
@ 2014-01-23 17:24   ` Sylwester Nawrocki
  0 siblings, 0 replies; 56+ messages in thread
From: Sylwester Nawrocki @ 2014-01-23 17:24 UTC (permalink / raw)
  To: Hans Verkuil, linux-media
  Cc: m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

On 20/01/14 13:46, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> ---
>  .../DocBook/media/v4l/vidioc-queryctrl.xml         | 223 +++++++++++++++++----
>  1 file changed, 189 insertions(+), 34 deletions(-)
> 
> diff --git a/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml b/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
> index e6645b9..5e93c30 100644
> --- a/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
> +++ b/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
> @@ -1,11 +1,12 @@
>  <refentry id="vidioc-queryctrl">
>    <refmeta>
> -    <refentrytitle>ioctl VIDIOC_QUERYCTRL, VIDIOC_QUERYMENU</refentrytitle>
> +    <refentrytitle>ioctl VIDIOC_QUERYCTRL, VIDIOC_QUERY_EXT_CTRL, VIDIOC_QUERYMENU</refentrytitle>
>      &manvol;
>    </refmeta>
>  
>    <refnamediv>
>      <refname>VIDIOC_QUERYCTRL</refname>
> +    <refname>VIDIOC_QUERY_EXT_CTRL</refname>
>      <refname>VIDIOC_QUERYMENU</refname>
>      <refpurpose>Enumerate controls and menu control items</refpurpose>
>    </refnamediv>
> @@ -24,6 +25,14 @@
>  	<funcdef>int <function>ioctl</function></funcdef>
>  	<paramdef>int <parameter>fd</parameter></paramdef>
>  	<paramdef>int <parameter>request</parameter></paramdef>
> +	<paramdef>struct v4l2_query_ext_ctrl *<parameter>argp</parameter></paramdef>
> +      </funcprototype>
> +    </funcsynopsis>
> +    <funcsynopsis>
> +      <funcprototype>
> +	<funcdef>int <function>ioctl</function></funcdef>
> +	<paramdef>int <parameter>fd</parameter></paramdef>
> +	<paramdef>int <parameter>request</parameter></paramdef>
>  	<paramdef>struct v4l2_querymenu *<parameter>argp</parameter></paramdef>
>        </funcprototype>
>      </funcsynopsis>
> @@ -42,7 +51,7 @@
>        <varlistentry>
>  	<term><parameter>request</parameter></term>
>  	<listitem>
> -	  <para>VIDIOC_QUERYCTRL, VIDIOC_QUERYMENU</para>
> +	  <para>VIDIOC_QUERYCTRL, VIDIOC_QUERY_EXT_CTRL, VIDIOC_QUERYMENU</para>
>  	</listitem>
>        </varlistentry>
>        <varlistentry>
> @@ -91,7 +100,26 @@ prematurely end the enumeration).</para></footnote></para>
>  <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> the driver returns the
>  next supported control, or <errorcode>EINVAL</errorcode> if there is
>  none. Drivers which do not support this flag yet always return
> -<errorcode>EINVAL</errorcode>.</para>
> +<errorcode>EINVAL</errorcode>. Hidden controls (i.e. controls
> +with the <constant>V4L2_CTRL_FLAG_HIDDEN</constant> flag set) are
> +skipped when using the <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant>
> +flag. Use the <constant>VIDIOC_QUERY_EXT_CTRL</constant> for that.</para>
> +
> +    <para>The <constant>VIDIOC_QUERY_EXT_CTRL</constant> ioctl was
> +introduced in order to better support controls that can use complex
> +types, and to expose addition control information that cannot be

s/addition/additional ?

> +returned in &v4l2-queryctrl; since that structure is full.</para>
> +
> +    <para><constant>VIDIOC_QUERY_EXT_CTRL</constant> is used in the
> +same way as <constant>VIDIOC_QUERYCTRL</constant>, except that the
> +<structfield>reserved</structfield> array must be zeroed as well.
> +In addition, the <constant>V4L2_CTRL_FLAG_NEXT_HIDDEN</constant> flag
> +can be specified to enumerate all hidden controls (i.e. controls
> +with the <constant>V4L2_CTRL_FLAG_HIDDEN</constant> flag set which

s/"set which"/"set, which" ?

> +includes all controls with complex types). Specify both
> +<constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> and
> +<constant>V4L2_CTRL_FLAG_NEXT_HIDDEN</constant> in order to enumerate
> +all controls, hidden or not.</para>
>  
>      <para>Additional information is required for menu controls: the
>  names of the menu items. To query them applications set the
> @@ -142,38 +170,23 @@ string. This information is intended for the user.</entry>
>  	    <entry>__s32</entry>
>  	    <entry><structfield>minimum</structfield></entry>
>  	    <entry>Minimum value, inclusive. This field gives a lower
> -bound for <constant>V4L2_CTRL_TYPE_INTEGER</constant> controls and the
> -lowest valid index for <constant>V4L2_CTRL_TYPE_MENU</constant> controls.
> -For <constant>V4L2_CTRL_TYPE_STRING</constant> controls the minimum value
> -gives the minimum length of the string. This length <emphasis>does not include the terminating
> -zero</emphasis>. It may not be valid for any other type of control, including
> -<constant>V4L2_CTRL_TYPE_INTEGER64</constant> controls. Note that this is a
> -signed value.</entry>
> +bound for the control. See &v4l2-ctrl-type; how the minimum value is to
> +be used for each possible control type. Note that this a signed 32-bit value.</entry>
>  	  </row>
>  	  <row>
>  	    <entry>__s32</entry>
>  	    <entry><structfield>maximum</structfield></entry>
>  	    <entry>Maximum value, inclusive. This field gives an upper
> -bound for <constant>V4L2_CTRL_TYPE_INTEGER</constant> controls and the
> -highest valid index for <constant>V4L2_CTRL_TYPE_MENU</constant>
> -controls. For <constant>V4L2_CTRL_TYPE_BITMASK</constant> controls it is the
> -set of usable bits.
> -For <constant>V4L2_CTRL_TYPE_STRING</constant> controls the maximum value
> -gives the maximum length of the string. This length <emphasis>does not include the terminating
> -zero</emphasis>. It may not be valid for any other type of control, including
> -<constant>V4L2_CTRL_TYPE_INTEGER64</constant> controls. Note that this is a
> -signed value.</entry>
> +bound for the control. See &v4l2-ctrl-type; how the maximum value is to
> +be used for each possible control type. Note that this a signed 32-bit value.</entry>
>  	  </row>
>  	  <row>
>  	    <entry>__s32</entry>
>  	    <entry><structfield>step</structfield></entry>
> -	    <entry><para>This field gives a step size for
> -<constant>V4L2_CTRL_TYPE_INTEGER</constant> controls. For
> -<constant>V4L2_CTRL_TYPE_STRING</constant> controls this field refers to
> -the string length that has to be a multiple of this step size.
> -It may not be valid for any other type of control, including
> -<constant>V4L2_CTRL_TYPE_INTEGER64</constant>
> -controls.</para><para>Generally drivers should not scale hardware
> +	    <entry><para>This field gives a step size for the control.
> +See &v4l2-ctrl-type; how the step value is to be used for each possible
> +control type. Note that this an unsigned 32-bit value.
> +</para><para>Generally drivers should not scale hardware
>  control values. It may be necessary for example when the
>  <structfield>name</structfield> or <structfield>id</structfield> imply
>  a particular unit and the hardware actually accepts only multiples of
> @@ -192,10 +205,11 @@ be always positive.</para></entry>
>  	    <entry><structfield>default_value</structfield></entry>
>  	    <entry>The default value of a
>  <constant>V4L2_CTRL_TYPE_INTEGER</constant>,
> -<constant>_BOOLEAN</constant> or <constant>_MENU</constant> control.
> -Not valid for other types of controls. Drivers reset controls only
> -when the driver is loaded, not later, in particular not when the
> -func-open; is called.</entry>
> +<constant>_BOOLEAN</constant>, <constant>_BITMASK</constant>,
> +<constant>_MENU</constant> or <constant>_INTEGER_MENU</constant> control.
> +Not valid for other types of controls.
> +Note that drivers reset controls to their default value only when the
> +driver is first loaded, never afterwards.</entry>
>  	  </row>
>  	  <row>
>  	    <entry>__u32</entry>
> @@ -213,6 +227,129 @@ the array to zero.</entry>
>        </tgroup>
>      </table>
>  
> +    <table pgwide="1" frame="none" id="v4l2-query-ext-ctrl">
> +      <title>struct <structname>v4l2_query_ext_ctrl</structname></title>
> +      <tgroup cols="3">
> +	&cs-str;
> +	<tbody valign="top">
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>id</structfield></entry>
> +	    <entry>Identifies the control, set by the application. See
> +<xref linkend="control-id" /> for predefined IDs. When the ID is ORed
> +with <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> the driver clears the
> +flag and returns the first non-hidden control with a higher ID. When the
> +ID is ORed with <constant>V4L2_CTRL_FLAG_NEXT_HIDDEN</constant> the driver
> +clears the flag and returns the first hidden control with a higher ID.
> +Set both to get the first control (hidden or not) with a higher ID.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>type</structfield></entry>
> +	    <entry>Type of control, see <xref
> +		linkend="v4l2-ctrl-type" />.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>char</entry>
> +	    <entry><structfield>name</structfield>[32]</entry>
> +	    <entry>Name of the control, a NUL-terminated ASCII
> +string. This information is intended for the user.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>char</entry>
> +	    <entry><structfield>unit</structfield>[32]</entry>
> +	    <entry>The name of the unit of the control's value, a NUL-terminated ASCII
> +string. This information is intended for the user. This may be an empty string if no
> +unit is known or if it is not applicable to this particular control.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__s64</entry>
> +	    <entry><structfield>minimum</structfield></entry>
> +	    <entry>Minimum value, inclusive. This field gives a lower
> +bound for the control. See &v4l2-ctrl-type; how the minimum value is to
> +be used for each possible control type. Note that this a signed 64-bit value.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__s64</entry>
> +	    <entry><structfield>maximum</structfield></entry>
> +	    <entry>Maximum value, inclusive. This field gives an upper
> +bound for the control. See &v4l2-ctrl-type; how the maximum value is to
> +be used for each possible control type. Note that this a signed 64-bit value.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u64</entry>
> +	    <entry><structfield>step</structfield></entry>
> +	    <entry><para>This field gives a step size for the control.
> +See &v4l2-ctrl-type; how the step value is to be used for each possible
> +control type. Note that this an unsigned 64-bit value.
> +</para><para>Generally drivers should not scale hardware
> +control values. It may be necessary for example when the
> +<structfield>name</structfield> or <structfield>id</structfield> imply
> +a particular unit and the hardware actually accepts only multiples of
> +said unit. If so, drivers must take care values are properly rounded
> +when scaling, such that errors will not accumulate on repeated
> +read-write cycles.</para><para>This field gives the smallest change of
> +an integer control actually affecting hardware. Often the information
> +is needed when the user can change controls by keyboard or GUI
> +buttons, rather than a slider. When for example a hardware register
> +accepts values 0-511 and the driver reports 0-65535, step should be
> +128.</para></entry>
> +	  </row>
> +	  <row>
> +	    <entry>__s64</entry>
> +	    <entry><structfield>default_value</structfield></entry>
> +	    <entry>The default value of a
> +<constant>V4L2_CTRL_TYPE_INTEGER</constant>, <constant>_INTEGER64</constant>,
> +<constant>_BOOLEAN</constant>, <constant>_BITMASK</constant>,
> +<constant>_MENU</constant> or <constant>_INTEGER_MENU</constant> control.
> +Not valid for other types of controls.
> +Note that drivers reset controls to their default value only when the
> +driver is first loaded, never afterwards.
> +</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>flags</structfield></entry>
> +	    <entry>Control flags, see <xref
> +		linkend="control-flags" />.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>cols</structfield></entry>
> +	    <entry>The number of columns in the matrix. If this control
> +is not a matrix, then both <structfield>cols</structfield> and
> +<structfield>rows</structfield> are 1. <structfield>cols</structfield>
> +can never be 0.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>rows</structfield></entry>
> +	    <entry>The number of rows in the matrix. If this control
> +is not a matrix, then both <structfield>cols</structfield> and
> +<structfield>rows</structfield> are 1. <structfield>rows</structfield>
> +can never be 0.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>elem_size</structfield></entry>
> +	    <entry>The size in bytes of a single element of the matrix.
> +Given a char pointer <constant>p</constant> to the matrix you can find the
> +position of cell <constant>(y, x)</constant> as follows:
> +<constant>p + (y * cols + x) * elem_size</constant>. <structfield>elem_size</structfield>
> +is always valid, also when the control isn't a matrix. For string controls
> +<structfield>elem_size</structfield> is equal to <structfield>maximum + 1</structfield>.
> +</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>reserved</structfield>[17]</entry>
> +	    <entry>Reserved for future extensions. Applications and drivers
> +must set the array to zero.</entry>
> +	  </row>
> +	</tbody>
> +      </tgroup>
> +    </table>
> +
>      <table pgwide="1" frame="none" id="v4l2-querymenu">
>        <title>struct <structname>v4l2_querymenu</structname></title>
>        <tgroup cols="4">
> @@ -347,11 +484,14 @@ Drivers must ignore the value passed with
>  	  </row>
>  	  <row>
>  	    <entry><constant>V4L2_CTRL_TYPE_INTEGER64</constant></entry>
> -	    <entry>n/a</entry>
> -	    <entry>n/a</entry>
> -	    <entry>n/a</entry>
> +	    <entry>any</entry>
> +	    <entry>any</entry>
> +	    <entry>any</entry>
>  	    <entry>A 64-bit integer valued control. Minimum, maximum
> -and step size cannot be queried.</entry>
> +and step size cannot be queried using <constant>VIDIOC_QUERYCTRL</constant>.
> +Only <constant>VIDIOC_QUERY_EXT_CTRL</constant> can retrieve the 64-bit
> +min/max/step values, they should be interpreted as n/a when using
> +<constant>VIDIOC_QUERYCTRL</constant>.</entry>
>  	  </row>
>  	  <row>
>  	    <entry><constant>V4L2_CTRL_TYPE_STRING</constant></entry>
> @@ -450,6 +590,21 @@ is in auto-gain mode. In such a case the hardware calculates the gain value base
>  the lighting conditions which can change over time. Note that setting a new value for
>  a volatile control will have no effect. The new value will just be ignored.</entry>
>  	  </row>
> +	  <row>
> +	    <entry><constant>V4L2_CTRL_FLAG_HIDDEN</constant></entry>
> +	    <entry>0x0100</entry>
> +	    <entry>This control is hidden and should not be shown in a GUI application.
> +Hidden controls are skipped when enumerating them using <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant>,
> +and they can only be enumerated by using the <constant>V4L2_CTRL_FLAG_NEXT_HIDDEN</constant>
> +flag. All controls that have a complex type have this flag set.</entry>
> +	  </row>
> +	  <row>
> +	    <entry><constant>V4L2_CTRL_FLAG_IS_PTR</constant></entry>
> +	    <entry>0x0200</entry>
> +	    <entry>This control has a pointer type, so its value has to be accessed
> +using one of the pointer fields of &v4l2-ext-control;. This flag is set for controls
> +that are a matrix, string, or have a complex type.</entry>
> +	  </row>
>  	</tbody>
>        </tgroup>
>      </table>
> 

Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>

--
Regards,
Sylwester

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 02/21] v4l2-ctrls: add unit string.
  2014-01-20 12:45 ` [RFCv2 PATCH 02/21] v4l2-ctrls: add unit string Hans Verkuil
  2014-01-22 22:47   ` Sylwester Nawrocki
@ 2014-01-24 10:35   ` Sakari Ailus
  2014-01-24 11:19     ` Hans Verkuil
  1 sibling, 1 reply; 56+ messages in thread
From: Sakari Ailus @ 2014-01-24 10:35 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-media, m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

Hi Hans,

Thanks for the patchset!

On Mon, Jan 20, 2014 at 01:45:55PM +0100, Hans Verkuil wrote:
> diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
> index 0b347e8..3998049 100644
> --- a/include/media/v4l2-ctrls.h
> +++ b/include/media/v4l2-ctrls.h
> @@ -85,6 +85,7 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
>    * @ops:	The control ops.
>    * @id:	The control ID.
>    * @name:	The control name.
> +  * @unit:	The control's unit. May be NULL.
>    * @type:	The control type.
>    * @minimum:	The control's minimum value.
>    * @maximum:	The control's maximum value.
> @@ -130,6 +131,7 @@ struct v4l2_ctrl {
>  	const struct v4l2_ctrl_ops *ops;
>  	u32 id;
>  	const char *name;
> +	const char *unit;

What would you think of using a numeric value (with the standardised units
#defined)? I think using a string begs for unmanaged unit usage. Code that
deals with units might work with one driver but not with another since it
uses a slightly different string for unit x.

A prefix could be potentially nice, too, so ms and µs would still have the
same unit but a different prefix.

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus@iki.fi	XMPP: sailus@retiisi.org.uk

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 02/21] v4l2-ctrls: add unit string.
  2014-01-24 10:35   ` Sakari Ailus
@ 2014-01-24 11:19     ` Hans Verkuil
  2014-01-24 15:54       ` Sakari Ailus
  0 siblings, 1 reply; 56+ messages in thread
From: Hans Verkuil @ 2014-01-24 11:19 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Hans Verkuil, linux-media, m.chehab, laurent.pinchart,
	t.stanislaws, Hans Verkuil

On 01/24/2014 11:35 AM, Sakari Ailus wrote:
> Hi Hans,
> 
> Thanks for the patchset!
> 
> On Mon, Jan 20, 2014 at 01:45:55PM +0100, Hans Verkuil wrote:
>> diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
>> index 0b347e8..3998049 100644
>> --- a/include/media/v4l2-ctrls.h
>> +++ b/include/media/v4l2-ctrls.h
>> @@ -85,6 +85,7 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
>>    * @ops:	The control ops.
>>    * @id:	The control ID.
>>    * @name:	The control name.
>> +  * @unit:	The control's unit. May be NULL.
>>    * @type:	The control type.
>>    * @minimum:	The control's minimum value.
>>    * @maximum:	The control's maximum value.
>> @@ -130,6 +131,7 @@ struct v4l2_ctrl {
>>  	const struct v4l2_ctrl_ops *ops;
>>  	u32 id;
>>  	const char *name;
>> +	const char *unit;
> 
> What would you think of using a numeric value (with the standardised units
> #defined)? I think using a string begs for unmanaged unit usage. Code that
> deals with units might work with one driver but not with another since it
> uses a slightly different string for unit x.

First of all, you always need a string. You don't want GUIs like qv4l2 to have
to switch on a unit in order to generate the unit strings. That's impossible to
keep up to date.

In addition, private controls can have really strange custom units, so you want
to have a string there as well.

Standard controls can have their unit string set in v4l2-ctrls.c, just as their
name is set there these days, thus ensuring consistency.

What I had in mind is that videodev2.h defines a list of standardized unit strings,
e.g.:

#define V4L2_CTRL_UNIT_USECS "usecs"
#define V4L2_CTRL_UNIT_MSECS "msecs"

and apps can do strcmp(qc->unit, V4L2_CTRL_UNIT_USECS) to see what the unit is.
If a driver doesn't use one of those standardized unit strings, then it is a
driver bug.

> A prefix could be potentially nice, too, so ms and µs would still have the
> same unit but a different prefix.

Can you give an example of a prefix? I don't really follow what you want to
achieve.

Regards,

	Hans


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 05/21] videodev2.h: add struct v4l2_query_ext_ctrl and VIDIOC_QUERY_EXT_CTRL.
  2014-01-20 12:45 ` [RFCv2 PATCH 05/21] videodev2.h: add struct v4l2_query_ext_ctrl and VIDIOC_QUERY_EXT_CTRL Hans Verkuil
  2014-01-22 23:02   ` Sylwester Nawrocki
@ 2014-01-24 11:28   ` Sakari Ailus
  2014-01-24 11:58     ` Hans Verkuil
  1 sibling, 1 reply; 56+ messages in thread
From: Sakari Ailus @ 2014-01-24 11:28 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-media, m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

Hi Hans,

On Mon, Jan 20, 2014 at 01:45:58PM +0100, Hans Verkuil wrote:
> +	union {
> +		__u64 val;
> +		__u32 reserved[4];
> +	} step;

While I do not question that step is obviously always a positive value (or
zero), using a different type from the value (and min and max) does add
slight complications every time it is being used. I don't think there's a
use case for using values over 2^62 for step either.

Speaking of which --- do you think we should continue to have step in the
interface? This has been proven to be slightly painful when the step is not
an integer. Using a step of one in that case has been the only feasible
solution. Step could be naturally be used as a hint but enforcing it often
forces setting it to one.

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus@iki.fi	XMPP: sailus@retiisi.org.uk

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 05/21] videodev2.h: add struct v4l2_query_ext_ctrl and VIDIOC_QUERY_EXT_CTRL.
  2014-01-24 11:28   ` Sakari Ailus
@ 2014-01-24 11:58     ` Hans Verkuil
  0 siblings, 0 replies; 56+ messages in thread
From: Hans Verkuil @ 2014-01-24 11:58 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

Hi Sakari,

On 01/24/2014 12:28 PM, Sakari Ailus wrote:
> Hi Hans,
> 
> On Mon, Jan 20, 2014 at 01:45:58PM +0100, Hans Verkuil wrote:
>> +	union {
>> +		__u64 val;
>> +		__u32 reserved[4];
>> +	} step;
> 
> While I do not question that step is obviously always a positive value (or
> zero), using a different type from the value (and min and max) does add
> slight complications every time it is being used. I don't think there's a
> use case for using values over 2^62 for step either.

What sort of complications? The reason I changed it is to avoid having to
check for step < 0. It also makes it clear that it has to be positive.

> 
> Speaking of which --- do you think we should continue to have step in the
> interface? This has been proven to be slightly painful when the step is not
> an integer. Using a step of one in that case has been the only feasible
> solution. Step could be naturally be used as a hint but enforcing it often
> forces setting it to one.

Step is used quite often, so we can't remove it. If the step for a particular
control isn't fixed over the range of possible values (at least, I think that
is what you mean), then I don't see any solution that isn't painful. Not to
mention that GUIs will have a hard time.

Suggestions are welcome, though.

Regards,

	Hans

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 09/21] v4l2-ctrls: rewrite copy routines to operate on union v4l2_ctrl_ptr.
  2014-01-20 12:46 ` [RFCv2 PATCH 09/21] v4l2-ctrls: rewrite copy routines to operate on union v4l2_ctrl_ptr Hans Verkuil
@ 2014-01-24 12:31   ` Sakari Ailus
  2014-01-24 12:44     ` Hans Verkuil
  0 siblings, 1 reply; 56+ messages in thread
From: Sakari Ailus @ 2014-01-24 12:31 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-media, m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

Hi Hans,

On Mon, Jan 20, 2014 at 01:46:02PM +0100, Hans Verkuil wrote:
> diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
> index 9f97af4..c0507ed 100644
> --- a/drivers/media/v4l2-core/v4l2-ctrls.c
> +++ b/drivers/media/v4l2-core/v4l2-ctrls.c
> @@ -1266,48 +1266,64 @@ static const struct v4l2_ctrl_type_ops std_type_ops = {
>  	.validate = std_validate,
>  };
>  
> -/* Helper function: copy the current control value back to the caller */
> -static int cur_to_user(struct v4l2_ext_control *c,
> -		       struct v4l2_ctrl *ctrl)
> +/* Helper function: copy the given control value back to the caller */
> +static int ptr_to_user(struct v4l2_ext_control *c,
> +		       struct v4l2_ctrl *ctrl,
> +		       union v4l2_ctrl_ptr ptr)
>  {
>  	u32 len;
>  
>  	if (ctrl->is_ptr && !ctrl->is_string)
> -		return copy_to_user(c->p, ctrl->cur.p, ctrl->elem_size);
> +		return copy_to_user(c->p, ptr.p, ctrl->elem_size);

Not a fault of this patch, but this is wrong: copy_to_user() returns the
bytes not copied. That should probably be fixed separately before this
patch. I can submit one.

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus@iki.fi	XMPP: sailus@retiisi.org.uk

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 09/21] v4l2-ctrls: rewrite copy routines to operate on union v4l2_ctrl_ptr.
  2014-01-24 12:31   ` Sakari Ailus
@ 2014-01-24 12:44     ` Hans Verkuil
  0 siblings, 0 replies; 56+ messages in thread
From: Hans Verkuil @ 2014-01-24 12:44 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil



On 01/24/2014 01:31 PM, Sakari Ailus wrote:
> Hi Hans,
> 
> On Mon, Jan 20, 2014 at 01:46:02PM +0100, Hans Verkuil wrote:
>> diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
>> index 9f97af4..c0507ed 100644
>> --- a/drivers/media/v4l2-core/v4l2-ctrls.c
>> +++ b/drivers/media/v4l2-core/v4l2-ctrls.c
>> @@ -1266,48 +1266,64 @@ static const struct v4l2_ctrl_type_ops std_type_ops = {
>>  	.validate = std_validate,
>>  };
>>  
>> -/* Helper function: copy the current control value back to the caller */
>> -static int cur_to_user(struct v4l2_ext_control *c,
>> -		       struct v4l2_ctrl *ctrl)
>> +/* Helper function: copy the given control value back to the caller */
>> +static int ptr_to_user(struct v4l2_ext_control *c,
>> +		       struct v4l2_ctrl *ctrl,
>> +		       union v4l2_ctrl_ptr ptr)
>>  {
>>  	u32 len;
>>  
>>  	if (ctrl->is_ptr && !ctrl->is_string)
>> -		return copy_to_user(c->p, ctrl->cur.p, ctrl->elem_size);
>> +		return copy_to_user(c->p, ptr.p, ctrl->elem_size);
> 
> Not a fault of this patch, but this is wrong: copy_to_user() returns the
> bytes not copied. That should probably be fixed separately before this
> patch. I can submit one.
> 

Thanks! Don't bother making a patch, I'll need to make more changes anyway so I'll
just fix this at the same time.

Regards,

	Hans

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 06/21] v4l2-ctrls: add support for complex types.
  2014-01-20 12:45 ` [RFCv2 PATCH 06/21] v4l2-ctrls: add support for complex types Hans Verkuil
  2014-01-23 11:44   ` Sylwester Nawrocki
@ 2014-01-24 15:44   ` Sakari Ailus
  2014-01-25  8:50     ` Hans Verkuil
  1 sibling, 1 reply; 56+ messages in thread
From: Sakari Ailus @ 2014-01-24 15:44 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-media, m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

Hi Hans,

On Mon, Jan 20, 2014 at 01:45:59PM +0100, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> This patch implements initial support for complex types.
> 
> For the most part the changes are fairly obvious (basic support for is_ptr
> types, the type_is_int function is replaced by a is_int bitfield, and
> v4l2_query_ext_ctrl is added), but one change needs more explanation:
> 
> The v4l2_ctrl struct adds a 'new' field and a 'stores' array at the end
> of the struct. This is in preparation for future patches where each control
> can have multiple configuration stores. The idea is that stores[0] is the current
> control value, stores[1] etc. are the control values for each configuration store
> and the 'new' value can be accessed through 'stores[-1]', i.e. the 'new' field.
> However, for now only stores[-1] and stores[0] is used.

Could we use zero or positive indices only, e.g. the new being zero and
current 1, or the other way? Or make the "new" value special, i.e. using a
different field name.

I think accessing the previous struct member by index -1 looks a little bit
hackish.

> These new fields use the v4l2_ctrl_ptr union, which is a pointer to a control
> value.
> 
> Note that these two new fields are not yet actually used.

Should they be then added yet in the first place? :-)

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus@iki.fi	XMPP: sailus@retiisi.org.uk

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 08/21] v4l2-ctrls: create type_ops.
  2014-01-20 12:46 ` [RFCv2 PATCH 08/21] v4l2-ctrls: create type_ops Hans Verkuil
  2014-01-23 14:23   ` Sylwester Nawrocki
@ 2014-01-24 15:46   ` Sakari Ailus
  2014-01-25  8:54     ` Hans Verkuil
  1 sibling, 1 reply; 56+ messages in thread
From: Sakari Ailus @ 2014-01-24 15:46 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-media, m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

Hi Hans,

On Mon, Jan 20, 2014 at 01:46:01PM +0100, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> Since complex controls can have non-standard types we need to be able to do
> type-specific checks etc. In order to make that easy type operations are added.
> There are four operations:
> 
> - equal: check if two values are equal
> - init: initialize a value
> - log: log the value
> - validate: validate a new value
> 
> This patch uses the v4l2_ctrl_ptr union for the first time.
> 
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> ---
>  drivers/media/v4l2-core/v4l2-ctrls.c | 267 ++++++++++++++++++++++-------------
>  include/media/v4l2-ctrls.h           |  21 +++
>  2 files changed, 190 insertions(+), 98 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
> index 98e940f..9f97af4 100644
> --- a/drivers/media/v4l2-core/v4l2-ctrls.c
> +++ b/drivers/media/v4l2-core/v4l2-ctrls.c
> @@ -1123,6 +1123,149 @@ static void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes)
>  			v4l2_event_queue_fh(sev->fh, &ev);
>  }
>  
> +static bool std_equal(const struct v4l2_ctrl *ctrl,
> +		      union v4l2_ctrl_ptr ptr1,
> +		      union v4l2_ctrl_ptr ptr2)
> +{
> +	switch (ctrl->type) {
> +	case V4L2_CTRL_TYPE_BUTTON:
> +		return false;
> +	case V4L2_CTRL_TYPE_STRING:
> +		/* strings are always 0-terminated */
> +		return !strcmp(ptr1.p_char, ptr2.p_char);
> +	case V4L2_CTRL_TYPE_INTEGER64:
> +		return *ptr1.p_s64 == *ptr2.p_s64;

The above two lines seem redundant to me.

> +	default:
> +		if (ctrl->is_ptr)
> +			return !memcmp(ptr1.p, ptr2.p, ctrl->elem_size);
> +		return *ptr1.p_s32 == *ptr2.p_s32;
> +	}
> +}
> +
> +static void std_init(const struct v4l2_ctrl *ctrl,
> +		     union v4l2_ctrl_ptr ptr)
> +{
> +	switch (ctrl->type) {
> +	case V4L2_CTRL_TYPE_STRING:
> +		memset(ptr.p_char, ' ', ctrl->minimum);
> +		ptr.p_char[ctrl->minimum] = '\0';
> +		break;
> +	case V4L2_CTRL_TYPE_INTEGER64:
> +		*ptr.p_s64 = ctrl->default_value;
> +		break;
> +	case V4L2_CTRL_TYPE_INTEGER:
> +	case V4L2_CTRL_TYPE_INTEGER_MENU:
> +	case V4L2_CTRL_TYPE_MENU:
> +	case V4L2_CTRL_TYPE_BITMASK:
> +	case V4L2_CTRL_TYPE_BOOLEAN:
> +		*ptr.p_s32 = ctrl->default_value;
> +		break;
> +	default:
> +		break;
> +	}
> +}
> +
> +static void std_log(const struct v4l2_ctrl *ctrl)
> +{
> +	union v4l2_ctrl_ptr ptr = ctrl->stores[0];
> +
> +	switch (ctrl->type) {
> +	case V4L2_CTRL_TYPE_INTEGER:
> +		pr_cont("%d", *ptr.p_s32);
> +		break;
> +	case V4L2_CTRL_TYPE_BOOLEAN:
> +		pr_cont("%s", *ptr.p_s32 ? "true" : "false");
> +		break;
> +	case V4L2_CTRL_TYPE_MENU:
> +		pr_cont("%s", ctrl->qmenu[*ptr.p_s32]);
> +		break;
> +	case V4L2_CTRL_TYPE_INTEGER_MENU:
> +		pr_cont("%lld", ctrl->qmenu_int[*ptr.p_s32]);
> +		break;
> +	case V4L2_CTRL_TYPE_BITMASK:
> +		pr_cont("0x%08x", *ptr.p_s32);
> +		break;
> +	case V4L2_CTRL_TYPE_INTEGER64:
> +		pr_cont("%lld", *ptr.p_s64);
> +		break;
> +	case V4L2_CTRL_TYPE_STRING:
> +		pr_cont("%s", ptr.p_char);
> +		break;
> +	default:
> +		pr_cont("unknown type %d", ctrl->type);
> +		break;
> +	}
> +}
> +
> +/* Round towards the closest legal value */
> +#define ROUND_TO_RANGE(val, offset_type, ctrl)			\
> +({								\
> +	offset_type offset;					\
> +	val += (ctrl)->step / 2;				\
> +	val = clamp_t(typeof(val), val,				\
> +		      (ctrl)->minimum, (ctrl)->maximum);	\
> +	offset = (val) - (ctrl)->minimum;			\
> +	offset = (ctrl)->step * (offset / (ctrl)->step);	\
> +	val = (ctrl)->minimum + offset;				\
> +	0;							\
> +})

Could you use an inline function instead? This doesn't really need to be a
macro, albeit I admit that it's always cool to express one's ability to
write GCC-only macros. :-D

(I just noticed that this patch just moves the macro to a different place,
but I think it was added by an earlier patch in the set.)

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus@iki.fi	XMPP: sailus@retiisi.org.uk

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 02/21] v4l2-ctrls: add unit string.
  2014-01-24 11:19     ` Hans Verkuil
@ 2014-01-24 15:54       ` Sakari Ailus
  2014-01-25  9:00         ` Hans Verkuil
  0 siblings, 1 reply; 56+ messages in thread
From: Sakari Ailus @ 2014-01-24 15:54 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: Hans Verkuil, linux-media, m.chehab, laurent.pinchart,
	t.stanislaws, Hans Verkuil

Hi Hans,

On Fri, Jan 24, 2014 at 12:19:30PM +0100, Hans Verkuil wrote:
> On 01/24/2014 11:35 AM, Sakari Ailus wrote:
> > Hi Hans,
> > 
> > Thanks for the patchset!
> > 
> > On Mon, Jan 20, 2014 at 01:45:55PM +0100, Hans Verkuil wrote:
> >> diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
> >> index 0b347e8..3998049 100644
> >> --- a/include/media/v4l2-ctrls.h
> >> +++ b/include/media/v4l2-ctrls.h
> >> @@ -85,6 +85,7 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
> >>    * @ops:	The control ops.
> >>    * @id:	The control ID.
> >>    * @name:	The control name.
> >> +  * @unit:	The control's unit. May be NULL.
> >>    * @type:	The control type.
> >>    * @minimum:	The control's minimum value.
> >>    * @maximum:	The control's maximum value.
> >> @@ -130,6 +131,7 @@ struct v4l2_ctrl {
> >>  	const struct v4l2_ctrl_ops *ops;
> >>  	u32 id;
> >>  	const char *name;
> >> +	const char *unit;
> > 
> > What would you think of using a numeric value (with the standardised units
> > #defined)? I think using a string begs for unmanaged unit usage. Code that
> > deals with units might work with one driver but not with another since it
> > uses a slightly different string for unit x.
> 
> First of all, you always need a string. You don't want GUIs like qv4l2 to have
> to switch on a unit in order to generate the unit strings. That's impossible to
> keep up to date.

That's true when when you want to show that to the user, yes. But when you
have an application which tries to figure out which value to put to the
control, a numeric value is more convenient.

Kernel interfaces seldom use strings and that's for a good reason.

> In addition, private controls can have really strange custom units, so you want
> to have a string there as well.

Good point as well.

> Standard controls can have their unit string set in v4l2-ctrls.c, just as their
> name is set there these days, thus ensuring consistency.
> 
> What I had in mind is that videodev2.h defines a list of standardized unit strings,
> e.g.:
> 
> #define V4L2_CTRL_UNIT_USECS "usecs"
> #define V4L2_CTRL_UNIT_MSECS "msecs"

That's possible as well, but requires the user to e.g. use if (strcmp())
... instead of just plain switch (unit) { ... }.

I'd also very much prefer to stick to SI units and prefixes where applicable
if we end up using strings. Combining the unit and prefix could make sense.

> and apps can do strcmp(qc->unit, V4L2_CTRL_UNIT_USECS) to see what the unit is.
> If a driver doesn't use one of those standardized unit strings, then it is a
> driver bug.
> 
> > A prefix could be potentially nice, too, so ms and µs would still have the
> > same unit but a different prefix.
> 
> Can you give an example of a prefix? I don't really follow what you want to
> achieve.

You use them in your own example above. :-)

<URL:http://en.wikipedia.org/wiki/SI_prefix>

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus@iki.fi	XMPP: sailus@retiisi.org.uk

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 06/21] v4l2-ctrls: add support for complex types.
  2014-01-24 15:44   ` Sakari Ailus
@ 2014-01-25  8:50     ` Hans Verkuil
  0 siblings, 0 replies; 56+ messages in thread
From: Hans Verkuil @ 2014-01-25  8:50 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

Hi Sakari,

On 01/24/2014 04:44 PM, Sakari Ailus wrote:
> Hi Hans,
> 
> On Mon, Jan 20, 2014 at 01:45:59PM +0100, Hans Verkuil wrote:
>> From: Hans Verkuil <hans.verkuil@cisco.com>
>>
>> This patch implements initial support for complex types.
>>
>> For the most part the changes are fairly obvious (basic support for is_ptr
>> types, the type_is_int function is replaced by a is_int bitfield, and
>> v4l2_query_ext_ctrl is added), but one change needs more explanation:
>>
>> The v4l2_ctrl struct adds a 'new' field and a 'stores' array at the end
>> of the struct. This is in preparation for future patches where each control
>> can have multiple configuration stores. The idea is that stores[0] is the current
>> control value, stores[1] etc. are the control values for each configuration store
>> and the 'new' value can be accessed through 'stores[-1]', i.e. the 'new' field.
>> However, for now only stores[-1] and stores[0] is used.
> 
> Could we use zero or positive indices only, e.g. the new being zero and
> current 1, or the other way? Or make the "new" value special, i.e. using a
> different field name.
> 
> I think accessing the previous struct member by index -1 looks a little bit
> hackish.

I should document this better. Drivers are not expected to use the stores array,
it is for internal use in the control framework only as it allows me to refer to
either the new or the current value by just an array index and later also
configuration stores which will start at index 1 and up, which is where this really
becomes important.

I am not yet adding configuration stores to the control framework as there is not
yet a driver that needs it, and it is for the most part a separate issue anyway.
But this generalization of how values can be accessed makes it much easier to
later add support for configuration stores.

>> These new fields use the v4l2_ctrl_ptr union, which is a pointer to a control
>> value.
>>
>> Note that these two new fields are not yet actually used.
> 
> Should they be then added yet in the first place? :-)

Well, they are used a few patches later, but I will see if it makes sense to only
introduce them when they are actually needed.

Regards,

	Hans

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 08/21] v4l2-ctrls: create type_ops.
  2014-01-24 15:46   ` Sakari Ailus
@ 2014-01-25  8:54     ` Hans Verkuil
  0 siblings, 0 replies; 56+ messages in thread
From: Hans Verkuil @ 2014-01-25  8:54 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, m.chehab, laurent.pinchart, t.stanislaws, Hans Verkuil

Hi Sakari,

On 01/24/2014 04:46 PM, Sakari Ailus wrote:
> Hi Hans,
> 
> On Mon, Jan 20, 2014 at 01:46:01PM +0100, Hans Verkuil wrote:
>> From: Hans Verkuil <hans.verkuil@cisco.com>
>>
>> Since complex controls can have non-standard types we need to be able to do
>> type-specific checks etc. In order to make that easy type operations are added.
>> There are four operations:
>>
>> - equal: check if two values are equal
>> - init: initialize a value
>> - log: log the value
>> - validate: validate a new value
>>
>> This patch uses the v4l2_ctrl_ptr union for the first time.
>>
>> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
>> ---
>>  drivers/media/v4l2-core/v4l2-ctrls.c | 267 ++++++++++++++++++++++-------------
>>  include/media/v4l2-ctrls.h           |  21 +++
>>  2 files changed, 190 insertions(+), 98 deletions(-)
>>
>> diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
>> index 98e940f..9f97af4 100644
>> --- a/drivers/media/v4l2-core/v4l2-ctrls.c
>> +++ b/drivers/media/v4l2-core/v4l2-ctrls.c
>> @@ -1123,6 +1123,149 @@ static void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes)
>>  			v4l2_event_queue_fh(sev->fh, &ev);
>>  }
>>  
>> +static bool std_equal(const struct v4l2_ctrl *ctrl,
>> +		      union v4l2_ctrl_ptr ptr1,
>> +		      union v4l2_ctrl_ptr ptr2)
>> +{
>> +	switch (ctrl->type) {
>> +	case V4L2_CTRL_TYPE_BUTTON:
>> +		return false;
>> +	case V4L2_CTRL_TYPE_STRING:
>> +		/* strings are always 0-terminated */
>> +		return !strcmp(ptr1.p_char, ptr2.p_char);
>> +	case V4L2_CTRL_TYPE_INTEGER64:
>> +		return *ptr1.p_s64 == *ptr2.p_s64;
> 
> The above two lines seem redundant to me.

Why? How else would you compare two 64-bit integers?

> 
>> +	default:
>> +		if (ctrl->is_ptr)
>> +			return !memcmp(ptr1.p, ptr2.p, ctrl->elem_size);
>> +		return *ptr1.p_s32 == *ptr2.p_s32;
>> +	}
>> +}
>> +
>> +static void std_init(const struct v4l2_ctrl *ctrl,
>> +		     union v4l2_ctrl_ptr ptr)
>> +{
>> +	switch (ctrl->type) {
>> +	case V4L2_CTRL_TYPE_STRING:
>> +		memset(ptr.p_char, ' ', ctrl->minimum);
>> +		ptr.p_char[ctrl->minimum] = '\0';
>> +		break;
>> +	case V4L2_CTRL_TYPE_INTEGER64:
>> +		*ptr.p_s64 = ctrl->default_value;
>> +		break;
>> +	case V4L2_CTRL_TYPE_INTEGER:
>> +	case V4L2_CTRL_TYPE_INTEGER_MENU:
>> +	case V4L2_CTRL_TYPE_MENU:
>> +	case V4L2_CTRL_TYPE_BITMASK:
>> +	case V4L2_CTRL_TYPE_BOOLEAN:
>> +		*ptr.p_s32 = ctrl->default_value;
>> +		break;
>> +	default:
>> +		break;
>> +	}
>> +}
>> +
>> +static void std_log(const struct v4l2_ctrl *ctrl)
>> +{
>> +	union v4l2_ctrl_ptr ptr = ctrl->stores[0];
>> +
>> +	switch (ctrl->type) {
>> +	case V4L2_CTRL_TYPE_INTEGER:
>> +		pr_cont("%d", *ptr.p_s32);
>> +		break;
>> +	case V4L2_CTRL_TYPE_BOOLEAN:
>> +		pr_cont("%s", *ptr.p_s32 ? "true" : "false");
>> +		break;
>> +	case V4L2_CTRL_TYPE_MENU:
>> +		pr_cont("%s", ctrl->qmenu[*ptr.p_s32]);
>> +		break;
>> +	case V4L2_CTRL_TYPE_INTEGER_MENU:
>> +		pr_cont("%lld", ctrl->qmenu_int[*ptr.p_s32]);
>> +		break;
>> +	case V4L2_CTRL_TYPE_BITMASK:
>> +		pr_cont("0x%08x", *ptr.p_s32);
>> +		break;
>> +	case V4L2_CTRL_TYPE_INTEGER64:
>> +		pr_cont("%lld", *ptr.p_s64);
>> +		break;
>> +	case V4L2_CTRL_TYPE_STRING:
>> +		pr_cont("%s", ptr.p_char);
>> +		break;
>> +	default:
>> +		pr_cont("unknown type %d", ctrl->type);
>> +		break;
>> +	}
>> +}
>> +
>> +/* Round towards the closest legal value */
>> +#define ROUND_TO_RANGE(val, offset_type, ctrl)			\
>> +({								\
>> +	offset_type offset;					\
>> +	val += (ctrl)->step / 2;				\
>> +	val = clamp_t(typeof(val), val,				\
>> +		      (ctrl)->minimum, (ctrl)->maximum);	\
>> +	offset = (val) - (ctrl)->minimum;			\
>> +	offset = (ctrl)->step * (offset / (ctrl)->step);	\
>> +	val = (ctrl)->minimum + offset;				\
>> +	0;							\
>> +})
> 
> Could you use an inline function instead? This doesn't really need to be a
> macro, albeit I admit that it's always cool to express one's ability to
> write GCC-only macros. :-D
> 
> (I just noticed that this patch just moves the macro to a different place,
> but I think it was added by an earlier patch in the set.)
> 

I'll see what I can do, although I am not going to spend a huge amount of time
on this :-)

Regards,

	Hans

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFCv2 PATCH 02/21] v4l2-ctrls: add unit string.
  2014-01-24 15:54       ` Sakari Ailus
@ 2014-01-25  9:00         ` Hans Verkuil
  0 siblings, 0 replies; 56+ messages in thread
From: Hans Verkuil @ 2014-01-25  9:00 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Hans Verkuil, linux-media, m.chehab, laurent.pinchart,
	t.stanislaws, Hans Verkuil

Hi Sakari,

On 01/24/2014 04:54 PM, Sakari Ailus wrote:
> Hi Hans,
> 
> On Fri, Jan 24, 2014 at 12:19:30PM +0100, Hans Verkuil wrote:
>> On 01/24/2014 11:35 AM, Sakari Ailus wrote:
>>> Hi Hans,
>>>
>>> Thanks for the patchset!
>>>
>>> On Mon, Jan 20, 2014 at 01:45:55PM +0100, Hans Verkuil wrote:
>>>> diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
>>>> index 0b347e8..3998049 100644
>>>> --- a/include/media/v4l2-ctrls.h
>>>> +++ b/include/media/v4l2-ctrls.h
>>>> @@ -85,6 +85,7 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
>>>>    * @ops:	The control ops.
>>>>    * @id:	The control ID.
>>>>    * @name:	The control name.
>>>> +  * @unit:	The control's unit. May be NULL.
>>>>    * @type:	The control type.
>>>>    * @minimum:	The control's minimum value.
>>>>    * @maximum:	The control's maximum value.
>>>> @@ -130,6 +131,7 @@ struct v4l2_ctrl {
>>>>  	const struct v4l2_ctrl_ops *ops;
>>>>  	u32 id;
>>>>  	const char *name;
>>>> +	const char *unit;
>>>
>>> What would you think of using a numeric value (with the standardised units
>>> #defined)? I think using a string begs for unmanaged unit usage. Code that
>>> deals with units might work with one driver but not with another since it
>>> uses a slightly different string for unit x.
>>
>> First of all, you always need a string. You don't want GUIs like qv4l2 to have
>> to switch on a unit in order to generate the unit strings. That's impossible to
>> keep up to date.
> 
> That's true when when you want to show that to the user, yes. But when you
> have an application which tries to figure out which value to put to the
> control, a numeric value is more convenient.
> 
> Kernel interfaces seldom use strings and that's for a good reason.

Well, actually, the kernel is in many places moving away from IDs to strings.
Headers full of IDs are surprisingly hard to maintain.

> 
>> In addition, private controls can have really strange custom units, so you want
>> to have a string there as well.
> 
> Good point as well.
> 
>> Standard controls can have their unit string set in v4l2-ctrls.c, just as their
>> name is set there these days, thus ensuring consistency.
>>
>> What I had in mind is that videodev2.h defines a list of standardized unit strings,
>> e.g.:
>>
>> #define V4L2_CTRL_UNIT_USECS "usecs"
>> #define V4L2_CTRL_UNIT_MSECS "msecs"
> 
> That's possible as well, but requires the user to e.g. use if (strcmp())
> ... instead of just plain switch (unit) { ... }.
> 
> I'd also very much prefer to stick to SI units and prefixes where applicable
> if we end up using strings. Combining the unit and prefix could make sense.
> 
>> and apps can do strcmp(qc->unit, V4L2_CTRL_UNIT_USECS) to see what the unit is.
>> If a driver doesn't use one of those standardized unit strings, then it is a
>> driver bug.
>>
>>> A prefix could be potentially nice, too, so ms and µs would still have the
>>> same unit but a different prefix.
>>
>> Can you give an example of a prefix? I don't really follow what you want to
>> achieve.
> 
> You use them in your own example above. :-)
> 
> <URL:http://en.wikipedia.org/wiki/SI_prefix>
> 

Ah, that sort of prefix.

I don't think the prefix makes sense, for a number of reasons: first I think it
makes life even harder for applications, since they now have to factor in a SI
prefix as well. Secondly, what to do with units like km/s? There are two prefixes
there (e.g. mm/usecs is also a valid speed representation).

I think that for the initial version we just add the unit string as that is needed
anyway. There are more than enough reserved fields available to add a unit_id field
later, but frankly, I'd like to see some real-life use-cases first.

Regards,

	Hans

^ permalink raw reply	[flat|nested] 56+ messages in thread

end of thread, other threads:[~2014-01-25  9:00 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-01-20 12:45 [RFCv2 PATCH 00/21] Add support for complex controls Hans Verkuil
2014-01-20 12:45 ` [RFCv2 PATCH 01/21] v4l2-ctrls: increase internal min/max/step/def to 64 bit Hans Verkuil
2014-01-22 22:45   ` Sylwester Nawrocki
2014-01-20 12:45 ` [RFCv2 PATCH 02/21] v4l2-ctrls: add unit string Hans Verkuil
2014-01-22 22:47   ` Sylwester Nawrocki
2014-01-24 10:35   ` Sakari Ailus
2014-01-24 11:19     ` Hans Verkuil
2014-01-24 15:54       ` Sakari Ailus
2014-01-25  9:00         ` Hans Verkuil
2014-01-20 12:45 ` [RFCv2 PATCH 03/21] v4l2-ctrls: use pr_info/cont instead of printk Hans Verkuil
2014-01-22 22:48   ` Sylwester Nawrocki
2014-01-20 12:45 ` [RFCv2 PATCH 04/21] videodev2.h: add initial support for complex controls Hans Verkuil
2014-01-22 22:55   ` Sylwester Nawrocki
2014-01-20 12:45 ` [RFCv2 PATCH 05/21] videodev2.h: add struct v4l2_query_ext_ctrl and VIDIOC_QUERY_EXT_CTRL Hans Verkuil
2014-01-22 23:02   ` Sylwester Nawrocki
2014-01-23 14:23     ` Hans Verkuil
2014-01-23 15:05       ` Sylwester Nawrocki
2014-01-24 11:28   ` Sakari Ailus
2014-01-24 11:58     ` Hans Verkuil
2014-01-20 12:45 ` [RFCv2 PATCH 06/21] v4l2-ctrls: add support for complex types Hans Verkuil
2014-01-23 11:44   ` Sylwester Nawrocki
2014-01-24 15:44   ` Sakari Ailus
2014-01-25  8:50     ` Hans Verkuil
2014-01-20 12:46 ` [RFCv2 PATCH 07/21] v4l2: integrate support for VIDIOC_QUERY_EXT_CTRL Hans Verkuil
2014-01-23 11:44   ` Sylwester Nawrocki
2014-01-20 12:46 ` [RFCv2 PATCH 08/21] v4l2-ctrls: create type_ops Hans Verkuil
2014-01-23 14:23   ` Sylwester Nawrocki
2014-01-24 15:46   ` Sakari Ailus
2014-01-25  8:54     ` Hans Verkuil
2014-01-20 12:46 ` [RFCv2 PATCH 09/21] v4l2-ctrls: rewrite copy routines to operate on union v4l2_ctrl_ptr Hans Verkuil
2014-01-24 12:31   ` Sakari Ailus
2014-01-24 12:44     ` Hans Verkuil
2014-01-20 12:46 ` [RFCv2 PATCH 10/21] v4l2-ctrls: compare values only once Hans Verkuil
2014-01-23 14:30   ` Sylwester Nawrocki
2014-01-20 12:46 ` [RFCv2 PATCH 11/21] v4l2-ctrls: prepare for matrix support: add cols & rows fields Hans Verkuil
2014-01-23 13:46   ` Sylwester Nawrocki
2014-01-20 12:46 ` [RFCv2 PATCH 12/21] v4l2-ctrls: replace cur by a union v4l2_ctrl_ptr Hans Verkuil
2014-01-23 15:47   ` Sylwester Nawrocki
2014-01-20 12:46 ` [RFCv2 PATCH 13/21] v4l2-ctrls: use 'new' to access pointer controls Hans Verkuil
2014-01-23 17:06   ` Sylwester Nawrocki
2014-01-20 12:46 ` [RFCv2 PATCH 14/21] v4l2-ctrls: prepare for matrix support Hans Verkuil
2014-01-20 12:46 ` [RFCv2 PATCH 15/21] v4l2-ctrls: type_ops can handle matrix elements Hans Verkuil
2014-01-20 12:46 ` [RFCv2 PATCH 16/21] v4l2-ctrls: add matrix support Hans Verkuil
2014-01-20 12:46 ` [RFCv2 PATCH 17/21] v4l2-ctrls.c: return elem_size instead of strlen Hans Verkuil
2014-01-23 13:46   ` Sylwester Nawrocki
2014-01-20 12:46 ` [RFCv2 PATCH 18/21] DocBook media: document VIDIOC_QUERY_EXT_CTRL Hans Verkuil
2014-01-23 17:24   ` Sylwester Nawrocki
2014-01-20 12:46 ` [RFCv2 PATCH 19/21] DocBook media: update VIDIOC_G/S/TRY_EXT_CTRLS Hans Verkuil
2014-01-23 13:46   ` Sylwester Nawrocki
2014-01-23 14:16     ` Hans Verkuil
2014-01-20 12:46 ` [RFCv2 PATCH 20/21] DocBook media: update control section Hans Verkuil
2014-01-23 15:34   ` Sylwester Nawrocki
2014-01-20 12:46 ` [RFCv2 PATCH 21/21] v4l2-controls.txt: update to the new way of accessing controls Hans Verkuil
2014-01-23 15:50   ` Sylwester Nawrocki
2014-01-22 22:44 ` [RFCv2 PATCH 00/21] Add support for complex controls Sylwester Nawrocki
2014-01-23 11:49   ` Hans Verkuil

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.