diff options
-rw-r--r-- | drivers/media/v4l2-core/v4l2-ctrls.c | 58 | ||||
-rw-r--r-- | include/media/v4l2-ctrls.h | 8 |
2 files changed, 44 insertions, 22 deletions
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index e6c98a705b19..6ed2d5608611 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c | |||
@@ -1161,7 +1161,7 @@ static void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes) | |||
1161 | v4l2_event_queue_fh(sev->fh, &ev); | 1161 | v4l2_event_queue_fh(sev->fh, &ev); |
1162 | } | 1162 | } |
1163 | 1163 | ||
1164 | static bool std_equal(const struct v4l2_ctrl *ctrl, | 1164 | static bool std_equal(const struct v4l2_ctrl *ctrl, u32 idx, |
1165 | union v4l2_ctrl_ptr ptr1, | 1165 | union v4l2_ctrl_ptr ptr1, |
1166 | union v4l2_ctrl_ptr ptr2) | 1166 | union v4l2_ctrl_ptr ptr2) |
1167 | { | 1167 | { |
@@ -1180,7 +1180,7 @@ static bool std_equal(const struct v4l2_ctrl *ctrl, | |||
1180 | } | 1180 | } |
1181 | } | 1181 | } |
1182 | 1182 | ||
1183 | static void std_init(const struct v4l2_ctrl *ctrl, | 1183 | static void std_init(const struct v4l2_ctrl *ctrl, u32 idx, |
1184 | union v4l2_ctrl_ptr ptr) | 1184 | union v4l2_ctrl_ptr ptr) |
1185 | { | 1185 | { |
1186 | switch (ctrl->type) { | 1186 | switch (ctrl->type) { |
@@ -1207,6 +1207,14 @@ static void std_log(const struct v4l2_ctrl *ctrl) | |||
1207 | { | 1207 | { |
1208 | union v4l2_ctrl_ptr ptr = ctrl->p_cur; | 1208 | union v4l2_ctrl_ptr ptr = ctrl->p_cur; |
1209 | 1209 | ||
1210 | if (ctrl->is_array) { | ||
1211 | unsigned i; | ||
1212 | |||
1213 | for (i = 0; i < ctrl->nr_of_dims; i++) | ||
1214 | pr_cont("[%u]", ctrl->dims[i]); | ||
1215 | pr_cont(" "); | ||
1216 | } | ||
1217 | |||
1210 | switch (ctrl->type) { | 1218 | switch (ctrl->type) { |
1211 | case V4L2_CTRL_TYPE_INTEGER: | 1219 | case V4L2_CTRL_TYPE_INTEGER: |
1212 | pr_cont("%d", *ptr.p_s32); | 1220 | pr_cont("%d", *ptr.p_s32); |
@@ -1249,7 +1257,7 @@ static void std_log(const struct v4l2_ctrl *ctrl) | |||
1249 | }) | 1257 | }) |
1250 | 1258 | ||
1251 | /* Validate a new control */ | 1259 | /* Validate a new control */ |
1252 | static int std_validate(const struct v4l2_ctrl *ctrl, | 1260 | static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx, |
1253 | union v4l2_ctrl_ptr ptr) | 1261 | union v4l2_ctrl_ptr ptr) |
1254 | { | 1262 | { |
1255 | size_t len; | 1263 | size_t len; |
@@ -1473,8 +1481,8 @@ static int cluster_changed(struct v4l2_ctrl *master) | |||
1473 | 1481 | ||
1474 | if (ctrl == NULL) | 1482 | if (ctrl == NULL) |
1475 | continue; | 1483 | continue; |
1476 | ctrl->has_changed = !ctrl->type_ops->equal(ctrl, | 1484 | ctrl->has_changed = !ctrl->type_ops->equal(ctrl, 0, |
1477 | ctrl->p_cur, ctrl->p_new); | 1485 | ctrl->p_cur, ctrl->p_new); |
1478 | changed |= ctrl->has_changed; | 1486 | changed |= ctrl->has_changed; |
1479 | } | 1487 | } |
1480 | return changed; | 1488 | return changed; |
@@ -1531,15 +1539,15 @@ static int validate_new(const struct v4l2_ctrl *ctrl, | |||
1531 | case V4L2_CTRL_TYPE_BUTTON: | 1539 | case V4L2_CTRL_TYPE_BUTTON: |
1532 | case V4L2_CTRL_TYPE_CTRL_CLASS: | 1540 | case V4L2_CTRL_TYPE_CTRL_CLASS: |
1533 | ptr.p_s32 = &c->value; | 1541 | ptr.p_s32 = &c->value; |
1534 | return ctrl->type_ops->validate(ctrl, ptr); | 1542 | return ctrl->type_ops->validate(ctrl, 0, ptr); |
1535 | 1543 | ||
1536 | case V4L2_CTRL_TYPE_INTEGER64: | 1544 | case V4L2_CTRL_TYPE_INTEGER64: |
1537 | ptr.p_s64 = &c->value64; | 1545 | ptr.p_s64 = &c->value64; |
1538 | return ctrl->type_ops->validate(ctrl, ptr); | 1546 | return ctrl->type_ops->validate(ctrl, 0, ptr); |
1539 | 1547 | ||
1540 | default: | 1548 | default: |
1541 | ptr.p = c->ptr; | 1549 | ptr.p = c->ptr; |
1542 | return ctrl->type_ops->validate(ctrl, ptr); | 1550 | return ctrl->type_ops->validate(ctrl, 0, ptr); |
1543 | } | 1551 | } |
1544 | } | 1552 | } |
1545 | 1553 | ||
@@ -1767,6 +1775,8 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, | |||
1767 | unsigned sz_extra; | 1775 | unsigned sz_extra; |
1768 | unsigned nr_of_dims = 0; | 1776 | unsigned nr_of_dims = 0; |
1769 | unsigned elems = 1; | 1777 | unsigned elems = 1; |
1778 | bool is_array; | ||
1779 | unsigned tot_ctrl_size; | ||
1770 | void *data; | 1780 | void *data; |
1771 | int err; | 1781 | int err; |
1772 | 1782 | ||
@@ -1779,6 +1789,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, | |||
1779 | if (nr_of_dims == V4L2_CTRL_MAX_DIMS) | 1789 | if (nr_of_dims == V4L2_CTRL_MAX_DIMS) |
1780 | break; | 1790 | break; |
1781 | } | 1791 | } |
1792 | is_array = nr_of_dims > 0; | ||
1782 | 1793 | ||
1783 | if (type == V4L2_CTRL_TYPE_INTEGER64) | 1794 | if (type == V4L2_CTRL_TYPE_INTEGER64) |
1784 | elem_size = sizeof(s64); | 1795 | elem_size = sizeof(s64); |
@@ -1786,10 +1797,11 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, | |||
1786 | elem_size = max + 1; | 1797 | elem_size = max + 1; |
1787 | else if (type < V4L2_CTRL_COMPOUND_TYPES) | 1798 | else if (type < V4L2_CTRL_COMPOUND_TYPES) |
1788 | elem_size = sizeof(s32); | 1799 | elem_size = sizeof(s32); |
1800 | tot_ctrl_size = elem_size * elems; | ||
1789 | 1801 | ||
1790 | /* Sanity checks */ | 1802 | /* Sanity checks */ |
1791 | if (id == 0 || name == NULL || id >= V4L2_CID_PRIVATE_BASE || | 1803 | if (id == 0 || name == NULL || !elem_size || |
1792 | elem_size == 0 || | 1804 | id >= V4L2_CID_PRIVATE_BASE || |
1793 | (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) || | 1805 | (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) || |
1794 | (type == V4L2_CTRL_TYPE_INTEGER_MENU && qmenu_int == NULL)) { | 1806 | (type == V4L2_CTRL_TYPE_INTEGER_MENU && qmenu_int == NULL)) { |
1795 | handler_set_err(hdl, -ERANGE); | 1807 | handler_set_err(hdl, -ERANGE); |
@@ -1804,6 +1816,12 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, | |||
1804 | handler_set_err(hdl, -ERANGE); | 1816 | handler_set_err(hdl, -ERANGE); |
1805 | return NULL; | 1817 | return NULL; |
1806 | } | 1818 | } |
1819 | if (is_array && | ||
1820 | (type == V4L2_CTRL_TYPE_BUTTON || | ||
1821 | type == V4L2_CTRL_TYPE_CTRL_CLASS)) { | ||
1822 | handler_set_err(hdl, -EINVAL); | ||
1823 | return NULL; | ||
1824 | } | ||
1807 | 1825 | ||
1808 | sz_extra = 0; | 1826 | sz_extra = 0; |
1809 | if (type == V4L2_CTRL_TYPE_BUTTON) | 1827 | if (type == V4L2_CTRL_TYPE_BUTTON) |
@@ -1812,8 +1830,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, | |||
1812 | flags |= V4L2_CTRL_FLAG_READ_ONLY; | 1830 | flags |= V4L2_CTRL_FLAG_READ_ONLY; |
1813 | else if (type == V4L2_CTRL_TYPE_INTEGER64 || | 1831 | else if (type == V4L2_CTRL_TYPE_INTEGER64 || |
1814 | type == V4L2_CTRL_TYPE_STRING || | 1832 | type == V4L2_CTRL_TYPE_STRING || |
1815 | type >= V4L2_CTRL_COMPOUND_TYPES) | 1833 | type >= V4L2_CTRL_COMPOUND_TYPES || |
1816 | sz_extra += 2 * elem_size; | 1834 | is_array) |
1835 | sz_extra += 2 * tot_ctrl_size; | ||
1817 | 1836 | ||
1818 | ctrl = kzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL); | 1837 | ctrl = kzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL); |
1819 | if (ctrl == NULL) { | 1838 | if (ctrl == NULL) { |
@@ -1834,9 +1853,10 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, | |||
1834 | ctrl->maximum = max; | 1853 | ctrl->maximum = max; |
1835 | ctrl->step = step; | 1854 | ctrl->step = step; |
1836 | ctrl->default_value = def; | 1855 | ctrl->default_value = def; |
1837 | ctrl->is_string = type == V4L2_CTRL_TYPE_STRING; | 1856 | ctrl->is_string = !is_array && type == V4L2_CTRL_TYPE_STRING; |
1838 | ctrl->is_ptr = type >= V4L2_CTRL_COMPOUND_TYPES || ctrl->is_string; | 1857 | ctrl->is_ptr = is_array || type >= V4L2_CTRL_COMPOUND_TYPES || ctrl->is_string; |
1839 | ctrl->is_int = !ctrl->is_ptr && type != V4L2_CTRL_TYPE_INTEGER64; | 1858 | ctrl->is_int = !ctrl->is_ptr && type != V4L2_CTRL_TYPE_INTEGER64; |
1859 | ctrl->is_array = is_array; | ||
1840 | ctrl->elems = elems; | 1860 | ctrl->elems = elems; |
1841 | ctrl->nr_of_dims = nr_of_dims; | 1861 | ctrl->nr_of_dims = nr_of_dims; |
1842 | if (nr_of_dims) | 1862 | if (nr_of_dims) |
@@ -1852,13 +1872,13 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, | |||
1852 | 1872 | ||
1853 | if (!ctrl->is_int) { | 1873 | if (!ctrl->is_int) { |
1854 | ctrl->p_new.p = data; | 1874 | ctrl->p_new.p = data; |
1855 | ctrl->p_cur.p = data + elem_size; | 1875 | ctrl->p_cur.p = data + tot_ctrl_size; |
1856 | } else { | 1876 | } else { |
1857 | ctrl->p_new.p = &ctrl->val; | 1877 | ctrl->p_new.p = &ctrl->val; |
1858 | ctrl->p_cur.p = &ctrl->cur.val; | 1878 | ctrl->p_cur.p = &ctrl->cur.val; |
1859 | } | 1879 | } |
1860 | ctrl->type_ops->init(ctrl, ctrl->p_cur); | 1880 | ctrl->type_ops->init(ctrl, 0, ctrl->p_cur); |
1861 | ctrl->type_ops->init(ctrl, ctrl->p_new); | 1881 | ctrl->type_ops->init(ctrl, 0, ctrl->p_new); |
1862 | 1882 | ||
1863 | if (handler_new_ref(hdl, ctrl)) { | 1883 | if (handler_new_ref(hdl, ctrl)) { |
1864 | kfree(ctrl); | 1884 | kfree(ctrl); |
@@ -2764,7 +2784,7 @@ s64 v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl *ctrl) | |||
2764 | struct v4l2_ext_control c; | 2784 | struct v4l2_ext_control c; |
2765 | 2785 | ||
2766 | /* It's a driver bug if this happens. */ | 2786 | /* It's a driver bug if this happens. */ |
2767 | WARN_ON(ctrl->type != V4L2_CTRL_TYPE_INTEGER64); | 2787 | WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64); |
2768 | c.value = 0; | 2788 | c.value = 0; |
2769 | get_ctrl(ctrl, &c); | 2789 | get_ctrl(ctrl, &c); |
2770 | return c.value; | 2790 | return c.value; |
@@ -3074,7 +3094,7 @@ int v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val) | |||
3074 | struct v4l2_ext_control c; | 3094 | struct v4l2_ext_control c; |
3075 | 3095 | ||
3076 | /* It's a driver bug if this happens. */ | 3096 | /* It's a driver bug if this happens. */ |
3077 | WARN_ON(ctrl->type != V4L2_CTRL_TYPE_INTEGER64); | 3097 | WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64); |
3078 | c.value64 = val; | 3098 | c.value64 = val; |
3079 | return set_ctrl_lock(NULL, ctrl, &c); | 3099 | return set_ctrl_lock(NULL, ctrl, &c); |
3080 | } | 3100 | } |
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index d30da09b7b69..7915b1125bb5 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h | |||
@@ -74,13 +74,13 @@ struct v4l2_ctrl_ops { | |||
74 | * @validate: validate the value. Return 0 on success and a negative value otherwise. | 74 | * @validate: validate the value. Return 0 on success and a negative value otherwise. |
75 | */ | 75 | */ |
76 | struct v4l2_ctrl_type_ops { | 76 | struct v4l2_ctrl_type_ops { |
77 | bool (*equal)(const struct v4l2_ctrl *ctrl, | 77 | bool (*equal)(const struct v4l2_ctrl *ctrl, u32 idx, |
78 | union v4l2_ctrl_ptr ptr1, | 78 | union v4l2_ctrl_ptr ptr1, |
79 | union v4l2_ctrl_ptr ptr2); | 79 | union v4l2_ctrl_ptr ptr2); |
80 | void (*init)(const struct v4l2_ctrl *ctrl, | 80 | void (*init)(const struct v4l2_ctrl *ctrl, u32 idx, |
81 | union v4l2_ctrl_ptr ptr); | 81 | union v4l2_ctrl_ptr ptr); |
82 | void (*log)(const struct v4l2_ctrl *ctrl); | 82 | void (*log)(const struct v4l2_ctrl *ctrl); |
83 | int (*validate)(const struct v4l2_ctrl *ctrl, | 83 | int (*validate)(const struct v4l2_ctrl *ctrl, u32 idx, |
84 | union v4l2_ctrl_ptr ptr); | 84 | union v4l2_ctrl_ptr ptr); |
85 | }; | 85 | }; |
86 | 86 | ||
@@ -111,6 +111,7 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv); | |||
111 | * @is_ptr: If set, then this control is an array and/or has type >= V4L2_CTRL_COMPOUND_TYPES | 111 | * @is_ptr: If set, then this control is an array and/or has type >= V4L2_CTRL_COMPOUND_TYPES |
112 | * and/or has type V4L2_CTRL_TYPE_STRING. In other words, struct | 112 | * and/or has type V4L2_CTRL_TYPE_STRING. In other words, struct |
113 | * v4l2_ext_control uses field p to point to the data. | 113 | * v4l2_ext_control uses field p to point to the data. |
114 | * @is_array: If set, then this control contains an N-dimensional array. | ||
114 | * @has_volatiles: If set, then one or more members of the cluster are volatile. | 115 | * @has_volatiles: If set, then one or more members of the cluster are volatile. |
115 | * Drivers should never touch this flag. | 116 | * Drivers should never touch this flag. |
116 | * @call_notify: If set, then call the handler's notify function whenever the | 117 | * @call_notify: If set, then call the handler's notify function whenever the |
@@ -169,6 +170,7 @@ struct v4l2_ctrl { | |||
169 | unsigned int is_int:1; | 170 | unsigned int is_int:1; |
170 | unsigned int is_string:1; | 171 | unsigned int is_string:1; |
171 | unsigned int is_ptr:1; | 172 | unsigned int is_ptr:1; |
173 | unsigned int is_array:1; | ||
172 | unsigned int has_volatiles:1; | 174 | unsigned int has_volatiles:1; |
173 | unsigned int call_notify:1; | 175 | unsigned int call_notify:1; |
174 | unsigned int manual_mode_value:8; | 176 | unsigned int manual_mode_value:8; |