forked from Minki/linux
[media] v4l: Introduce integer menu controls
Create a new control type called V4L2_CTRL_TYPE_INTEGER_MENU. Integer menu controls are just like menu controls but the menu items are 64-bit integers rather than strings. Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Tested-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
3fd7e4341e
commit
ce580fe519
@ -852,7 +852,8 @@ static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 change
|
||||
ev->u.ctrl.value64 = ctrl->cur.val64;
|
||||
ev->u.ctrl.minimum = ctrl->minimum;
|
||||
ev->u.ctrl.maximum = ctrl->maximum;
|
||||
if (ctrl->type == V4L2_CTRL_TYPE_MENU)
|
||||
if (ctrl->type == V4L2_CTRL_TYPE_MENU
|
||||
|| ctrl->type == V4L2_CTRL_TYPE_INTEGER_MENU)
|
||||
ev->u.ctrl.step = 1;
|
||||
else
|
||||
ev->u.ctrl.step = ctrl->step;
|
||||
@ -1083,10 +1084,13 @@ static int validate_new_int(const struct v4l2_ctrl *ctrl, s32 *pval)
|
||||
return 0;
|
||||
|
||||
case V4L2_CTRL_TYPE_MENU:
|
||||
case V4L2_CTRL_TYPE_INTEGER_MENU:
|
||||
if (val < ctrl->minimum || val > ctrl->maximum)
|
||||
return -ERANGE;
|
||||
if (ctrl->qmenu[val][0] == '\0' ||
|
||||
(ctrl->menu_skip_mask & (1 << val)))
|
||||
if (ctrl->menu_skip_mask & (1 << val))
|
||||
return -EINVAL;
|
||||
if (ctrl->type == V4L2_CTRL_TYPE_MENU &&
|
||||
ctrl->qmenu[val][0] == '\0')
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
|
||||
@ -1114,6 +1118,7 @@ static int validate_new(const struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c
|
||||
case V4L2_CTRL_TYPE_INTEGER:
|
||||
case V4L2_CTRL_TYPE_BOOLEAN:
|
||||
case V4L2_CTRL_TYPE_MENU:
|
||||
case V4L2_CTRL_TYPE_INTEGER_MENU:
|
||||
case V4L2_CTRL_TYPE_BITMASK:
|
||||
case V4L2_CTRL_TYPE_BUTTON:
|
||||
case V4L2_CTRL_TYPE_CTRL_CLASS:
|
||||
@ -1343,7 +1348,8 @@ 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 * const *qmenu, void *priv)
|
||||
u32 flags, const char * const *qmenu,
|
||||
const s64 *qmenu_int, void *priv)
|
||||
{
|
||||
struct v4l2_ctrl *ctrl;
|
||||
unsigned sz_extra = 0;
|
||||
@ -1356,6 +1362,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
|
||||
(type == V4L2_CTRL_TYPE_INTEGER && step == 0) ||
|
||||
(type == V4L2_CTRL_TYPE_BITMASK && max == 0) ||
|
||||
(type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) ||
|
||||
(type == V4L2_CTRL_TYPE_INTEGER_MENU && qmenu_int == NULL) ||
|
||||
(type == V4L2_CTRL_TYPE_STRING && max == 0)) {
|
||||
handler_set_err(hdl, -ERANGE);
|
||||
return NULL;
|
||||
@ -1366,6 +1373,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
|
||||
}
|
||||
if ((type == V4L2_CTRL_TYPE_INTEGER ||
|
||||
type == V4L2_CTRL_TYPE_MENU ||
|
||||
type == V4L2_CTRL_TYPE_INTEGER_MENU ||
|
||||
type == V4L2_CTRL_TYPE_BOOLEAN) &&
|
||||
(def < min || def > max)) {
|
||||
handler_set_err(hdl, -ERANGE);
|
||||
@ -1400,7 +1408,10 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
|
||||
ctrl->minimum = min;
|
||||
ctrl->maximum = max;
|
||||
ctrl->step = step;
|
||||
ctrl->qmenu = qmenu;
|
||||
if (type == V4L2_CTRL_TYPE_MENU)
|
||||
ctrl->qmenu = qmenu;
|
||||
else if (type == V4L2_CTRL_TYPE_INTEGER_MENU)
|
||||
ctrl->qmenu_int = qmenu_int;
|
||||
ctrl->priv = priv;
|
||||
ctrl->cur.val = ctrl->val = ctrl->default_value = def;
|
||||
|
||||
@ -1427,6 +1438,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
|
||||
struct v4l2_ctrl *ctrl;
|
||||
const char *name = cfg->name;
|
||||
const char * const *qmenu = cfg->qmenu;
|
||||
const s64 *qmenu_int = cfg->qmenu_int;
|
||||
enum v4l2_ctrl_type type = cfg->type;
|
||||
u32 flags = cfg->flags;
|
||||
s32 min = cfg->min;
|
||||
@ -1438,18 +1450,24 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
|
||||
v4l2_ctrl_fill(cfg->id, &name, &type, &min, &max, &step,
|
||||
&def, &flags);
|
||||
|
||||
is_menu = (cfg->type == V4L2_CTRL_TYPE_MENU);
|
||||
is_menu = (cfg->type == V4L2_CTRL_TYPE_MENU ||
|
||||
cfg->type == V4L2_CTRL_TYPE_INTEGER_MENU);
|
||||
if (is_menu)
|
||||
WARN_ON(step);
|
||||
else
|
||||
WARN_ON(cfg->menu_skip_mask);
|
||||
if (is_menu && qmenu == NULL)
|
||||
if (cfg->type == V4L2_CTRL_TYPE_MENU && qmenu == NULL)
|
||||
qmenu = v4l2_ctrl_get_menu(cfg->id);
|
||||
else if (cfg->type == V4L2_CTRL_TYPE_INTEGER_MENU &&
|
||||
qmenu_int == NULL) {
|
||||
handler_set_err(hdl, -EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->id, name,
|
||||
type, min, max,
|
||||
is_menu ? cfg->menu_skip_mask : step,
|
||||
def, flags, qmenu, priv);
|
||||
def, flags, qmenu, qmenu_int, priv);
|
||||
if (ctrl)
|
||||
ctrl->is_private = cfg->is_private;
|
||||
return ctrl;
|
||||
@ -1466,12 +1484,13 @@ struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
|
||||
u32 flags;
|
||||
|
||||
v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
|
||||
if (type == V4L2_CTRL_TYPE_MENU) {
|
||||
if (type == V4L2_CTRL_TYPE_MENU
|
||||
|| type == V4L2_CTRL_TYPE_INTEGER_MENU) {
|
||||
handler_set_err(hdl, -EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
return v4l2_ctrl_new(hdl, ops, id, name, type,
|
||||
min, max, step, def, flags, NULL, NULL);
|
||||
min, max, step, def, flags, NULL, NULL, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(v4l2_ctrl_new_std);
|
||||
|
||||
@ -1493,7 +1512,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
|
||||
return NULL;
|
||||
}
|
||||
return v4l2_ctrl_new(hdl, ops, id, name, type,
|
||||
0, max, mask, def, flags, qmenu, NULL);
|
||||
0, max, mask, def, flags, qmenu, NULL, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(v4l2_ctrl_new_std_menu);
|
||||
|
||||
@ -1659,6 +1678,9 @@ static void log_ctrl(const struct v4l2_ctrl *ctrl,
|
||||
case V4L2_CTRL_TYPE_MENU:
|
||||
printk(KERN_CONT "%s", ctrl->qmenu[ctrl->cur.val]);
|
||||
break;
|
||||
case V4L2_CTRL_TYPE_INTEGER_MENU:
|
||||
printk(KERN_CONT "%lld", ctrl->qmenu_int[ctrl->cur.val]);
|
||||
break;
|
||||
case V4L2_CTRL_TYPE_BITMASK:
|
||||
printk(KERN_CONT "0x%08x", ctrl->cur.val);
|
||||
break;
|
||||
@ -1795,7 +1817,8 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
|
||||
qc->minimum = ctrl->minimum;
|
||||
qc->maximum = ctrl->maximum;
|
||||
qc->default_value = ctrl->default_value;
|
||||
if (ctrl->type == V4L2_CTRL_TYPE_MENU)
|
||||
if (ctrl->type == V4L2_CTRL_TYPE_MENU
|
||||
|| ctrl->type == V4L2_CTRL_TYPE_INTEGER_MENU)
|
||||
qc->step = 1;
|
||||
else
|
||||
qc->step = ctrl->step;
|
||||
@ -1825,16 +1848,33 @@ int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm)
|
||||
|
||||
qm->reserved = 0;
|
||||
/* Sanity checks */
|
||||
if (ctrl->qmenu == NULL ||
|
||||
i < ctrl->minimum || i > ctrl->maximum)
|
||||
switch (ctrl->type) {
|
||||
case V4L2_CTRL_TYPE_MENU:
|
||||
if (ctrl->qmenu == NULL)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case V4L2_CTRL_TYPE_INTEGER_MENU:
|
||||
if (ctrl->qmenu_int == NULL)
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (i < ctrl->minimum || i > ctrl->maximum)
|
||||
return -EINVAL;
|
||||
|
||||
/* Use mask to see if this menu item should be skipped */
|
||||
if (ctrl->menu_skip_mask & (1 << i))
|
||||
return -EINVAL;
|
||||
/* Empty menu items should also be skipped */
|
||||
if (ctrl->qmenu[i] == NULL || ctrl->qmenu[i][0] == '\0')
|
||||
return -EINVAL;
|
||||
strlcpy(qm->name, ctrl->qmenu[i], sizeof(qm->name));
|
||||
if (ctrl->type == V4L2_CTRL_TYPE_MENU) {
|
||||
if (ctrl->qmenu[i] == NULL || ctrl->qmenu[i][0] == '\0')
|
||||
return -EINVAL;
|
||||
strlcpy(qm->name, ctrl->qmenu[i], sizeof(qm->name));
|
||||
} else {
|
||||
qm->value = ctrl->qmenu_int[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(v4l2_querymenu);
|
||||
|
@ -1151,6 +1151,7 @@ enum v4l2_ctrl_type {
|
||||
V4L2_CTRL_TYPE_CTRL_CLASS = 6,
|
||||
V4L2_CTRL_TYPE_STRING = 7,
|
||||
V4L2_CTRL_TYPE_BITMASK = 8,
|
||||
V4L2_CTRL_TYPE_INTEGER_MENU = 9,
|
||||
};
|
||||
|
||||
/* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
|
||||
@ -1170,7 +1171,10 @@ struct v4l2_queryctrl {
|
||||
struct v4l2_querymenu {
|
||||
__u32 id;
|
||||
__u32 index;
|
||||
__u8 name[32]; /* Whatever */
|
||||
union {
|
||||
__u8 name[32]; /* Whatever */
|
||||
__s64 value;
|
||||
};
|
||||
__u32 reserved;
|
||||
};
|
||||
|
||||
|
@ -130,7 +130,10 @@ struct v4l2_ctrl {
|
||||
u32 step;
|
||||
u32 menu_skip_mask;
|
||||
};
|
||||
const char * const *qmenu;
|
||||
union {
|
||||
const char * const *qmenu;
|
||||
const s64 *qmenu_int;
|
||||
};
|
||||
unsigned long flags;
|
||||
union {
|
||||
s32 val;
|
||||
@ -220,6 +223,7 @@ struct v4l2_ctrl_config {
|
||||
u32 flags;
|
||||
u32 menu_skip_mask;
|
||||
const char * const *qmenu;
|
||||
const s64 *qmenu_int;
|
||||
unsigned int is_private:1;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user