diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2014-06-12 06:54:16 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-07-17 09:38:44 -0400 |
commit | d9a2547150245f34a050f744ea46542c44792652 (patch) | |
tree | b8d20d264d795e1bd8015fe84ce6402f87990e9b | |
parent | 5082c2417841e64df975789011e182ce99a9dacd (diff) |
[media] v4l2-ctrls: add support for compound types
This patch implements initial support for compound types.
The changes are fairly obvious: basic support for is_ptr types, the
type_is_int function is replaced by a is_int bitfield, and
v4l2_query_ext_ctrl is added.
Note that this patch does not yet add support for N-dimensional
arrays, that comes later. So v4l2_query_ext_ctrl just sets elems to
1 and nr_of_dims and dims[] are all zero.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
-rw-r--r-- | drivers/media/v4l2-core/v4l2-ctrls.c | 224 | ||||
-rw-r--r-- | include/media/v4l2-ctrls.h | 23 |
2 files changed, 187 insertions, 60 deletions
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 365884b3abad..d5cd1aab970b 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c | |||
@@ -1124,20 +1124,6 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, | |||
1124 | } | 1124 | } |
1125 | EXPORT_SYMBOL(v4l2_ctrl_fill); | 1125 | EXPORT_SYMBOL(v4l2_ctrl_fill); |
1126 | 1126 | ||
1127 | /* Helper function to determine whether the control type is compatible with | ||
1128 | VIDIOC_G/S_CTRL. */ | ||
1129 | static bool type_is_int(const struct v4l2_ctrl *ctrl) | ||
1130 | { | ||
1131 | switch (ctrl->type) { | ||
1132 | case V4L2_CTRL_TYPE_INTEGER64: | ||
1133 | case V4L2_CTRL_TYPE_STRING: | ||
1134 | /* Nope, these need v4l2_ext_control */ | ||
1135 | return false; | ||
1136 | default: | ||
1137 | return true; | ||
1138 | } | ||
1139 | } | ||
1140 | |||
1141 | static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 changes) | 1127 | static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 changes) |
1142 | { | 1128 | { |
1143 | memset(ev->reserved, 0, sizeof(ev->reserved)); | 1129 | memset(ev->reserved, 0, sizeof(ev->reserved)); |
@@ -1146,7 +1132,7 @@ static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 change | |||
1146 | ev->u.ctrl.changes = changes; | 1132 | ev->u.ctrl.changes = changes; |
1147 | ev->u.ctrl.type = ctrl->type; | 1133 | ev->u.ctrl.type = ctrl->type; |
1148 | ev->u.ctrl.flags = ctrl->flags; | 1134 | ev->u.ctrl.flags = ctrl->flags; |
1149 | if (ctrl->type == V4L2_CTRL_TYPE_STRING) | 1135 | if (ctrl->is_ptr) |
1150 | ev->u.ctrl.value64 = 0; | 1136 | ev->u.ctrl.value64 = 0; |
1151 | else | 1137 | else |
1152 | ev->u.ctrl.value64 = ctrl->cur.val64; | 1138 | ev->u.ctrl.value64 = ctrl->cur.val64; |
@@ -1181,6 +1167,9 @@ static int cur_to_user(struct v4l2_ext_control *c, | |||
1181 | { | 1167 | { |
1182 | u32 len; | 1168 | u32 len; |
1183 | 1169 | ||
1170 | if (ctrl->is_ptr && !ctrl->is_string) | ||
1171 | return copy_to_user(c->ptr, ctrl->cur.p, ctrl->elem_size); | ||
1172 | |||
1184 | switch (ctrl->type) { | 1173 | switch (ctrl->type) { |
1185 | case V4L2_CTRL_TYPE_STRING: | 1174 | case V4L2_CTRL_TYPE_STRING: |
1186 | len = strlen(ctrl->cur.string); | 1175 | len = strlen(ctrl->cur.string); |
@@ -1208,6 +1197,9 @@ static int user_to_new(struct v4l2_ext_control *c, | |||
1208 | u32 size; | 1197 | u32 size; |
1209 | 1198 | ||
1210 | ctrl->is_new = 1; | 1199 | ctrl->is_new = 1; |
1200 | if (ctrl->is_ptr && !ctrl->is_string) | ||
1201 | return copy_from_user(ctrl->p, c->ptr, ctrl->elem_size); | ||
1202 | |||
1211 | switch (ctrl->type) { | 1203 | switch (ctrl->type) { |
1212 | case V4L2_CTRL_TYPE_INTEGER64: | 1204 | case V4L2_CTRL_TYPE_INTEGER64: |
1213 | ctrl->val64 = c->value64; | 1205 | ctrl->val64 = c->value64; |
@@ -1242,6 +1234,9 @@ static int new_to_user(struct v4l2_ext_control *c, | |||
1242 | { | 1234 | { |
1243 | u32 len; | 1235 | u32 len; |
1244 | 1236 | ||
1237 | if (ctrl->is_ptr && !ctrl->is_string) | ||
1238 | return copy_to_user(c->ptr, ctrl->p, ctrl->elem_size); | ||
1239 | |||
1245 | switch (ctrl->type) { | 1240 | switch (ctrl->type) { |
1246 | case V4L2_CTRL_TYPE_STRING: | 1241 | case V4L2_CTRL_TYPE_STRING: |
1247 | len = strlen(ctrl->string); | 1242 | len = strlen(ctrl->string); |
@@ -1268,6 +1263,7 @@ static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags) | |||
1268 | 1263 | ||
1269 | if (ctrl == NULL) | 1264 | if (ctrl == NULL) |
1270 | return; | 1265 | return; |
1266 | |||
1271 | switch (ctrl->type) { | 1267 | switch (ctrl->type) { |
1272 | case V4L2_CTRL_TYPE_BUTTON: | 1268 | case V4L2_CTRL_TYPE_BUTTON: |
1273 | changed = true; | 1269 | changed = true; |
@@ -1282,8 +1278,13 @@ static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags) | |||
1282 | ctrl->cur.val64 = ctrl->val64; | 1278 | ctrl->cur.val64 = ctrl->val64; |
1283 | break; | 1279 | break; |
1284 | default: | 1280 | default: |
1285 | changed = ctrl->val != ctrl->cur.val; | 1281 | if (ctrl->is_ptr) { |
1286 | ctrl->cur.val = ctrl->val; | 1282 | changed = memcmp(ctrl->p, ctrl->cur.p, ctrl->elem_size); |
1283 | memcpy(ctrl->cur.p, ctrl->p, ctrl->elem_size); | ||
1284 | } else { | ||
1285 | changed = ctrl->val != ctrl->cur.val; | ||
1286 | ctrl->cur.val = ctrl->val; | ||
1287 | } | ||
1287 | break; | 1288 | break; |
1288 | } | 1289 | } |
1289 | if (ch_flags & V4L2_EVENT_CTRL_CH_FLAGS) { | 1290 | if (ch_flags & V4L2_EVENT_CTRL_CH_FLAGS) { |
@@ -1323,7 +1324,10 @@ static void cur_to_new(struct v4l2_ctrl *ctrl) | |||
1323 | ctrl->val64 = ctrl->cur.val64; | 1324 | ctrl->val64 = ctrl->cur.val64; |
1324 | break; | 1325 | break; |
1325 | default: | 1326 | default: |
1326 | ctrl->val = ctrl->cur.val; | 1327 | if (ctrl->is_ptr) |
1328 | memcpy(ctrl->p, ctrl->cur.p, ctrl->elem_size); | ||
1329 | else | ||
1330 | ctrl->val = ctrl->cur.val; | ||
1327 | break; | 1331 | break; |
1328 | } | 1332 | } |
1329 | } | 1333 | } |
@@ -1536,7 +1540,7 @@ static struct v4l2_ctrl_ref *find_private_ref( | |||
1536 | VIDIOC_G/S_CTRL. */ | 1540 | VIDIOC_G/S_CTRL. */ |
1537 | if (V4L2_CTRL_ID2CLASS(ref->ctrl->id) == V4L2_CTRL_CLASS_USER && | 1541 | if (V4L2_CTRL_ID2CLASS(ref->ctrl->id) == V4L2_CTRL_CLASS_USER && |
1538 | V4L2_CTRL_DRIVER_PRIV(ref->ctrl->id)) { | 1542 | V4L2_CTRL_DRIVER_PRIV(ref->ctrl->id)) { |
1539 | if (!type_is_int(ref->ctrl)) | 1543 | if (!ref->ctrl->is_int) |
1540 | continue; | 1544 | continue; |
1541 | if (id == 0) | 1545 | if (id == 0) |
1542 | return ref; | 1546 | return ref; |
@@ -1606,8 +1610,12 @@ static int handler_new_ref(struct v4l2_ctrl_handler *hdl, | |||
1606 | u32 class_ctrl = V4L2_CTRL_ID2CLASS(id) | 1; | 1610 | u32 class_ctrl = V4L2_CTRL_ID2CLASS(id) | 1; |
1607 | int bucket = id % hdl->nr_of_buckets; /* which bucket to use */ | 1611 | int bucket = id % hdl->nr_of_buckets; /* which bucket to use */ |
1608 | 1612 | ||
1609 | /* Automatically add the control class if it is not yet present. */ | 1613 | /* |
1610 | if (id != class_ctrl && find_ref_lock(hdl, class_ctrl) == NULL) | 1614 | * Automatically add the control class if it is not yet present and |
1615 | * the new control is not a compound control. | ||
1616 | */ | ||
1617 | if (ctrl->type < V4L2_CTRL_COMPOUND_TYPES && | ||
1618 | id != class_ctrl && find_ref_lock(hdl, class_ctrl) == NULL) | ||
1611 | if (!v4l2_ctrl_new_std(hdl, NULL, class_ctrl, 0, 0, 0, 0)) | 1619 | if (!v4l2_ctrl_new_std(hdl, NULL, class_ctrl, 0, 0, 0, 0)) |
1612 | return hdl->error; | 1620 | return hdl->error; |
1613 | 1621 | ||
@@ -1668,18 +1676,28 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, | |||
1668 | const struct v4l2_ctrl_ops *ops, | 1676 | const struct v4l2_ctrl_ops *ops, |
1669 | u32 id, const char *name, enum v4l2_ctrl_type type, | 1677 | u32 id, const char *name, enum v4l2_ctrl_type type, |
1670 | s64 min, s64 max, u64 step, s64 def, | 1678 | s64 min, s64 max, u64 step, s64 def, |
1679 | u32 elem_size, | ||
1671 | u32 flags, const char * const *qmenu, | 1680 | u32 flags, const char * const *qmenu, |
1672 | const s64 *qmenu_int, void *priv) | 1681 | const s64 *qmenu_int, void *priv) |
1673 | { | 1682 | { |
1674 | struct v4l2_ctrl *ctrl; | 1683 | struct v4l2_ctrl *ctrl; |
1675 | unsigned sz_extra = 0; | 1684 | unsigned sz_extra; |
1685 | void *data; | ||
1676 | int err; | 1686 | int err; |
1677 | 1687 | ||
1678 | if (hdl->error) | 1688 | if (hdl->error) |
1679 | return NULL; | 1689 | return NULL; |
1680 | 1690 | ||
1691 | if (type == V4L2_CTRL_TYPE_INTEGER64) | ||
1692 | elem_size = sizeof(s64); | ||
1693 | else if (type == V4L2_CTRL_TYPE_STRING) | ||
1694 | elem_size = max + 1; | ||
1695 | else if (type < V4L2_CTRL_COMPOUND_TYPES) | ||
1696 | elem_size = sizeof(s32); | ||
1697 | |||
1681 | /* Sanity checks */ | 1698 | /* Sanity checks */ |
1682 | if (id == 0 || name == NULL || id >= V4L2_CID_PRIVATE_BASE || | 1699 | if (id == 0 || name == NULL || id >= V4L2_CID_PRIVATE_BASE || |
1700 | elem_size == 0 || | ||
1683 | (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) || | 1701 | (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) || |
1684 | (type == V4L2_CTRL_TYPE_INTEGER_MENU && qmenu_int == NULL)) { | 1702 | (type == V4L2_CTRL_TYPE_INTEGER_MENU && qmenu_int == NULL)) { |
1685 | handler_set_err(hdl, -ERANGE); | 1703 | handler_set_err(hdl, -ERANGE); |
@@ -1695,12 +1713,13 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, | |||
1695 | return NULL; | 1713 | return NULL; |
1696 | } | 1714 | } |
1697 | 1715 | ||
1716 | sz_extra = 0; | ||
1698 | if (type == V4L2_CTRL_TYPE_BUTTON) | 1717 | if (type == V4L2_CTRL_TYPE_BUTTON) |
1699 | flags |= V4L2_CTRL_FLAG_WRITE_ONLY; | 1718 | flags |= V4L2_CTRL_FLAG_WRITE_ONLY; |
1700 | else if (type == V4L2_CTRL_TYPE_CTRL_CLASS) | 1719 | else if (type == V4L2_CTRL_TYPE_CTRL_CLASS) |
1701 | flags |= V4L2_CTRL_FLAG_READ_ONLY; | 1720 | flags |= V4L2_CTRL_FLAG_READ_ONLY; |
1702 | else if (type == V4L2_CTRL_TYPE_STRING) | 1721 | else if (type == V4L2_CTRL_TYPE_STRING || type >= V4L2_CTRL_COMPOUND_TYPES) |
1703 | sz_extra += 2 * (max + 1); | 1722 | sz_extra += 2 * elem_size; |
1704 | 1723 | ||
1705 | ctrl = kzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL); | 1724 | ctrl = kzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL); |
1706 | if (ctrl == NULL) { | 1725 | if (ctrl == NULL) { |
@@ -1719,18 +1738,28 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, | |||
1719 | ctrl->minimum = min; | 1738 | ctrl->minimum = min; |
1720 | ctrl->maximum = max; | 1739 | ctrl->maximum = max; |
1721 | ctrl->step = step; | 1740 | ctrl->step = step; |
1741 | ctrl->default_value = def; | ||
1742 | ctrl->is_string = type == V4L2_CTRL_TYPE_STRING; | ||
1743 | ctrl->is_ptr = type >= V4L2_CTRL_COMPOUND_TYPES || ctrl->is_string; | ||
1744 | ctrl->is_int = !ctrl->is_ptr && type != V4L2_CTRL_TYPE_INTEGER64; | ||
1745 | ctrl->elem_size = elem_size; | ||
1722 | if (type == V4L2_CTRL_TYPE_MENU) | 1746 | if (type == V4L2_CTRL_TYPE_MENU) |
1723 | ctrl->qmenu = qmenu; | 1747 | ctrl->qmenu = qmenu; |
1724 | else if (type == V4L2_CTRL_TYPE_INTEGER_MENU) | 1748 | else if (type == V4L2_CTRL_TYPE_INTEGER_MENU) |
1725 | ctrl->qmenu_int = qmenu_int; | 1749 | ctrl->qmenu_int = qmenu_int; |
1726 | ctrl->priv = priv; | 1750 | ctrl->priv = priv; |
1727 | ctrl->cur.val = ctrl->val = ctrl->default_value = def; | 1751 | ctrl->cur.val = ctrl->val = def; |
1752 | data = &ctrl->cur + 1; | ||
1753 | |||
1754 | if (ctrl->is_string) { | ||
1755 | ctrl->string = data; | ||
1756 | ctrl->cur.string = data + elem_size; | ||
1728 | 1757 | ||
1729 | if (ctrl->type == V4L2_CTRL_TYPE_STRING) { | ||
1730 | ctrl->cur.string = (char *)&ctrl[1] + sz_extra - (max + 1); | ||
1731 | ctrl->string = (char *)&ctrl[1] + sz_extra - 2 * (max + 1); | ||
1732 | if (ctrl->minimum) | 1758 | if (ctrl->minimum) |
1733 | memset(ctrl->cur.string, ' ', ctrl->minimum); | 1759 | memset(ctrl->cur.string, ' ', ctrl->minimum); |
1760 | } else if (ctrl->is_ptr) { | ||
1761 | ctrl->p = data; | ||
1762 | ctrl->cur.p = data + elem_size; | ||
1734 | } | 1763 | } |
1735 | if (handler_new_ref(hdl, ctrl)) { | 1764 | if (handler_new_ref(hdl, ctrl)) { |
1736 | kfree(ctrl); | 1765 | kfree(ctrl); |
@@ -1778,7 +1807,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl, | |||
1778 | ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->id, name, | 1807 | ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->id, name, |
1779 | type, min, max, | 1808 | type, min, max, |
1780 | is_menu ? cfg->menu_skip_mask : step, | 1809 | is_menu ? cfg->menu_skip_mask : step, |
1781 | def, flags, qmenu, qmenu_int, priv); | 1810 | def, cfg->elem_size, |
1811 | flags, qmenu, qmenu_int, priv); | ||
1782 | if (ctrl) | 1812 | if (ctrl) |
1783 | ctrl->is_private = cfg->is_private; | 1813 | ctrl->is_private = cfg->is_private; |
1784 | return ctrl; | 1814 | return ctrl; |
@@ -1795,13 +1825,15 @@ struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl, | |||
1795 | u32 flags; | 1825 | u32 flags; |
1796 | 1826 | ||
1797 | v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags); | 1827 | v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags); |
1798 | if (type == V4L2_CTRL_TYPE_MENU | 1828 | if (type == V4L2_CTRL_TYPE_MENU || |
1799 | || type == V4L2_CTRL_TYPE_INTEGER_MENU) { | 1829 | type == V4L2_CTRL_TYPE_INTEGER_MENU || |
1830 | type >= V4L2_CTRL_COMPOUND_TYPES) { | ||
1800 | handler_set_err(hdl, -EINVAL); | 1831 | handler_set_err(hdl, -EINVAL); |
1801 | return NULL; | 1832 | return NULL; |
1802 | } | 1833 | } |
1803 | return v4l2_ctrl_new(hdl, ops, id, name, type, | 1834 | return v4l2_ctrl_new(hdl, ops, id, name, type, |
1804 | min, max, step, def, flags, NULL, NULL, NULL); | 1835 | min, max, step, def, 0, |
1836 | flags, NULL, NULL, NULL); | ||
1805 | } | 1837 | } |
1806 | EXPORT_SYMBOL(v4l2_ctrl_new_std); | 1838 | EXPORT_SYMBOL(v4l2_ctrl_new_std); |
1807 | 1839 | ||
@@ -1833,7 +1865,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, | |||
1833 | return NULL; | 1865 | return NULL; |
1834 | } | 1866 | } |
1835 | return v4l2_ctrl_new(hdl, ops, id, name, type, | 1867 | return v4l2_ctrl_new(hdl, ops, id, name, type, |
1836 | 0, max, mask, def, flags, qmenu, qmenu_int, NULL); | 1868 | 0, max, mask, def, 0, |
1869 | flags, qmenu, qmenu_int, NULL); | ||
1837 | } | 1870 | } |
1838 | EXPORT_SYMBOL(v4l2_ctrl_new_std_menu); | 1871 | EXPORT_SYMBOL(v4l2_ctrl_new_std_menu); |
1839 | 1872 | ||
@@ -1864,7 +1897,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl, | |||
1864 | return NULL; | 1897 | return NULL; |
1865 | } | 1898 | } |
1866 | return v4l2_ctrl_new(hdl, ops, id, name, type, 0, max, mask, def, | 1899 | return v4l2_ctrl_new(hdl, ops, id, name, type, 0, max, mask, def, |
1867 | flags, qmenu, NULL, NULL); | 1900 | 0, flags, qmenu, NULL, NULL); |
1868 | 1901 | ||
1869 | } | 1902 | } |
1870 | EXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items); | 1903 | EXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items); |
@@ -1888,7 +1921,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl, | |||
1888 | return NULL; | 1921 | return NULL; |
1889 | } | 1922 | } |
1890 | return v4l2_ctrl_new(hdl, ops, id, name, type, | 1923 | return v4l2_ctrl_new(hdl, ops, id, name, type, |
1891 | 0, max, 0, def, flags, NULL, qmenu_int, NULL); | 1924 | 0, max, 0, def, 0, |
1925 | flags, NULL, qmenu_int, NULL); | ||
1892 | } | 1926 | } |
1893 | EXPORT_SYMBOL(v4l2_ctrl_new_int_menu); | 1927 | EXPORT_SYMBOL(v4l2_ctrl_new_int_menu); |
1894 | 1928 | ||
@@ -2177,9 +2211,10 @@ int v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl) | |||
2177 | } | 2211 | } |
2178 | EXPORT_SYMBOL(v4l2_ctrl_handler_setup); | 2212 | EXPORT_SYMBOL(v4l2_ctrl_handler_setup); |
2179 | 2213 | ||
2180 | /* Implement VIDIOC_QUERYCTRL */ | 2214 | /* Implement VIDIOC_QUERY_EXT_CTRL */ |
2181 | int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc) | 2215 | int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctrl *qc) |
2182 | { | 2216 | { |
2217 | const unsigned next_flags = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND; | ||
2183 | u32 id = qc->id & V4L2_CTRL_ID_MASK; | 2218 | u32 id = qc->id & V4L2_CTRL_ID_MASK; |
2184 | struct v4l2_ctrl_ref *ref; | 2219 | struct v4l2_ctrl_ref *ref; |
2185 | struct v4l2_ctrl *ctrl; | 2220 | struct v4l2_ctrl *ctrl; |
@@ -2192,7 +2227,20 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc) | |||
2192 | /* Try to find it */ | 2227 | /* Try to find it */ |
2193 | ref = find_ref(hdl, id); | 2228 | ref = find_ref(hdl, id); |
2194 | 2229 | ||
2195 | if ((qc->id & V4L2_CTRL_FLAG_NEXT_CTRL) && !list_empty(&hdl->ctrl_refs)) { | 2230 | if ((qc->id & next_flags) && !list_empty(&hdl->ctrl_refs)) { |
2231 | bool is_compound; | ||
2232 | /* Match any control that is not hidden */ | ||
2233 | unsigned mask = 1; | ||
2234 | bool match = false; | ||
2235 | |||
2236 | if ((qc->id & next_flags) == V4L2_CTRL_FLAG_NEXT_COMPOUND) { | ||
2237 | /* Match any hidden control */ | ||
2238 | match = true; | ||
2239 | } else if ((qc->id & next_flags) == next_flags) { | ||
2240 | /* Match any control, compound or not */ | ||
2241 | mask = 0; | ||
2242 | } | ||
2243 | |||
2196 | /* Find the next control with ID > qc->id */ | 2244 | /* Find the next control with ID > qc->id */ |
2197 | 2245 | ||
2198 | /* Did we reach the end of the control list? */ | 2246 | /* Did we reach the end of the control list? */ |
@@ -2200,19 +2248,34 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc) | |||
2200 | ref = NULL; /* Yes, so there is no next control */ | 2248 | ref = NULL; /* Yes, so there is no next control */ |
2201 | } else if (ref) { | 2249 | } else if (ref) { |
2202 | /* We found a control with the given ID, so just get | 2250 | /* We found a control with the given ID, so just get |
2203 | the next one in the list. */ | 2251 | the next valid one in the list. */ |
2204 | ref = list_entry(ref->node.next, typeof(*ref), node); | 2252 | list_for_each_entry_continue(ref, &hdl->ctrl_refs, node) { |
2253 | is_compound = | ||
2254 | ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES; | ||
2255 | if (id < ref->ctrl->id && | ||
2256 | (is_compound & mask) == match) | ||
2257 | break; | ||
2258 | } | ||
2259 | if (&ref->node == &hdl->ctrl_refs) | ||
2260 | ref = NULL; | ||
2205 | } else { | 2261 | } else { |
2206 | /* No control with the given ID exists, so start | 2262 | /* No control with the given ID exists, so start |
2207 | searching for the next largest ID. We know there | 2263 | searching for the next largest ID. We know there |
2208 | is one, otherwise the first 'if' above would have | 2264 | is one, otherwise the first 'if' above would have |
2209 | been true. */ | 2265 | been true. */ |
2210 | list_for_each_entry(ref, &hdl->ctrl_refs, node) | 2266 | list_for_each_entry(ref, &hdl->ctrl_refs, node) { |
2211 | if (id < ref->ctrl->id) | 2267 | is_compound = |
2268 | ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES; | ||
2269 | if (id < ref->ctrl->id && | ||
2270 | (is_compound & mask) == match) | ||
2212 | break; | 2271 | break; |
2272 | } | ||
2273 | if (&ref->node == &hdl->ctrl_refs) | ||
2274 | ref = NULL; | ||
2213 | } | 2275 | } |
2214 | } | 2276 | } |
2215 | mutex_unlock(hdl->lock); | 2277 | mutex_unlock(hdl->lock); |
2278 | |||
2216 | if (!ref) | 2279 | if (!ref) |
2217 | return -EINVAL; | 2280 | return -EINVAL; |
2218 | 2281 | ||
@@ -2223,6 +2286,12 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc) | |||
2223 | else | 2286 | else |
2224 | qc->id = ctrl->id; | 2287 | qc->id = ctrl->id; |
2225 | strlcpy(qc->name, ctrl->name, sizeof(qc->name)); | 2288 | strlcpy(qc->name, ctrl->name, sizeof(qc->name)); |
2289 | qc->flags = ctrl->flags; | ||
2290 | qc->type = ctrl->type; | ||
2291 | if (ctrl->is_ptr) | ||
2292 | qc->flags |= V4L2_CTRL_FLAG_HAS_PAYLOAD; | ||
2293 | qc->elem_size = ctrl->elem_size; | ||
2294 | qc->elems = 1; | ||
2226 | qc->minimum = ctrl->minimum; | 2295 | qc->minimum = ctrl->minimum; |
2227 | qc->maximum = ctrl->maximum; | 2296 | qc->maximum = ctrl->maximum; |
2228 | qc->default_value = ctrl->default_value; | 2297 | qc->default_value = ctrl->default_value; |
@@ -2231,15 +2300,50 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc) | |||
2231 | qc->step = 1; | 2300 | qc->step = 1; |
2232 | else | 2301 | else |
2233 | qc->step = ctrl->step; | 2302 | qc->step = ctrl->step; |
2234 | qc->flags = ctrl->flags; | 2303 | return 0; |
2235 | qc->type = ctrl->type; | 2304 | } |
2305 | EXPORT_SYMBOL(v4l2_query_ext_ctrl); | ||
2306 | |||
2307 | /* Implement VIDIOC_QUERYCTRL */ | ||
2308 | int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc) | ||
2309 | { | ||
2310 | struct v4l2_query_ext_ctrl qec = { qc->id }; | ||
2311 | int rc; | ||
2312 | |||
2313 | rc = v4l2_query_ext_ctrl(hdl, &qec); | ||
2314 | if (rc) | ||
2315 | return rc; | ||
2316 | |||
2317 | qc->id = qec.id; | ||
2318 | qc->type = qec.type; | ||
2319 | qc->flags = qec.flags; | ||
2320 | strlcpy(qc->name, qec.name, sizeof(qc->name)); | ||
2321 | switch (qc->type) { | ||
2322 | case V4L2_CTRL_TYPE_INTEGER: | ||
2323 | case V4L2_CTRL_TYPE_BOOLEAN: | ||
2324 | case V4L2_CTRL_TYPE_MENU: | ||
2325 | case V4L2_CTRL_TYPE_INTEGER_MENU: | ||
2326 | case V4L2_CTRL_TYPE_STRING: | ||
2327 | case V4L2_CTRL_TYPE_BITMASK: | ||
2328 | qc->minimum = qec.minimum; | ||
2329 | qc->maximum = qec.maximum; | ||
2330 | qc->step = qec.step; | ||
2331 | qc->default_value = qec.default_value; | ||
2332 | break; | ||
2333 | default: | ||
2334 | qc->minimum = 0; | ||
2335 | qc->maximum = 0; | ||
2336 | qc->step = 0; | ||
2337 | qc->default_value = 0; | ||
2338 | break; | ||
2339 | } | ||
2236 | return 0; | 2340 | return 0; |
2237 | } | 2341 | } |
2238 | EXPORT_SYMBOL(v4l2_queryctrl); | 2342 | EXPORT_SYMBOL(v4l2_queryctrl); |
2239 | 2343 | ||
2240 | int v4l2_subdev_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) | 2344 | int v4l2_subdev_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) |
2241 | { | 2345 | { |
2242 | if (qc->id & V4L2_CTRL_FLAG_NEXT_CTRL) | 2346 | if (qc->id & (V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND)) |
2243 | return -EINVAL; | 2347 | return -EINVAL; |
2244 | return v4l2_queryctrl(sd->ctrl_handler, qc); | 2348 | return v4l2_queryctrl(sd->ctrl_handler, qc); |
2245 | } | 2349 | } |
@@ -2339,7 +2443,8 @@ EXPORT_SYMBOL(v4l2_subdev_querymenu); | |||
2339 | Find the controls in the control array and do some basic checks. */ | 2443 | Find the controls in the control array and do some basic checks. */ |
2340 | static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl, | 2444 | static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl, |
2341 | struct v4l2_ext_controls *cs, | 2445 | struct v4l2_ext_controls *cs, |
2342 | struct v4l2_ctrl_helper *helpers) | 2446 | struct v4l2_ctrl_helper *helpers, |
2447 | bool get) | ||
2343 | { | 2448 | { |
2344 | struct v4l2_ctrl_helper *h; | 2449 | struct v4l2_ctrl_helper *h; |
2345 | bool have_clusters = false; | 2450 | bool have_clusters = false; |
@@ -2371,6 +2476,13 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl, | |||
2371 | have_clusters = true; | 2476 | have_clusters = true; |
2372 | if (ctrl->cluster[0] != ctrl) | 2477 | if (ctrl->cluster[0] != ctrl) |
2373 | ref = find_ref_lock(hdl, ctrl->cluster[0]->id); | 2478 | ref = find_ref_lock(hdl, ctrl->cluster[0]->id); |
2479 | if (ctrl->is_ptr && !ctrl->is_string && c->size < ctrl->elem_size) { | ||
2480 | if (get) { | ||
2481 | c->size = ctrl->elem_size; | ||
2482 | return -ENOSPC; | ||
2483 | } | ||
2484 | return -EFAULT; | ||
2485 | } | ||
2374 | /* Store the ref to the master control of the cluster */ | 2486 | /* Store the ref to the master control of the cluster */ |
2375 | h->mref = ref; | 2487 | h->mref = ref; |
2376 | h->ctrl = ctrl; | 2488 | h->ctrl = ctrl; |
@@ -2451,7 +2563,7 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs | |||
2451 | return -ENOMEM; | 2563 | return -ENOMEM; |
2452 | } | 2564 | } |
2453 | 2565 | ||
2454 | ret = prepare_ext_ctrls(hdl, cs, helpers); | 2566 | ret = prepare_ext_ctrls(hdl, cs, helpers, true); |
2455 | cs->error_idx = cs->count; | 2567 | cs->error_idx = cs->count; |
2456 | 2568 | ||
2457 | for (i = 0; !ret && i < cs->count; i++) | 2569 | for (i = 0; !ret && i < cs->count; i++) |
@@ -2513,11 +2625,11 @@ static int get_ctrl(struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c) | |||
2513 | int ret = 0; | 2625 | int ret = 0; |
2514 | int i; | 2626 | int i; |
2515 | 2627 | ||
2516 | /* String controls are not supported. The new_to_user() and | 2628 | /* Compound controls are not supported. The new_to_user() and |
2517 | * cur_to_user() calls below would need to be modified not to access | 2629 | * cur_to_user() calls below would need to be modified not to access |
2518 | * userspace memory when called from get_ctrl(). | 2630 | * userspace memory when called from get_ctrl(). |
2519 | */ | 2631 | */ |
2520 | if (ctrl->type == V4L2_CTRL_TYPE_STRING) | 2632 | if (!ctrl->is_int) |
2521 | return -EINVAL; | 2633 | return -EINVAL; |
2522 | 2634 | ||
2523 | if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY) | 2635 | if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY) |
@@ -2543,7 +2655,7 @@ int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control) | |||
2543 | struct v4l2_ext_control c; | 2655 | struct v4l2_ext_control c; |
2544 | int ret; | 2656 | int ret; |
2545 | 2657 | ||
2546 | if (ctrl == NULL || !type_is_int(ctrl)) | 2658 | if (ctrl == NULL || !ctrl->is_int) |
2547 | return -EINVAL; | 2659 | return -EINVAL; |
2548 | ret = get_ctrl(ctrl, &c); | 2660 | ret = get_ctrl(ctrl, &c); |
2549 | control->value = c.value; | 2661 | control->value = c.value; |
@@ -2562,7 +2674,7 @@ s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl) | |||
2562 | struct v4l2_ext_control c; | 2674 | struct v4l2_ext_control c; |
2563 | 2675 | ||
2564 | /* It's a driver bug if this happens. */ | 2676 | /* It's a driver bug if this happens. */ |
2565 | WARN_ON(!type_is_int(ctrl)); | 2677 | WARN_ON(!ctrl->is_int); |
2566 | c.value = 0; | 2678 | c.value = 0; |
2567 | get_ctrl(ctrl, &c); | 2679 | get_ctrl(ctrl, &c); |
2568 | return c.value; | 2680 | return c.value; |
@@ -2698,7 +2810,7 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, | |||
2698 | if (!helpers) | 2810 | if (!helpers) |
2699 | return -ENOMEM; | 2811 | return -ENOMEM; |
2700 | } | 2812 | } |
2701 | ret = prepare_ext_ctrls(hdl, cs, helpers); | 2813 | ret = prepare_ext_ctrls(hdl, cs, helpers, false); |
2702 | if (!ret) | 2814 | if (!ret) |
2703 | ret = validate_ctrls(cs, helpers, set); | 2815 | ret = validate_ctrls(cs, helpers, set); |
2704 | if (ret && set) | 2816 | if (ret && set) |
@@ -2803,11 +2915,11 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, | |||
2803 | struct v4l2_ctrl *master = ctrl->cluster[0]; | 2915 | struct v4l2_ctrl *master = ctrl->cluster[0]; |
2804 | int i; | 2916 | int i; |
2805 | 2917 | ||
2806 | /* String controls are not supported. The user_to_new() and | 2918 | /* Compound controls are not supported. The user_to_new() and |
2807 | * cur_to_user() calls below would need to be modified not to access | 2919 | * cur_to_user() calls below would need to be modified not to access |
2808 | * userspace memory when called from set_ctrl(). | 2920 | * userspace memory when called from set_ctrl(). |
2809 | */ | 2921 | */ |
2810 | if (ctrl->type == V4L2_CTRL_TYPE_STRING) | 2922 | if (ctrl->is_ptr) |
2811 | return -EINVAL; | 2923 | return -EINVAL; |
2812 | 2924 | ||
2813 | /* Reset the 'is_new' flags of the cluster */ | 2925 | /* Reset the 'is_new' flags of the cluster */ |
@@ -2849,7 +2961,7 @@ int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, | |||
2849 | struct v4l2_ext_control c; | 2961 | struct v4l2_ext_control c; |
2850 | int ret; | 2962 | int ret; |
2851 | 2963 | ||
2852 | if (ctrl == NULL || !type_is_int(ctrl)) | 2964 | if (ctrl == NULL || !ctrl->is_int) |
2853 | return -EINVAL; | 2965 | return -EINVAL; |
2854 | 2966 | ||
2855 | if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) | 2967 | if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) |
@@ -2873,7 +2985,7 @@ int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val) | |||
2873 | struct v4l2_ext_control c; | 2985 | struct v4l2_ext_control c; |
2874 | 2986 | ||
2875 | /* It's a driver bug if this happens. */ | 2987 | /* It's a driver bug if this happens. */ |
2876 | WARN_ON(!type_is_int(ctrl)); | 2988 | WARN_ON(!ctrl->is_int); |
2877 | c.value = val; | 2989 | c.value = val; |
2878 | return set_ctrl_lock(NULL, ctrl, &c); | 2990 | return set_ctrl_lock(NULL, ctrl, &c); |
2879 | } | 2991 | } |
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index a2e8f038a8ed..9024daebdf3b 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h | |||
@@ -73,6 +73,12 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv); | |||
73 | * members are in 'automatic' mode or 'manual' mode. This is | 73 | * members are in 'automatic' mode or 'manual' mode. This is |
74 | * used for autogain/gain type clusters. Drivers should never | 74 | * used for autogain/gain type clusters. Drivers should never |
75 | * set this flag directly. | 75 | * set this flag directly. |
76 | * @is_int: If set, then this control has a simple integer value (i.e. it | ||
77 | * uses ctrl->val). | ||
78 | * @is_string: If set, then this control has type V4L2_CTRL_TYPE_STRING. | ||
79 | * @is_ptr: If set, then this control is an array and/or has type >= V4L2_CTRL_COMPOUND_TYPES | ||
80 | * and/or has type V4L2_CTRL_TYPE_STRING. In other words, struct | ||
81 | * v4l2_ext_control uses field p to point to the data. | ||
76 | * @has_volatiles: If set, then one or more members of the cluster are volatile. | 82 | * @has_volatiles: If set, then one or more members of the cluster are volatile. |
77 | * Drivers should never touch this flag. | 83 | * Drivers should never touch this flag. |
78 | * @call_notify: If set, then call the handler's notify function whenever the | 84 | * @call_notify: If set, then call the handler's notify function whenever the |
@@ -90,6 +96,7 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv); | |||
90 | * @maximum: The control's maximum value. | 96 | * @maximum: The control's maximum value. |
91 | * @default_value: The control's default value. | 97 | * @default_value: The control's default value. |
92 | * @step: The control's step value for non-menu controls. | 98 | * @step: The control's step value for non-menu controls. |
99 | * @elem_size: The size in bytes of the control. | ||
93 | * @menu_skip_mask: The control's skip mask for menu controls. This makes it | 100 | * @menu_skip_mask: The control's skip mask for menu controls. This makes it |
94 | * easy to skip menu items that are not valid. If bit X is set, | 101 | * easy to skip menu items that are not valid. If bit X is set, |
95 | * then menu item X is skipped. Of course, this only works for | 102 | * then menu item X is skipped. Of course, this only works for |
@@ -104,7 +111,6 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv); | |||
104 | * @cur: The control's current value. | 111 | * @cur: The control's current value. |
105 | * @val: The control's new s32 value. | 112 | * @val: The control's new s32 value. |
106 | * @val64: The control's new s64 value. | 113 | * @val64: The control's new s64 value. |
107 | * @string: The control's new string value. | ||
108 | * @priv: The control's private pointer. For use by the driver. It is | 114 | * @priv: The control's private pointer. For use by the driver. It is |
109 | * untouched by the control framework. Note that this pointer is | 115 | * untouched by the control framework. Note that this pointer is |
110 | * not freed when the control is deleted. Should this be needed | 116 | * not freed when the control is deleted. Should this be needed |
@@ -123,6 +129,9 @@ struct v4l2_ctrl { | |||
123 | unsigned int is_new:1; | 129 | unsigned int is_new:1; |
124 | unsigned int is_private:1; | 130 | unsigned int is_private:1; |
125 | unsigned int is_auto:1; | 131 | unsigned int is_auto:1; |
132 | unsigned int is_int:1; | ||
133 | unsigned int is_string:1; | ||
134 | unsigned int is_ptr:1; | ||
126 | unsigned int has_volatiles:1; | 135 | unsigned int has_volatiles:1; |
127 | unsigned int call_notify:1; | 136 | unsigned int call_notify:1; |
128 | unsigned int manual_mode_value:8; | 137 | unsigned int manual_mode_value:8; |
@@ -132,6 +141,7 @@ struct v4l2_ctrl { | |||
132 | const char *name; | 141 | const char *name; |
133 | enum v4l2_ctrl_type type; | 142 | enum v4l2_ctrl_type type; |
134 | s64 minimum, maximum, default_value; | 143 | s64 minimum, maximum, default_value; |
144 | u32 elem_size; | ||
135 | union { | 145 | union { |
136 | u64 step; | 146 | u64 step; |
137 | u64 menu_skip_mask; | 147 | u64 menu_skip_mask; |
@@ -141,17 +151,19 @@ struct v4l2_ctrl { | |||
141 | const s64 *qmenu_int; | 151 | const s64 *qmenu_int; |
142 | }; | 152 | }; |
143 | unsigned long flags; | 153 | unsigned long flags; |
154 | void *priv; | ||
144 | union { | 155 | union { |
145 | s32 val; | 156 | s32 val; |
146 | s64 val64; | 157 | s64 val64; |
147 | char *string; | 158 | char *string; |
148 | } cur; | 159 | void *p; |
160 | }; | ||
149 | union { | 161 | union { |
150 | s32 val; | 162 | s32 val; |
151 | s64 val64; | 163 | s64 val64; |
152 | char *string; | 164 | char *string; |
153 | }; | 165 | void *p; |
154 | void *priv; | 166 | } cur; |
155 | }; | 167 | }; |
156 | 168 | ||
157 | /** struct v4l2_ctrl_ref - The control reference. | 169 | /** struct v4l2_ctrl_ref - The control reference. |
@@ -212,6 +224,7 @@ struct v4l2_ctrl_handler { | |||
212 | * @max: The control's maximum value. | 224 | * @max: The control's maximum value. |
213 | * @step: The control's step value for non-menu controls. | 225 | * @step: The control's step value for non-menu controls. |
214 | * @def: The control's default value. | 226 | * @def: The control's default value. |
227 | * @elem_size: The size in bytes of the control. | ||
215 | * @flags: The control's flags. | 228 | * @flags: The control's flags. |
216 | * @menu_skip_mask: The control's skip mask for menu controls. This makes it | 229 | * @menu_skip_mask: The control's skip mask for menu controls. This makes it |
217 | * easy to skip menu items that are not valid. If bit X is set, | 230 | * easy to skip menu items that are not valid. If bit X is set, |
@@ -235,6 +248,7 @@ struct v4l2_ctrl_config { | |||
235 | s64 max; | 248 | s64 max; |
236 | u64 step; | 249 | u64 step; |
237 | s64 def; | 250 | s64 def; |
251 | u32 elem_size; | ||
238 | u32 flags; | 252 | u32 flags; |
239 | u64 menu_skip_mask; | 253 | u64 menu_skip_mask; |
240 | const char * const *qmenu; | 254 | const char * const *qmenu; |
@@ -659,6 +673,7 @@ unsigned int v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait); | |||
659 | 673 | ||
660 | /* Helpers for ioctl_ops. If hdl == NULL then they will all return -EINVAL. */ | 674 | /* Helpers for ioctl_ops. If hdl == NULL then they will all return -EINVAL. */ |
661 | int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc); | 675 | int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc); |
676 | int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctrl *qc); | ||
662 | int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm); | 677 | int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm); |
663 | int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *ctrl); | 678 | int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *ctrl); |
664 | int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, | 679 | int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, |