diff options
author | Sakari Ailus <sakari.ailus@iki.fi> | 2011-08-04 12:51:11 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-04-10 13:49:44 -0400 |
commit | ce580fe5190dec4d872e7925946b0aec1f694370 (patch) | |
tree | cb745116ea3f1fb4f8cb327810b43b140fcb8fb8 | |
parent | 3fd7e4341e04f80e2605f56bbd8cb1e8b027901a (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.c | 74 | ||||
-rw-r--r-- | include/linux/videodev2.h | 6 | ||||
-rw-r--r-- | include/media/v4l2-ctrls.h | 6 |
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 | } |
1476 | EXPORT_SYMBOL(v4l2_ctrl_new_std); | 1495 | EXPORT_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 | } |
1498 | EXPORT_SYMBOL(v4l2_ctrl_new_std_menu); | 1517 | EXPORT_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 | } |
1840 | EXPORT_SYMBOL(v4l2_querymenu); | 1880 | EXPORT_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 { | |||
1170 | struct v4l2_querymenu { | 1171 | struct 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 | ||