summaryrefslogtreecommitdiffstats
path: root/drivers/media/video/v4l2-ctrls.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/v4l2-ctrls.c')
-rw-r--r--drivers/media/video/v4l2-ctrls.c89
1 files changed, 53 insertions, 36 deletions
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 9d2502cd03f..ef66d2af0c5 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -38,15 +38,15 @@ struct ctrl_helper {
the given control ID. The pointer array ends with a NULL pointer.
An empty string signifies a menu entry that is invalid. This allows
drivers to disable certain options if it is not supported. */
-const char **v4l2_ctrl_get_menu(u32 id)
+const char * const *v4l2_ctrl_get_menu(u32 id)
{
- static const char *mpeg_audio_sampling_freq[] = {
+ static const char * const mpeg_audio_sampling_freq[] = {
"44.1 kHz",
"48 kHz",
"32 kHz",
NULL
};
- static const char *mpeg_audio_encoding[] = {
+ static const char * const mpeg_audio_encoding[] = {
"MPEG-1/2 Layer I",
"MPEG-1/2 Layer II",
"MPEG-1/2 Layer III",
@@ -54,7 +54,7 @@ const char **v4l2_ctrl_get_menu(u32 id)
"AC-3",
NULL
};
- static const char *mpeg_audio_l1_bitrate[] = {
+ static const char * const mpeg_audio_l1_bitrate[] = {
"32 kbps",
"64 kbps",
"96 kbps",
@@ -71,7 +71,7 @@ const char **v4l2_ctrl_get_menu(u32 id)
"448 kbps",
NULL
};
- static const char *mpeg_audio_l2_bitrate[] = {
+ static const char * const mpeg_audio_l2_bitrate[] = {
"32 kbps",
"48 kbps",
"56 kbps",
@@ -88,7 +88,7 @@ const char **v4l2_ctrl_get_menu(u32 id)
"384 kbps",
NULL
};
- static const char *mpeg_audio_l3_bitrate[] = {
+ static const char * const mpeg_audio_l3_bitrate[] = {
"32 kbps",
"40 kbps",
"48 kbps",
@@ -105,7 +105,7 @@ const char **v4l2_ctrl_get_menu(u32 id)
"320 kbps",
NULL
};
- static const char *mpeg_audio_ac3_bitrate[] = {
+ static const char * const mpeg_audio_ac3_bitrate[] = {
"32 kbps",
"40 kbps",
"48 kbps",
@@ -127,50 +127,50 @@ const char **v4l2_ctrl_get_menu(u32 id)
"640 kbps",
NULL
};
- static const char *mpeg_audio_mode[] = {
+ static const char * const mpeg_audio_mode[] = {
"Stereo",
"Joint Stereo",
"Dual",
"Mono",
NULL
};
- static const char *mpeg_audio_mode_extension[] = {
+ static const char * const mpeg_audio_mode_extension[] = {
"Bound 4",
"Bound 8",
"Bound 12",
"Bound 16",
NULL
};
- static const char *mpeg_audio_emphasis[] = {
+ static const char * const mpeg_audio_emphasis[] = {
"No Emphasis",
"50/15 us",
"CCITT J17",
NULL
};
- static const char *mpeg_audio_crc[] = {
+ static const char * const mpeg_audio_crc[] = {
"No CRC",
"16-bit CRC",
NULL
};
- static const char *mpeg_video_encoding[] = {
+ static const char * const mpeg_video_encoding[] = {
"MPEG-1",
"MPEG-2",
"MPEG-4 AVC",
NULL
};
- static const char *mpeg_video_aspect[] = {
+ static const char * const mpeg_video_aspect[] = {
"1x1",
"4x3",
"16x9",
"2.21x1",
NULL
};
- static const char *mpeg_video_bitrate_mode[] = {
+ static const char * const mpeg_video_bitrate_mode[] = {
"Variable Bitrate",
"Constant Bitrate",
NULL
};
- static const char *mpeg_stream_type[] = {
+ static const char * const mpeg_stream_type[] = {
"MPEG-2 Program Stream",
"MPEG-2 Transport Stream",
"MPEG-1 System Stream",
@@ -179,25 +179,25 @@ const char **v4l2_ctrl_get_menu(u32 id)
"MPEG-2 SVCD-compatible Stream",
NULL
};
- static const char *mpeg_stream_vbi_fmt[] = {
+ static const char * const mpeg_stream_vbi_fmt[] = {
"No VBI",
"Private packet, IVTV format",
NULL
};
- static const char *camera_power_line_frequency[] = {
+ static const char * const camera_power_line_frequency[] = {
"Disabled",
"50 Hz",
"60 Hz",
NULL
};
- static const char *camera_exposure_auto[] = {
+ static const char * const camera_exposure_auto[] = {
"Auto Mode",
"Manual Mode",
"Shutter Priority Mode",
"Aperture Priority Mode",
NULL
};
- static const char *colorfx[] = {
+ static const char * const colorfx[] = {
"None",
"Black & White",
"Sepia",
@@ -210,7 +210,7 @@ const char **v4l2_ctrl_get_menu(u32 id)
"Vivid",
NULL
};
- static const char *tune_preemphasis[] = {
+ static const char * const tune_preemphasis[] = {
"No preemphasis",
"50 useconds",
"75 useconds",
@@ -569,7 +569,7 @@ static int user_to_new(struct v4l2_ext_control *c,
int ret;
u32 size;
- ctrl->has_new = 1;
+ ctrl->is_new = 1;
switch (ctrl->type) {
case V4L2_CTRL_TYPE_INTEGER64:
ctrl->val64 = c->value64;
@@ -952,7 +952,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
u32 id, const char *name, enum v4l2_ctrl_type type,
s32 min, s32 max, u32 step, s32 def,
- u32 flags, const char **qmenu, void *priv)
+ u32 flags, const char * const *qmenu, void *priv)
{
struct v4l2_ctrl *ctrl;
unsigned sz_extra = 0;
@@ -962,13 +962,20 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
/* Sanity checks */
if (id == 0 || name == NULL || id >= V4L2_CID_PRIVATE_BASE ||
- def < min || def > max || max < min ||
+ max < min ||
(type == V4L2_CTRL_TYPE_INTEGER && step == 0) ||
(type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) ||
(type == V4L2_CTRL_TYPE_STRING && max == 0)) {
handler_set_err(hdl, -ERANGE);
return NULL;
}
+ if ((type == V4L2_CTRL_TYPE_INTEGER ||
+ type == V4L2_CTRL_TYPE_MENU ||
+ type == V4L2_CTRL_TYPE_BOOLEAN) &&
+ (def < min || def > max)) {
+ handler_set_err(hdl, -ERANGE);
+ return NULL;
+ }
if (type == V4L2_CTRL_TYPE_BUTTON)
flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
@@ -1019,7 +1026,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
bool is_menu;
struct v4l2_ctrl *ctrl;
const char *name = cfg->name;
- const char **qmenu = cfg->qmenu;
+ const char * const *qmenu = cfg->qmenu;
enum v4l2_ctrl_type type = cfg->type;
u32 flags = cfg->flags;
s32 min = cfg->min;
@@ -1075,7 +1082,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
u32 id, s32 max, s32 mask, s32 def)
{
- const char **qmenu = v4l2_ctrl_get_menu(id);
+ const char * const *qmenu = v4l2_ctrl_get_menu(id);
const char *name;
enum v4l2_ctrl_type type;
s32 min;
@@ -1273,8 +1280,12 @@ int v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl)
if (ctrl->done)
continue;
- for (i = 0; i < master->ncontrols; i++)
- cur_to_new(master->cluster[i]);
+ for (i = 0; i < master->ncontrols; i++) {
+ if (master->cluster[i]) {
+ cur_to_new(master->cluster[i]);
+ master->cluster[i]->is_new = 1;
+ }
+ }
/* Skip button controls and read-only controls. */
if (ctrl->type == V4L2_CTRL_TYPE_BUTTON ||
@@ -1333,12 +1344,15 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
ctrl = ref->ctrl;
memset(qc, 0, sizeof(*qc));
- qc->id = ctrl->id;
+ if (id >= V4L2_CID_PRIVATE_BASE)
+ qc->id = id;
+ else
+ qc->id = ctrl->id;
strlcpy(qc->name, ctrl->name, sizeof(qc->name));
qc->minimum = ctrl->minimum;
qc->maximum = ctrl->maximum;
qc->default_value = ctrl->default_value;
- if (qc->type == V4L2_CTRL_TYPE_MENU)
+ if (ctrl->type == V4L2_CTRL_TYPE_MENU)
qc->step = 1;
else
qc->step = ctrl->step;
@@ -1638,7 +1652,7 @@ static int try_or_set_control_cluster(struct v4l2_ctrl *master, bool set)
if (ctrl == NULL)
continue;
- if (ctrl->has_new) {
+ if (ctrl->is_new) {
/* Double check this: it may have changed since the
last check in try_or_set_ext_ctrls(). */
if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED))
@@ -1712,13 +1726,13 @@ static int try_or_set_ext_ctrls(struct v4l2_ctrl_handler *hdl,
v4l2_ctrl_lock(ctrl);
- /* Reset the 'has_new' flags of the cluster */
+ /* Reset the 'is_new' flags of the cluster */
for (j = 0; j < master->ncontrols; j++)
if (master->cluster[j])
- master->cluster[j]->has_new = 0;
+ master->cluster[j]->is_new = 0;
/* Copy the new caller-supplied control values.
- user_to_new() sets 'has_new' to 1. */
+ user_to_new() sets 'is_new' to 1. */
ret = cluster_walk(i, cs, helpers, user_to_new);
if (!ret)
@@ -1813,15 +1827,18 @@ static int set_ctrl(struct v4l2_ctrl *ctrl, s32 *val)
int ret;
int i;
+ if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
+ return -EACCES;
+
v4l2_ctrl_lock(ctrl);
- /* Reset the 'has_new' flags of the cluster */
+ /* Reset the 'is_new' flags of the cluster */
for (i = 0; i < master->ncontrols; i++)
if (master->cluster[i])
- master->cluster[i]->has_new = 0;
+ master->cluster[i]->is_new = 0;
ctrl->val = *val;
- ctrl->has_new = 1;
+ ctrl->is_new = 1;
ret = try_or_set_control_cluster(master, false);
if (!ret)
ret = try_or_set_control_cluster(master, true);