[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:
parent
20deebfe17
commit
8ac7a9493a
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user