[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:
Hans Verkuil 2014-07-21 10:45:42 -03:00 коммит произвёл Mauro Carvalho Chehab
Родитель 592d1349f7
Коммит 5d0360a4f0
2 изменённых файлов: 44 добавлений и 27 удалений

Просмотреть файл

@ -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);