aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSakari Ailus <sakari.ailus@iki.fi>2011-08-04 12:51:11 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-04-10 13:49:44 -0400
commitce580fe5190dec4d872e7925946b0aec1f694370 (patch)
treecb745116ea3f1fb4f8cb327810b43b140fcb8fb8
parent3fd7e4341e04f80e2605f56bbd8cb1e8b027901a (diff)
[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>
-rw-r--r--drivers/media/video/v4l2-ctrls.c74
-rw-r--r--include/linux/videodev2.h6
-rw-r--r--include/media/v4l2-ctrls.h6
3 files changed, 67 insertions, 19 deletions
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 18015c0a8d31..3e0a72dec994 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -852,7 +852,8 @@ static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 change
852 ev->u.ctrl.value64 = ctrl->cur.val64; 852 ev->u.ctrl.value64 = ctrl->cur.val64;
853 ev->u.ctrl.minimum = ctrl->minimum; 853 ev->u.ctrl.minimum = ctrl->minimum;
854 ev->u.ctrl.maximum = ctrl->maximum; 854 ev->u.ctrl.maximum = ctrl->maximum;
855 if (ctrl->type == V4L2_CTRL_TYPE_MENU) 855 if (ctrl->type == V4L2_CTRL_TYPE_MENU
856 || ctrl->type == V4L2_CTRL_TYPE_INTEGER_MENU)
856 ev->u.ctrl.step = 1; 857 ev->u.ctrl.step = 1;
857 else 858 else
858 ev->u.ctrl.step = ctrl->step; 859 ev->u.ctrl.step = ctrl->step;
@@ -1083,10 +1084,13 @@ static int validate_new_int(const struct v4l2_ctrl *ctrl, s32 *pval)
1083 return 0; 1084 return 0;
1084 1085
1085 case V4L2_CTRL_TYPE_MENU: 1086 case V4L2_CTRL_TYPE_MENU:
1087 case V4L2_CTRL_TYPE_INTEGER_MENU:
1086 if (val < ctrl->minimum || val > ctrl->maximum) 1088 if (val < ctrl->minimum || val > ctrl->maximum)
1087 return -ERANGE; 1089 return -ERANGE;
1088 if (ctrl->qmenu[val][0] == '\0' || 1090 if (ctrl->menu_skip_mask & (1 << val))
1089 (ctrl->menu_skip_mask & (1 << val))) 1091 return -EINVAL;
1092 if (ctrl->type == V4L2_CTRL_TYPE_MENU &&
1093 ctrl->qmenu[val][0] == '\0')
1090 return -EINVAL; 1094 return -EINVAL;
1091 return 0; 1095 return 0;
1092 1096
@@ -1114,6 +1118,7 @@ static int validate_new(const struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c
1114 case V4L2_CTRL_TYPE_INTEGER: 1118 case V4L2_CTRL_TYPE_INTEGER:
1115 case V4L2_CTRL_TYPE_BOOLEAN: 1119 case V4L2_CTRL_TYPE_BOOLEAN:
1116 case V4L2_CTRL_TYPE_MENU: 1120 case V4L2_CTRL_TYPE_MENU:
1121 case V4L2_CTRL_TYPE_INTEGER_MENU:
1117 case V4L2_CTRL_TYPE_BITMASK: 1122 case V4L2_CTRL_TYPE_BITMASK:
1118 case V4L2_CTRL_TYPE_BUTTON: 1123 case V4L2_CTRL_TYPE_BUTTON:
1119 case V4L2_CTRL_TYPE_CTRL_CLASS: 1124 case V4L2_CTRL_TYPE_CTRL_CLASS:
@@ -1343,7 +1348,8 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
1343 const struct v4l2_ctrl_ops *ops, 1348 const struct v4l2_ctrl_ops *ops,
1344 u32 id, const char *name, enum v4l2_ctrl_type type, 1349 u32 id, const char *name, enum v4l2_ctrl_type type,
1345 s32 min, s32 max, u32 step, s32 def, 1350 s32 min, s32 max, u32 step, s32 def,
1346 u32 flags, const char * const *qmenu, void *priv) 1351 u32 flags, const char * const *qmenu,
1352 const s64 *qmenu_int, void *priv)
1347{ 1353{
1348 struct v4l2_ctrl *ctrl; 1354 struct v4l2_ctrl *ctrl;
1349 unsigned sz_extra = 0; 1355 unsigned sz_extra = 0;
@@ -1356,6 +1362,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
1356 (type == V4L2_CTRL_TYPE_INTEGER && step == 0) || 1362 (type == V4L2_CTRL_TYPE_INTEGER && step == 0) ||
1357 (type == V4L2_CTRL_TYPE_BITMASK && max == 0) || 1363 (type == V4L2_CTRL_TYPE_BITMASK && max == 0) ||
1358 (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) || 1364 (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) ||
1365 (type == V4L2_CTRL_TYPE_INTEGER_MENU && qmenu_int == NULL) ||
1359 (type == V4L2_CTRL_TYPE_STRING && max == 0)) { 1366 (type == V4L2_CTRL_TYPE_STRING && max == 0)) {
1360 handler_set_err(hdl, -ERANGE); 1367 handler_set_err(hdl, -ERANGE);
1361 return NULL; 1368 return NULL;
@@ -1366,6 +1373,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
1366 } 1373 }
1367 if ((type == V4L2_CTRL_TYPE_INTEGER || 1374 if ((type == V4L2_CTRL_TYPE_INTEGER ||
1368 type == V4L2_CTRL_TYPE_MENU || 1375 type == V4L2_CTRL_TYPE_MENU ||
1376 type == V4L2_CTRL_TYPE_INTEGER_MENU ||
1369 type == V4L2_CTRL_TYPE_BOOLEAN) && 1377 type == V4L2_CTRL_TYPE_BOOLEAN) &&
1370 (def < min || def > max)) { 1378 (def < min || def > max)) {
1371 handler_set_err(hdl, -ERANGE); 1379 handler_set_err(hdl, -ERANGE);
@@ -1400,7 +1408,10 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
1400 ctrl->minimum = min; 1408 ctrl->minimum = min;
1401 ctrl->maximum = max; 1409 ctrl->maximum = max;
1402 ctrl->step = step; 1410 ctrl->step = step;
1403 ctrl->qmenu = qmenu; 1411 if (type == V4L2_CTRL_TYPE_MENU)
1412 ctrl->qmenu = qmenu;
1413 else if (type == V4L2_CTRL_TYPE_INTEGER_MENU)
1414 ctrl->qmenu_int = qmenu_int;
1404 ctrl->priv = priv; 1415 ctrl->priv = priv;
1405 ctrl->cur.val = ctrl->val = ctrl->default_value = def; 1416 ctrl->cur.val = ctrl->val = ctrl->default_value = def;
1406 1417
@@ -1427,6 +1438,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
1427 struct v4l2_ctrl *ctrl; 1438 struct v4l2_ctrl *ctrl;
1428 const char *name = cfg->name; 1439 const char *name = cfg->name;
1429 const char * const *qmenu = cfg->qmenu; 1440 const char * const *qmenu = cfg->qmenu;
1441 const s64 *qmenu_int = cfg->qmenu_int;
1430 enum v4l2_ctrl_type type = cfg->type; 1442 enum v4l2_ctrl_type type = cfg->type;
1431 u32 flags = cfg->flags; 1443 u32 flags = cfg->flags;
1432 s32 min = cfg->min; 1444 s32 min = cfg->min;
@@ -1438,18 +1450,24 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
1438 v4l2_ctrl_fill(cfg->id, &name, &type, &min, &max, &step, 1450 v4l2_ctrl_fill(cfg->id, &name, &type, &min, &max, &step,
1439 &def, &flags); 1451 &def, &flags);
1440 1452
1441 is_menu = (cfg->type == V4L2_CTRL_TYPE_MENU); 1453 is_menu = (cfg->type == V4L2_CTRL_TYPE_MENU ||
1454 cfg->type == V4L2_CTRL_TYPE_INTEGER_MENU);
1442 if (is_menu) 1455 if (is_menu)
1443 WARN_ON(step); 1456 WARN_ON(step);
1444 else 1457 else
1445 WARN_ON(cfg->menu_skip_mask); 1458 WARN_ON(cfg->menu_skip_mask);
1446 if (is_menu && qmenu == NULL) 1459 if (cfg->type == V4L2_CTRL_TYPE_MENU && qmenu == NULL)
1447 qmenu = v4l2_ctrl_get_menu(cfg->id); 1460 qmenu = v4l2_ctrl_get_menu(cfg->id);
1461 else if (cfg->type == V4L2_CTRL_TYPE_INTEGER_MENU &&
1462 qmenu_int == NULL) {
1463 handler_set_err(hdl, -EINVAL);
1464 return NULL;
1465 }
1448 1466
1449 ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->id, name, 1467 ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->id, name,
1450 type, min, max, 1468 type, min, max,
1451 is_menu ? cfg->menu_skip_mask : step, 1469 is_menu ? cfg->menu_skip_mask : step,
1452 def, flags, qmenu, priv); 1470 def, flags, qmenu, qmenu_int, priv);
1453 if (ctrl) 1471 if (ctrl)
1454 ctrl->is_private = cfg->is_private; 1472 ctrl->is_private = cfg->is_private;
1455 return ctrl; 1473 return ctrl;
@@ -1466,12 +1484,13 @@ struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
1466 u32 flags; 1484 u32 flags;
1467 1485
1468 v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags); 1486 v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
1469 if (type == V4L2_CTRL_TYPE_MENU) { 1487 if (type == V4L2_CTRL_TYPE_MENU
1488 || type == V4L2_CTRL_TYPE_INTEGER_MENU) {
1470 handler_set_err(hdl, -EINVAL); 1489 handler_set_err(hdl, -EINVAL);
1471 return NULL; 1490 return NULL;
1472 } 1491 }
1473 return v4l2_ctrl_new(hdl, ops, id, name, type, 1492 return v4l2_ctrl_new(hdl, ops, id, name, type,
1474 min, max, step, def, flags, NULL, NULL); 1493 min, max, step, def, flags, NULL, NULL, NULL);
1475} 1494}
1476EXPORT_SYMBOL(v4l2_ctrl_new_std); 1495EXPORT_SYMBOL(v4l2_ctrl_new_std);
1477 1496
@@ -1493,7 +1512,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
1493 return NULL; 1512 return NULL;
1494 } 1513 }
1495 return v4l2_ctrl_new(hdl, ops, id, name, type, 1514 return v4l2_ctrl_new(hdl, ops, id, name, type,
1496 0, max, mask, def, flags, qmenu, NULL); 1515 0, max, mask, def, flags, qmenu, NULL, NULL);
1497} 1516}
1498EXPORT_SYMBOL(v4l2_ctrl_new_std_menu); 1517EXPORT_SYMBOL(v4l2_ctrl_new_std_menu);
1499 1518
@@ -1659,6 +1678,9 @@ static void log_ctrl(const struct v4l2_ctrl *ctrl,
1659 case V4L2_CTRL_TYPE_MENU: 1678 case V4L2_CTRL_TYPE_MENU:
1660 printk(KERN_CONT "%s", ctrl->qmenu[ctrl->cur.val]); 1679 printk(KERN_CONT "%s", ctrl->qmenu[ctrl->cur.val]);
1661 break; 1680 break;
1681 case V4L2_CTRL_TYPE_INTEGER_MENU:
1682 printk(KERN_CONT "%lld", ctrl->qmenu_int[ctrl->cur.val]);
1683 break;
1662 case V4L2_CTRL_TYPE_BITMASK: 1684 case V4L2_CTRL_TYPE_BITMASK:
1663 printk(KERN_CONT "0x%08x", ctrl->cur.val); 1685 printk(KERN_CONT "0x%08x", ctrl->cur.val);
1664 break; 1686 break;
@@ -1795,7 +1817,8 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
1795 qc->minimum = ctrl->minimum; 1817 qc->minimum = ctrl->minimum;
1796 qc->maximum = ctrl->maximum; 1818 qc->maximum = ctrl->maximum;
1797 qc->default_value = ctrl->default_value; 1819 qc->default_value = ctrl->default_value;
1798 if (ctrl->type == V4L2_CTRL_TYPE_MENU) 1820 if (ctrl->type == V4L2_CTRL_TYPE_MENU
1821 || ctrl->type == V4L2_CTRL_TYPE_INTEGER_MENU)
1799 qc->step = 1; 1822 qc->step = 1;
1800 else 1823 else
1801 qc->step = ctrl->step; 1824 qc->step = ctrl->step;
@@ -1825,16 +1848,33 @@ int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm)
1825 1848
1826 qm->reserved = 0; 1849 qm->reserved = 0;
1827 /* Sanity checks */ 1850 /* Sanity checks */
1828 if (ctrl->qmenu == NULL || 1851 switch (ctrl->type) {
1829 i < ctrl->minimum || i > ctrl->maximum) 1852 case V4L2_CTRL_TYPE_MENU:
1853 if (ctrl->qmenu == NULL)
1854 return -EINVAL;
1855 break;
1856 case V4L2_CTRL_TYPE_INTEGER_MENU:
1857 if (ctrl->qmenu_int == NULL)
1858 return -EINVAL;
1859 break;
1860 default:
1861 return -EINVAL;
1862 }
1863
1864 if (i < ctrl->minimum || i > ctrl->maximum)
1830 return -EINVAL; 1865 return -EINVAL;
1866
1831 /* Use mask to see if this menu item should be skipped */ 1867 /* Use mask to see if this menu item should be skipped */
1832 if (ctrl->menu_skip_mask & (1 << i)) 1868 if (ctrl->menu_skip_mask & (1 << i))
1833 return -EINVAL; 1869 return -EINVAL;
1834 /* Empty menu items should also be skipped */ 1870 /* Empty menu items should also be skipped */
1835 if (ctrl->qmenu[i] == NULL || ctrl->qmenu[i][0] == '\0') 1871 if (ctrl->type == V4L2_CTRL_TYPE_MENU) {
1836 return -EINVAL; 1872 if (ctrl->qmenu[i] == NULL || ctrl->qmenu[i][0] == '\0')
1837 strlcpy(qm->name, ctrl->qmenu[i], sizeof(qm->name)); 1873 return -EINVAL;
1874 strlcpy(qm->name, ctrl->qmenu[i], sizeof(qm->name));
1875 } else {
1876 qm->value = ctrl->qmenu_int[i];
1877 }
1838 return 0; 1878 return 0;
1839} 1879}
1840EXPORT_SYMBOL(v4l2_querymenu); 1880EXPORT_SYMBOL(v4l2_querymenu);
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index c9c9a4680cc5..e69cacc9e9ea 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1151,6 +1151,7 @@ enum v4l2_ctrl_type {
1151 V4L2_CTRL_TYPE_CTRL_CLASS = 6, 1151 V4L2_CTRL_TYPE_CTRL_CLASS = 6,
1152 V4L2_CTRL_TYPE_STRING = 7, 1152 V4L2_CTRL_TYPE_STRING = 7,
1153 V4L2_CTRL_TYPE_BITMASK = 8, 1153 V4L2_CTRL_TYPE_BITMASK = 8,
1154 V4L2_CTRL_TYPE_INTEGER_MENU = 9,
1154}; 1155};
1155 1156
1156/* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ 1157/* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
@@ -1170,7 +1171,10 @@ struct v4l2_queryctrl {
1170struct v4l2_querymenu { 1171struct v4l2_querymenu {
1171 __u32 id; 1172 __u32 id;
1172 __u32 index; 1173 __u32 index;
1173 __u8 name[32]; /* Whatever */ 1174 union {
1175 __u8 name[32]; /* Whatever */
1176 __s64 value;
1177 };
1174 __u32 reserved; 1178 __u32 reserved;
1175}; 1179};
1176 1180
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 3dbd06638506..533315bd74e0 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -130,7 +130,10 @@ struct v4l2_ctrl {
130 u32 step; 130 u32 step;
131 u32 menu_skip_mask; 131 u32 menu_skip_mask;
132 }; 132 };
133 const char * const *qmenu; 133 union {
134 const char * const *qmenu;
135 const s64 *qmenu_int;
136 };
134 unsigned long flags; 137 unsigned long flags;
135 union { 138 union {
136 s32 val; 139 s32 val;
@@ -220,6 +223,7 @@ struct v4l2_ctrl_config {
220 u32 flags; 223 u32 flags;
221 u32 menu_skip_mask; 224 u32 menu_skip_mask;
222 const char * const *qmenu; 225 const char * const *qmenu;
226 const s64 *qmenu_int;
223 unsigned int is_private:1; 227 unsigned int is_private:1;
224}; 228};
225 229