aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/v4l2-core/v4l2-ctrls.c58
-rw-r--r--include/media/v4l2-ctrls.h8
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
1164static bool std_equal(const struct v4l2_ctrl *ctrl, 1164static 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
1183static void std_init(const struct v4l2_ctrl *ctrl, 1183static 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 */
1252static int std_validate(const struct v4l2_ctrl *ctrl, 1260static 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 */
76struct v4l2_ctrl_type_ops { 76struct 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;