[media] v4l2-ctrls: add a notify callback

Sometimes platform/bridge drivers need to be notified when a control from
a sub-device changes value. In order to support this a notify callback was
added.
[dheitmueller@kernellabs.com: fix merge conflict in v4l2-ctrls.c]

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Hans Verkuil 2012-09-07 04:46:39 -03:00 committed by Mauro Carvalho Chehab
parent 20deebfe17
commit 8ac7a9493a
3 changed files with 57 additions and 8 deletions

View file

@ -715,14 +715,20 @@ a control of this type whenever the first control belonging to a new control
class is added.
Proposals for Extensions
========================
Adding Notify Callbacks
=======================
Some ideas for future extensions to the spec:
Sometimes the platform or bridge driver needs to be notified when a control
from a sub-device driver changes. You can set a notify callback by calling
this function:
1) Add a V4L2_CTRL_FLAG_HEX to have values shown as hexadecimal instead of
decimal. Useful for e.g. video_mute_yuv.
void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl,
void (*notify)(struct v4l2_ctrl *ctrl, void *priv), void *priv);
2) It is possible to mark in the controls array which controls have been
successfully written and which failed by for example adding a bit to the
control ID. Not sure if it is worth the effort, though.
Whenever the give control changes value the notify callback will be called
with a pointer to the control and the priv pointer that was passed with
v4l2_ctrl_notify. Note that the control's handler lock is held when the
notify function is called.
There can be only one notify function per control handler. Any attempt
to set another notify function will cause a WARN_ON.

View file

@ -1204,6 +1204,8 @@ static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
send_event(fh, ctrl,
(changed ? V4L2_EVENT_CTRL_CH_VALUE : 0) |
(update_inactive ? V4L2_EVENT_CTRL_CH_FLAGS : 0));
if (ctrl->call_notify && changed && ctrl->handler->notify)
ctrl->handler->notify(ctrl, ctrl->handler->notify_priv);
}
}
@ -2725,6 +2727,22 @@ int v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)
}
EXPORT_SYMBOL(v4l2_ctrl_s_ctrl_int64);
void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void *priv)
{
if (ctrl == NULL)
return;
if (notify == NULL) {
ctrl->call_notify = 0;
return;
}
if (WARN_ON(ctrl->handler->notify && ctrl->handler->notify != notify))
return;
ctrl->handler->notify = notify;
ctrl->handler->notify_priv = priv;
ctrl->call_notify = 1;
}
EXPORT_SYMBOL(v4l2_ctrl_notify);
static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems)
{
struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id);

View file

@ -53,6 +53,8 @@ struct v4l2_ctrl_ops {
int (*s_ctrl)(struct v4l2_ctrl *ctrl);
};
typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
/** struct v4l2_ctrl - The control structure.
* @node: The list node.
* @ev_subs: The list of control event subscriptions.
@ -72,6 +74,8 @@ struct v4l2_ctrl_ops {
* set this flag directly.
* @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
* control's value changes.
* @manual_mode_value: If the is_auto flag is set, then this is the value
* of the auto control that determines if that control is in
* manual mode. So if the value of the auto control equals this
@ -119,6 +123,7 @@ struct v4l2_ctrl {
unsigned int is_private:1;
unsigned int is_auto:1;
unsigned int has_volatiles:1;
unsigned int call_notify:1;
unsigned int manual_mode_value:8;
const struct v4l2_ctrl_ops *ops;
@ -177,6 +182,10 @@ struct v4l2_ctrl_ref {
* control is needed multiple times, so this is a simple
* optimization.
* @buckets: Buckets for the hashing. Allows for quick control lookup.
* @notify: A notify callback that is called whenever the control changes value.
* Note that the handler's lock is held when the notify function
* is called!
* @notify_priv: Passed as argument to the v4l2_ctrl notify callback.
* @nr_of_buckets: Total number of buckets in the array.
* @error: The error code of the first failed control addition.
*/
@ -187,6 +196,8 @@ struct v4l2_ctrl_handler {
struct list_head ctrl_refs;
struct v4l2_ctrl_ref *cached;
struct v4l2_ctrl_ref **buckets;
v4l2_ctrl_notify_fnc notify;
void *notify_priv;
u16 nr_of_buckets;
int error;
};
@ -525,6 +536,20 @@ static inline void v4l2_ctrl_unlock(struct v4l2_ctrl *ctrl)
mutex_unlock(ctrl->handler->lock);
}
/** v4l2_ctrl_notify() - Function to set a notify callback for a control.
* @ctrl: The control.
* @notify: The callback function.
* @priv: The callback private handle, passed as argument to the callback.
*
* This function sets a callback function for the control. If @ctrl is NULL,
* then it will do nothing. If @notify is NULL, then the notify callback will
* be removed.
*
* There can be only one notify. If another already exists, then a WARN_ON
* will be issued and the function will do nothing.
*/
void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void *priv);
/** v4l2_ctrl_g_ctrl() - Helper function to get the control's value from within a driver.
* @ctrl: The control.
*