From: Hans Verkuil <hverkuil@xs4all.nl>
To: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
Cc: linux-media <linux-media@vger.kernel.org>,
Mauro Carvalho Chehab <m.chehab@samsung.com>,
Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Sylwester Nawrocki <s.nawrocki@samsung.com>,
Ismael Luceno <ismael.luceno@corp.bluecherry.net>,
pete@sensoray.com, Hans Verkuil <hans.verkuil@cisco.com>
Subject: Re: [REVIEWv2 PATCH 08/34] v4l2-ctrls: create type_ops.
Date: Wed, 12 Feb 2014 13:31:22 +0100 [thread overview]
Message-ID: <52FB699A.8080103@xs4all.nl> (raw)
In-Reply-To: <CAPybu_1U5vGdB9nDeEO71nfE3TrYrWnpngof9ook40dYg9zh9Q@mail.gmail.com>
On 02/12/14 13:03, Ricardo Ribalda Delgado wrote:
> Hello Hans
>
> My usercase is different gain and offset per pixel (non uniformity
> correction). My sensor is now 4 Mpx, and probably 12 Mpx soon :)
The hardware actually supports per pixel gain and offset?! Wow.
Anyway, I am not opposed to making changes in this area (although I want
this to be merged first), provided you also do some performance measurements.
I am also assuming that such large matrices only rarely change, so to
what extent performance improvements have any real-life effect may be
debatable.
Regards,
Hans
>
> Right now it is implemented as a video output... but I think that I am
> exploiting an API :)
>
> Regards!
>
> On Wed, Feb 12, 2014 at 12:36 PM, Hans Verkuil <hverkuil@xs4all.nl> wrote:
>> On 02/12/14 11:55, Ricardo Ribalda Delgado wrote:
>>> Hello Hans
>>>
>>> If we have a matrix control with a huge number of elements (ie, the
>>> number of pixels), a control validation will imply over ahuge number
>>> of function calls.
>>>
>>> In the case of the matrix you are always validating/init all the
>>> values of of the array. Why dont we modify the type_ops so they
>>> operate on the whole matrix (remove the idx from the function).
>>
>> I actually considered that, but rejected it (for now) because I want
>> to see a realistic use-case first. If you get such large matrices, then
>> you have to ask yourself whether the control framework is the right
>> approach anyway, and if it is, whether you want to do these validations
>> in the first place.
>>
>> Also note that validations typically will still have to be done on a
>> per-element basis (so pushing down the loop over all elements into the
>> validation function will have little effect) and ditto for the more
>> complex comparisons. Only if you are able to do something like memcmp
>> to compare two matrices will it become beneficial to optimize this.
>>
>> I see this as a possible future performance enhancement and before doing
>> that I need to see a good use-case and also see some performence measurements.
>>
>>> Anyway we should modify
>>>
>>> for (idx = 0; idx < ctrl->rows * ctrl->cols; idx++)
>>> ctrl_changed |= !ctrl->type_ops->equal(ctrl, idx,
>>> ctrl->stores[0], ctrl->new);
>>>
>>> to
>>>
>>> for (idx = 0; idx < ctrl->rows * ctrl->cols; idx++)
>>> if (!ctrl->type_ops->equal(ctrl, idx, ctrl->stores[0],
>>> ctrl->new))
>>> break
>>>
>>> if (idx==ctrl->rows * ctrl->col)
>>> ctrol_changed=true;
>>>
>>> Saving us some calls when we already know that the control has changed.
>>
>> Oops! Absolutely, thanks for pointing this out. That's a left-over from
>> older code.
>>
>> I'll post a patch for this.
>>
>> Regards,
>>
>> Hans
>>
>>>
>>>
>>> Thanks!
>>>
>>>
>>> ps: consider all my code pseudocode :P
>>>
>>>
>>> On Mon, Feb 10, 2014 at 9:46 AM, Hans Verkuil <hverkuil@xs4all.nl> 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>
>>>> Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.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 67e5d1e..988a2bd8 100644
>>>> --- a/drivers/media/v4l2-core/v4l2-ctrls.c
>>>> +++ b/drivers/media/v4l2-core/v4l2-ctrls.c
>>>> @@ -1132,6 +1132,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)
>>>> @@ -1315,21 +1458,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;
>>>> }
>>>> @@ -1370,65 +1499,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);
>>>> }
>>>> }
>>>>
>>>> @@ -1645,6 +1739,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,
>>>> @@ -1656,6 +1751,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;
>>>> @@ -1715,6 +1811,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;
>>>> @@ -1736,19 +1833,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;
>>>> @@ -1793,7 +1887,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,
>>>> @@ -1821,7 +1915,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);
>>>> }
>>>> @@ -1855,7 +1949,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);
>>>> }
>>>> @@ -1888,7 +1982,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);
>>>>
>>>> }
>>>> @@ -1913,7 +2008,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);
>>>> }
>>>> @@ -2096,32 +2191,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 515c1ba..aaf7333 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
>>>>
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-media" in
>>>> the body of a message to majordomo@vger.kernel.org
>>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>
>>>
>>>
>>
>
>
>
next prev parent reply other threads:[~2014-02-12 12:35 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-02-10 8:46 [REVIEWv2 PATCH 00/34] Add support for complex controls, use in solo/go7007 Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 01/34] v4l2-ctrls: increase internal min/max/step/def to 64 bit Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 02/34] v4l2-ctrls: add unit string Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 03/34] v4l2-ctrls: use pr_info/cont instead of printk Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 04/34] videodev2.h: add initial support for complex controls Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 05/34] videodev2.h: add struct v4l2_query_ext_ctrl and VIDIOC_QUERY_EXT_CTRL Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 06/34] v4l2-ctrls: add support for complex types Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 07/34] v4l2: integrate support for VIDIOC_QUERY_EXT_CTRL Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 08/34] v4l2-ctrls: create type_ops Hans Verkuil
2014-02-12 10:55 ` Ricardo Ribalda Delgado
2014-02-12 11:36 ` Hans Verkuil
2014-02-12 12:03 ` Ricardo Ribalda Delgado
2014-02-12 12:31 ` Hans Verkuil [this message]
2014-02-12 13:03 ` Ricardo Ribalda Delgado
2014-02-10 8:46 ` [REVIEWv2 PATCH 09/34] v4l2-ctrls: rewrite copy routines to operate on union v4l2_ctrl_ptr Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 10/34] v4l2-ctrls: compare values only once Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 11/34] v4l2-ctrls: prepare for matrix support: add cols & rows fields Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 12/34] v4l2-ctrls: replace cur by a union v4l2_ctrl_ptr Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 13/34] v4l2-ctrls: use 'new' to access pointer controls Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 14/34] v4l2-ctrls: prepare for matrix support Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 15/34] v4l2-ctrls: type_ops can handle matrix elements Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 16/34] v4l2-ctrls: add matrix support Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 17/34] v4l2-ctrls: return elem_size instead of strlen Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 18/34] v4l2-ctrl: fix error return of copy_to/from_user Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 19/34] DocBook media: document VIDIOC_QUERY_EXT_CTRL Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 20/34] DocBook media: update VIDIOC_G/S/TRY_EXT_CTRLS Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 21/34] DocBook media: fix coding style in the control example code Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 22/34] DocBook media: update control section Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 23/34] v4l2-controls.txt: update to the new way of accessing controls Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 24/34] v4l2-ctrls/videodev2.h: add u8 and u16 types Hans Verkuil
2014-02-12 10:44 ` Ricardo Ribalda Delgado
2014-02-12 11:20 ` Hans Verkuil
2014-02-12 12:11 ` Ricardo Ribalda Delgado
2014-02-12 12:40 ` Hans Verkuil
2014-02-12 13:13 ` Ricardo Ribalda Delgado
2014-02-12 13:26 ` Hans Verkuil
2014-02-12 13:40 ` Ricardo Ribalda Delgado
2014-02-12 14:05 ` Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 25/34] DocBook media: document new u8 and u16 control types Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 26/34] v4l2-ctrls: fix comments Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 27/34] v4l2-ctrls/v4l2-controls.h: add MD controls Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 28/34] DocBook media: document new motion detection controls Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 29/34] v4l2: add a motion detection event Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 30/34] DocBook: document new v4l " Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 31/34] solo6x10: implement the new motion detection controls Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 32/34] solo6x10: implement the motion detection event Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 33/34] solo6x10: fix 'dma from stack' warning Hans Verkuil
2014-02-10 8:46 ` [REVIEWv2 PATCH 34/34] go7007: add motion detection support Hans Verkuil
2014-02-12 7:56 ` [REVIEWv2 PATCH 35/34] DocBook media: clarify how the matrix maps to the grid Hans Verkuil
2014-02-12 11:39 ` [REVIEWv2 PATCH 36/34] v4l2-ctrls: break off loop on first changed element Hans Verkuil
2014-02-16 20:14 ` [REVIEWv2 PATCH 00/34] Add support for complex controls, use in solo/go7007 Sakari Ailus
2014-02-17 9:45 ` Hans Verkuil
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=52FB699A.8080103@xs4all.nl \
--to=hverkuil@xs4all.nl \
--cc=hans.verkuil@cisco.com \
--cc=ismael.luceno@corp.bluecherry.net \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-media@vger.kernel.org \
--cc=m.chehab@samsung.com \
--cc=pete@sensoray.com \
--cc=ricardo.ribalda@gmail.com \
--cc=s.nawrocki@samsung.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox