[media] v4l2-ctrls: add support for setting string controls
Rather than always having to use a v4l2_ext_control struct to set a control value from within a driver, switch to just setting the new value. This is faster and it makes it possible to set more complex types such as a string control as is added by this patch. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
This commit is contained in:
Родитель
592d1349f7
Коммит
5d0360a4f0
|
@ -3121,26 +3121,22 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
|
||||||
struct v4l2_ctrl *master = ctrl->cluster[0];
|
struct v4l2_ctrl *master = ctrl->cluster[0];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Compound 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->is_ptr)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* Reset the 'is_new' flags of the cluster */
|
/* Reset the 'is_new' flags of the cluster */
|
||||||
for (i = 0; i < master->ncontrols; i++)
|
for (i = 0; i < master->ncontrols; i++)
|
||||||
if (master->cluster[i])
|
if (master->cluster[i])
|
||||||
master->cluster[i]->is_new = 0;
|
master->cluster[i]->is_new = 0;
|
||||||
|
|
||||||
|
if (c)
|
||||||
|
user_to_new(c, ctrl);
|
||||||
|
|
||||||
/* For autoclusters with volatiles that are switched from auto to
|
/* For autoclusters with volatiles that are switched from auto to
|
||||||
manual mode we have to update the current volatile values since
|
manual mode we have to update the current volatile values since
|
||||||
those will become the initial manual values after such a switch. */
|
those will become the initial manual values after such a switch. */
|
||||||
if (master->is_auto && master->has_volatiles && ctrl == master &&
|
if (master->is_auto && master->has_volatiles && ctrl == master &&
|
||||||
!is_cur_manual(master) && c->value == master->manual_mode_value)
|
!is_cur_manual(master) && ctrl->val == master->manual_mode_value)
|
||||||
update_from_auto_cluster(master);
|
update_from_auto_cluster(master);
|
||||||
|
|
||||||
user_to_new(c, ctrl);
|
ctrl->is_new = 1;
|
||||||
return try_or_set_cluster(fh, master, true, ch_flags);
|
return try_or_set_cluster(fh, master, true, ch_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3188,40 +3184,37 @@ EXPORT_SYMBOL(v4l2_subdev_s_ctrl);
|
||||||
|
|
||||||
int __v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
|
int __v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
|
||||||
{
|
{
|
||||||
struct v4l2_ext_control c;
|
|
||||||
int rval;
|
|
||||||
|
|
||||||
lockdep_assert_held(ctrl->handler->lock);
|
lockdep_assert_held(ctrl->handler->lock);
|
||||||
|
|
||||||
/* It's a driver bug if this happens. */
|
/* It's a driver bug if this happens. */
|
||||||
WARN_ON(!ctrl->is_int);
|
WARN_ON(!ctrl->is_int);
|
||||||
c.value = val;
|
ctrl->val = val;
|
||||||
rval = set_ctrl(NULL, ctrl, &c, 0);
|
return set_ctrl(NULL, ctrl, NULL, 0);
|
||||||
if (!rval)
|
|
||||||
cur_to_user(&c, ctrl);
|
|
||||||
|
|
||||||
return rval;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl);
|
EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl);
|
||||||
|
|
||||||
int __v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)
|
int __v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)
|
||||||
{
|
{
|
||||||
struct v4l2_ext_control c;
|
|
||||||
int rval;
|
|
||||||
|
|
||||||
lockdep_assert_held(ctrl->handler->lock);
|
lockdep_assert_held(ctrl->handler->lock);
|
||||||
|
|
||||||
/* It's a driver bug if this happens. */
|
/* It's a driver bug if this happens. */
|
||||||
WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
|
WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
|
||||||
c.value64 = val;
|
*ctrl->p_new.p_s64 = val;
|
||||||
rval = set_ctrl(NULL, ctrl, &c, 0);
|
return set_ctrl(NULL, ctrl, NULL, 0);
|
||||||
if (!rval)
|
|
||||||
cur_to_user(&c, ctrl);
|
|
||||||
|
|
||||||
return rval;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_int64);
|
EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_int64);
|
||||||
|
|
||||||
|
int __v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s)
|
||||||
|
{
|
||||||
|
lockdep_assert_held(ctrl->handler->lock);
|
||||||
|
|
||||||
|
/* It's a driver bug if this happens. */
|
||||||
|
WARN_ON(ctrl->type != V4L2_CTRL_TYPE_STRING);
|
||||||
|
strlcpy(ctrl->p_new.p_char, s, ctrl->maximum + 1);
|
||||||
|
return set_ctrl(NULL, ctrl, NULL, 0);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_string);
|
||||||
|
|
||||||
void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void *priv)
|
void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void *priv)
|
||||||
{
|
{
|
||||||
if (ctrl == NULL)
|
if (ctrl == NULL)
|
||||||
|
|
|
@ -737,6 +737,30 @@ static inline int v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** __v4l2_ctrl_s_ctrl_string() - Unlocked variant of v4l2_ctrl_s_ctrl_string(). */
|
||||||
|
int __v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s);
|
||||||
|
|
||||||
|
/** v4l2_ctrl_s_ctrl_string() - Helper function to set a control's string value from within a driver.
|
||||||
|
* @ctrl: The control.
|
||||||
|
* @s: The new string.
|
||||||
|
*
|
||||||
|
* This set the control's new string safely by going through the control
|
||||||
|
* framework. This function will lock the control's handler, so it cannot be
|
||||||
|
* used from within the &v4l2_ctrl_ops functions.
|
||||||
|
*
|
||||||
|
* This function is for string type controls only.
|
||||||
|
*/
|
||||||
|
static inline int v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s)
|
||||||
|
{
|
||||||
|
int rval;
|
||||||
|
|
||||||
|
v4l2_ctrl_lock(ctrl);
|
||||||
|
rval = __v4l2_ctrl_s_ctrl_string(ctrl, s);
|
||||||
|
v4l2_ctrl_unlock(ctrl);
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
/* Internal helper functions that deal with control events. */
|
/* Internal helper functions that deal with control events. */
|
||||||
extern const struct v4l2_subscribed_event_ops v4l2_ctrl_sub_ev_ops;
|
extern const struct v4l2_subscribed_event_ops v4l2_ctrl_sub_ev_ops;
|
||||||
void v4l2_ctrl_replace(struct v4l2_event *old, const struct v4l2_event *new);
|
void v4l2_ctrl_replace(struct v4l2_event *old, const struct v4l2_event *new);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче