Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

media: v4l2-ctrls: add support for V4L2_CTRL_WHICH_MIN/MAX_VAL

Add the capability of retrieving the min and max values of a
compound control.

[Ricardo: Added static to v4l2_ctrl_type_op_(maximum|minimum) proto]
[Ricardo: Fix documentation]

Signed-off-by: Yunke Cao <yunkec@google.com>
Tested-by: Yunke Cao <yunkec@google.com>
Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
Link: https://lore.kernel.org/r/20250203-uvc-roi-v17-2-5900a9fed613@chromium.org
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
[hverkuil: fix small alignment checkpatch warning]

+248 -49
+17 -5
Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst
··· 338 338 - Which value of the control to get/set/try. 339 339 * - :cspan:`2` ``V4L2_CTRL_WHICH_CUR_VAL`` will return the current value of 340 340 the control, ``V4L2_CTRL_WHICH_DEF_VAL`` will return the default 341 - value of the control and ``V4L2_CTRL_WHICH_REQUEST_VAL`` indicates that 342 - these controls have to be retrieved from a request or tried/set for 343 - a request. In the latter case the ``request_fd`` field contains the 341 + value of the control, ``V4L2_CTRL_WHICH_MIN_VAL`` will return the minimum 342 + value of the control, and ``V4L2_CTRL_WHICH_MAX_VAL`` will return the maximum 343 + value of the control. ``V4L2_CTRL_WHICH_REQUEST_VAL`` indicates that 344 + the control value has to be retrieved from a request or tried/set for 345 + a request. In that case the ``request_fd`` field contains the 344 346 file descriptor of the request that should be used. If the device 345 347 does not support requests, then ``EACCES`` will be returned. 346 348 347 - When using ``V4L2_CTRL_WHICH_DEF_VAL`` be aware that you can only 348 - get the default value of the control, you cannot set or try it. 349 + When using ``V4L2_CTRL_WHICH_DEF_VAL``, ``V4L2_CTRL_WHICH_MIN_VAL`` 350 + or ``V4L2_CTRL_WHICH_MAX_VAL`` be aware that you can only get the 351 + default/minimum/maximum value of the control, you cannot set or try it. 352 + 353 + Whether a control supports querying the minimum and maximum values using 354 + ``V4L2_CTRL_WHICH_MIN_VAL`` and ``V4L2_CTRL_WHICH_MAX_VAL`` is indicated 355 + by the ``V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX`` flag. Most non-compound 356 + control types support this. For controls with compound types, the 357 + definition of minimum/maximum values are provided by 358 + the control documentation. If a compound control does not document the 359 + meaning of minimum/maximum value, then querying the minimum or maximum 360 + value will result in the error code -EINVAL. 349 361 350 362 For backwards compatibility you can also use a control class here 351 363 (see :ref:`ctrl-class`). In that case all controls have to
+8 -1
Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst
··· 447 447 - n/a 448 448 - A struct :c:type:`v4l2_rect`, containing a rectangle described by 449 449 the position of its top-left corner, the width and the height. Units 450 - depend on the use case. 450 + depend on the use case. Support for ``V4L2_CTRL_WHICH_MIN_VAL`` and 451 + ``V4L2_CTRL_WHICH_MAX_VAL`` is optional and depends on the 452 + ``V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX`` flag. See the documentation of 453 + the specific control on how to interpret the minimum and maximum values. 451 454 * - ``V4L2_CTRL_TYPE_H264_SPS`` 452 455 - n/a 453 456 - n/a ··· 667 664 ``dims[0]``. So setting the control with a differently sized 668 665 array will change the ``elems`` field when the control is 669 666 queried afterwards. 667 + * - ``V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX`` 668 + - 0x1000 669 + - This control supports getting minimum and maximum values using 670 + vidioc_g_ext_ctrls with V4L2_CTRL_WHICH_MIN/MAX_VAL. 670 671 671 672 Return Value 672 673 ============
+3
Documentation/userspace-api/media/videodev2.h.rst.exceptions
··· 396 396 replace define V4L2_CTRL_FLAG_EXECUTE_ON_WRITE control-flags 397 397 replace define V4L2_CTRL_FLAG_MODIFY_LAYOUT control-flags 398 398 replace define V4L2_CTRL_FLAG_DYNAMIC_ARRAY control-flags 399 + replace define V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX control-flags 399 400 400 401 replace define V4L2_CTRL_FLAG_NEXT_CTRL control 401 402 replace define V4L2_CTRL_FLAG_NEXT_COMPOUND control ··· 571 570 ignore define V4L2_CTRL_MAX_DIMS 572 571 ignore define V4L2_CTRL_WHICH_CUR_VAL 573 572 ignore define V4L2_CTRL_WHICH_DEF_VAL 573 + ignore define V4L2_CTRL_WHICH_MIN_VAL 574 + ignore define V4L2_CTRL_WHICH_MAX_VAL 574 575 ignore define V4L2_CTRL_WHICH_REQUEST_VAL 575 576 ignore define V4L2_OUT_CAP_CUSTOM_TIMINGS 576 577 ignore define V4L2_CID_MAX_CTRLS
+3 -1
drivers/media/i2c/imx214.c
··· 988 988 imx214->unit_size = v4l2_ctrl_new_std_compound(ctrl_hdlr, 989 989 NULL, 990 990 V4L2_CID_UNIT_CELL_SIZE, 991 - v4l2_ctrl_ptr_create((void *)&unit_size)); 991 + v4l2_ctrl_ptr_create((void *)&unit_size), 992 + v4l2_ctrl_ptr_create(NULL), 993 + v4l2_ctrl_ptr_create(NULL)); 992 994 993 995 v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx214_ctrl_ops, &props); 994 996
+7 -2
drivers/media/platform/qcom/venus/venc_ctrls.c
··· 662 662 663 663 v4l2_ctrl_new_std_compound(&inst->ctrl_handler, &venc_ctrl_ops, 664 664 V4L2_CID_COLORIMETRY_HDR10_CLL_INFO, 665 - v4l2_ctrl_ptr_create(&p_hdr10_cll)); 665 + v4l2_ctrl_ptr_create(&p_hdr10_cll), 666 + v4l2_ctrl_ptr_create(NULL), 667 + v4l2_ctrl_ptr_create(NULL)); 666 668 667 669 v4l2_ctrl_new_std_compound(&inst->ctrl_handler, &venc_ctrl_ops, 668 670 V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY, 669 - v4l2_ctrl_ptr_create((void *)&p_hdr10_mastering)); 671 + v4l2_ctrl_ptr_create((void *)&p_hdr10_mastering), 672 + v4l2_ctrl_ptr_create(NULL), 673 + v4l2_ctrl_ptr_create(NULL)); 674 + 670 675 671 676 v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, 672 677 V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE,
+44 -10
drivers/media/v4l2-core/v4l2-ctrls-api.c
··· 94 94 return ptr_to_user(c, ctrl, ctrl->p_new); 95 95 } 96 96 97 + /* Helper function: copy the minimum control value back to the caller */ 98 + static int min_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl) 99 + { 100 + ctrl->type_ops->minimum(ctrl, 0, ctrl->p_new); 101 + 102 + return ptr_to_user(c, ctrl, ctrl->p_new); 103 + } 104 + 105 + /* Helper function: copy the maximum control value back to the caller */ 106 + static int max_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl) 107 + { 108 + ctrl->type_ops->maximum(ctrl, 0, ctrl->p_new); 109 + 110 + return ptr_to_user(c, ctrl, ctrl->p_new); 111 + } 112 + 97 113 /* Helper function: copy the caller-provider value as the new control value */ 98 114 static int user_to_new(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl) 99 115 { ··· 245 229 cs->error_idx = i; 246 230 247 231 if (cs->which && 248 - cs->which != V4L2_CTRL_WHICH_DEF_VAL && 249 - cs->which != V4L2_CTRL_WHICH_REQUEST_VAL && 232 + (cs->which < V4L2_CTRL_WHICH_DEF_VAL || 233 + cs->which > V4L2_CTRL_WHICH_MAX_VAL) && 250 234 V4L2_CTRL_ID2WHICH(id) != cs->which) { 251 235 dprintk(vdev, 252 236 "invalid which 0x%x or control id 0x%x\n", ··· 272 256 ctrl = ref->ctrl; 273 257 if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED) { 274 258 dprintk(vdev, "control id 0x%x is disabled\n", id); 259 + return -EINVAL; 260 + } 261 + 262 + if (!(ctrl->flags & V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX) && 263 + (cs->which == V4L2_CTRL_WHICH_MIN_VAL || 264 + cs->which == V4L2_CTRL_WHICH_MAX_VAL)) { 265 + dprintk(vdev, 266 + "invalid which 0x%x or control id 0x%x\n", 267 + cs->which, id); 275 268 return -EINVAL; 276 269 } 277 270 ··· 393 368 */ 394 369 static int class_check(struct v4l2_ctrl_handler *hdl, u32 which) 395 370 { 396 - if (which == 0 || which == V4L2_CTRL_WHICH_DEF_VAL || 397 - which == V4L2_CTRL_WHICH_REQUEST_VAL) 371 + if (which == 0 || (which >= V4L2_CTRL_WHICH_DEF_VAL && 372 + which <= V4L2_CTRL_WHICH_MAX_VAL)) 398 373 return 0; 399 374 return find_ref_lock(hdl, which | 1) ? 0 : -EINVAL; 400 375 } ··· 414 389 struct v4l2_ctrl_helper *helpers = helper; 415 390 int ret; 416 391 int i, j; 417 - bool is_default, is_request; 392 + bool is_default, is_request, is_min, is_max; 418 393 419 394 is_default = (cs->which == V4L2_CTRL_WHICH_DEF_VAL); 420 395 is_request = (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL); 396 + is_min = (cs->which == V4L2_CTRL_WHICH_MIN_VAL); 397 + is_max = (cs->which == V4L2_CTRL_WHICH_MAX_VAL); 421 398 422 399 cs->error_idx = cs->count; 423 400 cs->which = V4L2_CTRL_ID2WHICH(cs->which); ··· 459 432 460 433 /* 461 434 * g_volatile_ctrl will update the new control values. 462 - * This makes no sense for V4L2_CTRL_WHICH_DEF_VAL and 435 + * This makes no sense for V4L2_CTRL_WHICH_DEF_VAL, 436 + * V4L2_CTRL_WHICH_MIN_VAL, V4L2_CTRL_WHICH_MAX_VAL and 463 437 * V4L2_CTRL_WHICH_REQUEST_VAL. In the case of requests 464 438 * it is v4l2_ctrl_request_complete() that copies the 465 439 * volatile controls at the time of request completion 466 440 * to the request, so you don't want to do that again. 467 441 */ 468 - if (!is_default && !is_request && 442 + if (!is_default && !is_request && !is_min && !is_max && 469 443 ((master->flags & V4L2_CTRL_FLAG_VOLATILE) || 470 444 (master->has_volatiles && !is_cur_manual(master)))) { 471 445 for (j = 0; j < master->ncontrols; j++) ··· 495 467 ret = -ENOMEM; 496 468 else if (is_request && ref->p_req_valid) 497 469 ret = req_to_user(cs->controls + idx, ref); 470 + else if (is_min) 471 + ret = min_to_user(cs->controls + idx, ref->ctrl); 472 + else if (is_max) 473 + ret = max_to_user(cs->controls + idx, ref->ctrl); 498 474 else if (is_volatile) 499 475 ret = new_to_user(cs->controls + idx, ref->ctrl); 500 476 else ··· 596 564 597 565 cs->error_idx = cs->count; 598 566 599 - /* Default value cannot be changed */ 600 - if (cs->which == V4L2_CTRL_WHICH_DEF_VAL) { 601 - dprintk(vdev, "%s: cannot change default value\n", 567 + /* Default/minimum/maximum values cannot be changed */ 568 + if (cs->which == V4L2_CTRL_WHICH_DEF_VAL || 569 + cs->which == V4L2_CTRL_WHICH_MIN_VAL || 570 + cs->which == V4L2_CTRL_WHICH_MAX_VAL) { 571 + dprintk(vdev, "%s: cannot change default/min/max value\n", 602 572 video_device_node_name(vdev)); 603 573 return -EINVAL; 604 574 }
+129 -24
drivers/media/v4l2-core/v4l2-ctrls-core.c
··· 182 182 } 183 183 } 184 184 185 - void v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx, 186 - union v4l2_ctrl_ptr ptr) 185 + static void std_min_compound(const struct v4l2_ctrl *ctrl, u32 idx, 186 + union v4l2_ctrl_ptr ptr) 187 + { 188 + void *p = ptr.p + idx * ctrl->elem_size; 189 + 190 + if (ctrl->p_min.p_const) 191 + memcpy(p, ctrl->p_min.p_const, ctrl->elem_size); 192 + else 193 + memset(p, 0, ctrl->elem_size); 194 + } 195 + 196 + static void std_max_compound(const struct v4l2_ctrl *ctrl, u32 idx, 197 + union v4l2_ctrl_ptr ptr) 198 + { 199 + void *p = ptr.p + idx * ctrl->elem_size; 200 + 201 + if (ctrl->p_max.p_const) 202 + memcpy(p, ctrl->p_max.p_const, ctrl->elem_size); 203 + else 204 + memset(p, 0, ctrl->elem_size); 205 + } 206 + 207 + static void __v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx, 208 + u32 which, union v4l2_ctrl_ptr ptr) 187 209 { 188 210 unsigned int i; 189 211 u32 tot_elems = ctrl->elems; 190 212 u32 elems = tot_elems - from_idx; 213 + s64 value; 191 214 192 - if (from_idx >= tot_elems) 215 + switch (which) { 216 + case V4L2_CTRL_WHICH_DEF_VAL: 217 + value = ctrl->default_value; 218 + break; 219 + case V4L2_CTRL_WHICH_MAX_VAL: 220 + value = ctrl->maximum; 221 + break; 222 + case V4L2_CTRL_WHICH_MIN_VAL: 223 + value = ctrl->minimum; 224 + break; 225 + default: 193 226 return; 227 + } 194 228 195 229 switch (ctrl->type) { 196 230 case V4L2_CTRL_TYPE_STRING: 231 + if (which == V4L2_CTRL_WHICH_DEF_VAL) 232 + value = ctrl->minimum; 233 + 197 234 for (i = from_idx; i < tot_elems; i++) { 198 235 unsigned int offset = i * ctrl->elem_size; 199 236 200 - memset(ptr.p_char + offset, ' ', ctrl->minimum); 201 - ptr.p_char[offset + ctrl->minimum] = '\0'; 237 + memset(ptr.p_char + offset, ' ', value); 238 + ptr.p_char[offset + value] = '\0'; 202 239 } 203 240 break; 204 241 case V4L2_CTRL_TYPE_INTEGER64: 205 - if (ctrl->default_value) { 242 + if (value) { 206 243 for (i = from_idx; i < tot_elems; i++) 207 - ptr.p_s64[i] = ctrl->default_value; 244 + ptr.p_s64[i] = value; 208 245 } else { 209 246 memset(ptr.p_s64 + from_idx, 0, elems * sizeof(s64)); 210 247 } ··· 251 214 case V4L2_CTRL_TYPE_MENU: 252 215 case V4L2_CTRL_TYPE_BITMASK: 253 216 case V4L2_CTRL_TYPE_BOOLEAN: 254 - if (ctrl->default_value) { 217 + if (value) { 255 218 for (i = from_idx; i < tot_elems; i++) 256 - ptr.p_s32[i] = ctrl->default_value; 219 + ptr.p_s32[i] = value; 257 220 } else { 258 221 memset(ptr.p_s32 + from_idx, 0, elems * sizeof(s32)); 259 222 } ··· 263 226 memset(ptr.p_s32 + from_idx, 0, elems * sizeof(s32)); 264 227 break; 265 228 case V4L2_CTRL_TYPE_U8: 266 - memset(ptr.p_u8 + from_idx, ctrl->default_value, elems); 229 + memset(ptr.p_u8 + from_idx, value, elems); 267 230 break; 268 231 case V4L2_CTRL_TYPE_U16: 269 - if (ctrl->default_value) { 232 + if (value) { 270 233 for (i = from_idx; i < tot_elems; i++) 271 - ptr.p_u16[i] = ctrl->default_value; 234 + ptr.p_u16[i] = value; 272 235 } else { 273 236 memset(ptr.p_u16 + from_idx, 0, elems * sizeof(u16)); 274 237 } 275 238 break; 276 239 case V4L2_CTRL_TYPE_U32: 277 - if (ctrl->default_value) { 240 + if (value) { 278 241 for (i = from_idx; i < tot_elems; i++) 279 - ptr.p_u32[i] = ctrl->default_value; 242 + ptr.p_u32[i] = value; 280 243 } else { 281 244 memset(ptr.p_u32 + from_idx, 0, elems * sizeof(u32)); 282 245 } 283 246 break; 284 247 default: 285 - for (i = from_idx; i < tot_elems; i++) 286 - std_init_compound(ctrl, i, ptr); 248 + for (i = from_idx; i < tot_elems; i++) { 249 + switch (which) { 250 + case V4L2_CTRL_WHICH_DEF_VAL: 251 + std_init_compound(ctrl, i, ptr); 252 + break; 253 + case V4L2_CTRL_WHICH_MAX_VAL: 254 + std_max_compound(ctrl, i, ptr); 255 + break; 256 + case V4L2_CTRL_WHICH_MIN_VAL: 257 + std_min_compound(ctrl, i, ptr); 258 + break; 259 + } 260 + } 287 261 break; 288 262 } 289 263 } 264 + 265 + void v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx, 266 + union v4l2_ctrl_ptr ptr) 267 + { 268 + __v4l2_ctrl_type_op_init(ctrl, from_idx, V4L2_CTRL_WHICH_DEF_VAL, ptr); 269 + } 290 270 EXPORT_SYMBOL(v4l2_ctrl_type_op_init); 271 + 272 + static void v4l2_ctrl_type_op_minimum(const struct v4l2_ctrl *ctrl, 273 + u32 from_idx, union v4l2_ctrl_ptr ptr) 274 + { 275 + __v4l2_ctrl_type_op_init(ctrl, from_idx, V4L2_CTRL_WHICH_MIN_VAL, ptr); 276 + } 277 + 278 + static void v4l2_ctrl_type_op_maximum(const struct v4l2_ctrl *ctrl, 279 + u32 from_idx, union v4l2_ctrl_ptr ptr) 280 + { 281 + __v4l2_ctrl_type_op_init(ctrl, from_idx, V4L2_CTRL_WHICH_MAX_VAL, ptr); 282 + } 291 283 292 284 void v4l2_ctrl_type_op_log(const struct v4l2_ctrl *ctrl) 293 285 { ··· 1362 1296 static const struct v4l2_ctrl_type_ops std_type_ops = { 1363 1297 .equal = v4l2_ctrl_type_op_equal, 1364 1298 .init = v4l2_ctrl_type_op_init, 1299 + .minimum = v4l2_ctrl_type_op_minimum, 1300 + .maximum = v4l2_ctrl_type_op_maximum, 1365 1301 .log = v4l2_ctrl_type_op_log, 1366 1302 .validate = v4l2_ctrl_type_op_validate, 1367 1303 }; ··· 1836 1768 s64 min, s64 max, u64 step, s64 def, 1837 1769 const u32 dims[V4L2_CTRL_MAX_DIMS], u32 elem_size, 1838 1770 u32 flags, const char * const *qmenu, 1839 - const s64 *qmenu_int, const union v4l2_ctrl_ptr p_def, 1771 + const s64 *qmenu_int, 1772 + const union v4l2_ctrl_ptr p_def, 1773 + const union v4l2_ctrl_ptr p_min, 1774 + const union v4l2_ctrl_ptr p_max, 1840 1775 void *priv) 1841 1776 { 1842 1777 struct v4l2_ctrl *ctrl; ··· 1963 1892 break; 1964 1893 } 1965 1894 1895 + if (type < V4L2_CTRL_COMPOUND_TYPES && 1896 + type != V4L2_CTRL_TYPE_BUTTON && 1897 + type != V4L2_CTRL_TYPE_CTRL_CLASS && 1898 + type != V4L2_CTRL_TYPE_STRING) 1899 + flags |= V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX; 1900 + 1966 1901 /* Sanity checks */ 1967 1902 if (id == 0 || name == NULL || !elem_size || 1968 1903 id >= V4L2_CID_PRIVATE_BASE || ··· 1977 1900 handler_set_err(hdl, -ERANGE); 1978 1901 return NULL; 1979 1902 } 1903 + 1980 1904 err = check_range(type, min, max, step, def); 1981 1905 if (err) { 1982 1906 handler_set_err(hdl, err); ··· 2018 1940 sz_extra += 2 * tot_ctrl_size; 2019 1941 2020 1942 if (type >= V4L2_CTRL_COMPOUND_TYPES && p_def.p_const) 1943 + sz_extra += elem_size; 1944 + if (type >= V4L2_CTRL_COMPOUND_TYPES && p_min.p_const) 1945 + sz_extra += elem_size; 1946 + if (type >= V4L2_CTRL_COMPOUND_TYPES && p_max.p_const) 2021 1947 sz_extra += elem_size; 2022 1948 2023 1949 ctrl = kvzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL); ··· 2088 2006 memcpy(ctrl->p_def.p, p_def.p_const, elem_size); 2089 2007 } 2090 2008 2009 + if (flags & V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX) { 2010 + void *ptr = ctrl->p_def.p; 2011 + 2012 + if (p_min.p_const) { 2013 + ptr += elem_size; 2014 + ctrl->p_min.p = ptr; 2015 + memcpy(ctrl->p_min.p, p_min.p_const, elem_size); 2016 + } 2017 + 2018 + if (p_max.p_const) { 2019 + ptr += elem_size; 2020 + ctrl->p_max.p = ptr; 2021 + memcpy(ctrl->p_max.p, p_max.p_const, elem_size); 2022 + } 2023 + } 2024 + 2091 2025 ctrl->type_ops->init(ctrl, 0, ctrl->p_cur); 2092 2026 cur_to_new(ctrl); 2093 2027 ··· 2154 2056 type, min, max, 2155 2057 is_menu ? cfg->menu_skip_mask : step, def, 2156 2058 cfg->dims, cfg->elem_size, 2157 - flags, qmenu, qmenu_int, cfg->p_def, priv); 2059 + flags, qmenu, qmenu_int, cfg->p_def, cfg->p_min, 2060 + cfg->p_max, priv); 2158 2061 if (ctrl) 2159 2062 ctrl->is_private = cfg->is_private; 2160 2063 return ctrl; ··· 2180 2081 } 2181 2082 return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, 2182 2083 min, max, step, def, NULL, 0, 2183 - flags, NULL, NULL, ptr_null, NULL); 2084 + flags, NULL, NULL, ptr_null, ptr_null, 2085 + ptr_null, NULL); 2184 2086 } 2185 2087 EXPORT_SYMBOL(v4l2_ctrl_new_std); 2186 2088 ··· 2214 2114 } 2215 2115 return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, 2216 2116 0, max, mask, def, NULL, 0, 2217 - flags, qmenu, qmenu_int, ptr_null, NULL); 2117 + flags, qmenu, qmenu_int, ptr_null, ptr_null, 2118 + ptr_null, NULL); 2218 2119 } 2219 2120 EXPORT_SYMBOL(v4l2_ctrl_new_std_menu); 2220 2121 ··· 2247 2146 } 2248 2147 return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, 2249 2148 0, max, mask, def, NULL, 0, 2250 - flags, qmenu, NULL, ptr_null, NULL); 2149 + flags, qmenu, NULL, ptr_null, ptr_null, 2150 + ptr_null, NULL); 2251 2151 2252 2152 } 2253 2153 EXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items); ··· 2256 2154 /* Helper function for standard compound controls */ 2257 2155 struct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl, 2258 2156 const struct v4l2_ctrl_ops *ops, u32 id, 2259 - const union v4l2_ctrl_ptr p_def) 2157 + const union v4l2_ctrl_ptr p_def, 2158 + const union v4l2_ctrl_ptr p_min, 2159 + const union v4l2_ctrl_ptr p_max) 2260 2160 { 2261 2161 const char *name; 2262 2162 enum v4l2_ctrl_type type; ··· 2272 2168 } 2273 2169 return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, 2274 2170 min, max, step, def, NULL, 0, 2275 - flags, NULL, NULL, p_def, NULL); 2171 + flags, NULL, NULL, p_def, p_min, p_max, NULL); 2276 2172 } 2277 2173 EXPORT_SYMBOL(v4l2_ctrl_new_std_compound); 2278 2174 ··· 2296 2192 } 2297 2193 return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, 2298 2194 0, max, 0, def, NULL, 0, 2299 - flags, NULL, qmenu_int, ptr_null, NULL); 2195 + flags, NULL, qmenu_int, ptr_null, ptr_null, 2196 + ptr_null, NULL); 2300 2197 } 2301 2198 EXPORT_SYMBOL(v4l2_ctrl_new_int_menu); 2302 2199
+3 -1
drivers/media/v4l2-core/v4l2-ioctl.c
··· 893 893 return false; 894 894 break; 895 895 case V4L2_CTRL_WHICH_DEF_VAL: 896 - /* Default value cannot be changed */ 896 + case V4L2_CTRL_WHICH_MIN_VAL: 897 + case V4L2_CTRL_WHICH_MAX_VAL: 898 + /* Default, minimum or maximum value cannot be changed */ 897 899 if (ioctl == VIDIOC_S_EXT_CTRLS || 898 900 ioctl == VIDIOC_TRY_EXT_CTRLS) { 899 901 c->error_idx = c->count;
+31 -5
include/media/v4l2-ctrls.h
··· 133 133 * 134 134 * @equal: return true if all ctrl->elems array elements are equal. 135 135 * @init: initialize the value for array elements from from_idx to ctrl->elems. 136 + * @minimum: set the value to the minimum value of the control. 137 + * @maximum: set the value to the maximum value of the control. 136 138 * @log: log the value. 137 139 * @validate: validate the value for ctrl->new_elems array elements. 138 140 * Return 0 on success and a negative value otherwise. ··· 144 142 union v4l2_ctrl_ptr ptr1, union v4l2_ctrl_ptr ptr2); 145 143 void (*init)(const struct v4l2_ctrl *ctrl, u32 from_idx, 146 144 union v4l2_ctrl_ptr ptr); 145 + void (*minimum)(const struct v4l2_ctrl *ctrl, u32 idx, 146 + union v4l2_ctrl_ptr ptr); 147 + void (*maximum)(const struct v4l2_ctrl *ctrl, u32 idx, 148 + union v4l2_ctrl_ptr ptr); 147 149 void (*log)(const struct v4l2_ctrl *ctrl); 148 150 int (*validate)(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr ptr); 149 151 }; ··· 253 247 * @p_def: The control's default value represented via a union which 254 248 * provides a standard way of accessing control types 255 249 * through a pointer (for compound controls only). 250 + * @p_min: The control's minimum value represented via a union which 251 + * provides a standard way of accessing control types 252 + * through a pointer (for compound controls only). 253 + * @p_max: The control's maximum value represented via a union which 254 + * provides a standard way of accessing control types 255 + * through a pointer (for compound controls only). 256 256 * @p_cur: The control's current value represented via a union which 257 257 * provides a standard way of accessing control types 258 258 * through a pointer. ··· 318 306 } cur; 319 307 320 308 union v4l2_ctrl_ptr p_def; 309 + union v4l2_ctrl_ptr p_min; 310 + union v4l2_ctrl_ptr p_max; 321 311 union v4l2_ctrl_ptr p_new; 322 312 union v4l2_ctrl_ptr p_cur; 323 313 }; ··· 439 425 * @step: The control's step value for non-menu controls. 440 426 * @def: The control's default value. 441 427 * @p_def: The control's default value for compound controls. 428 + * @p_min: The control's minimum value for compound controls. 429 + * @p_max: The control's maximum value for compound controls. 442 430 * @dims: The size of each dimension. 443 431 * @elem_size: The size in bytes of the control. 444 432 * @flags: The control's flags. ··· 470 454 u64 step; 471 455 s64 def; 472 456 union v4l2_ctrl_ptr p_def; 457 + union v4l2_ctrl_ptr p_min; 458 + union v4l2_ctrl_ptr p_max; 473 459 u32 dims[V4L2_CTRL_MAX_DIMS]; 474 460 u32 elem_size; 475 461 u32 flags; ··· 741 723 * @ops: The control ops. 742 724 * @id: The control ID. 743 725 * @p_def: The control's default value. 726 + * @p_min: The control's minimum value. 727 + * @p_max: The control's maximum value. 744 728 * 745 - * Sames as v4l2_ctrl_new_std(), but with support to compound controls, thanks 746 - * to the @p_def field. Use v4l2_ctrl_ptr_create() to create @p_def from a 747 - * pointer. Use v4l2_ctrl_ptr_create(NULL) if the default value of the 748 - * compound control should be all zeroes. 729 + * Same as v4l2_ctrl_new_std(), but with support for compound controls. 730 + * To fill in the @p_def, @p_min and @p_max fields, use v4l2_ctrl_ptr_create() 731 + * to convert a pointer to a const union v4l2_ctrl_ptr. 732 + * Use v4l2_ctrl_ptr_create(NULL) if you want the default, minimum or maximum 733 + * value of the compound control to be all zeroes. 734 + * If the compound control does not set the ``V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX`` 735 + * flag, then it does not has minimum and maximum values. In that case just use 736 + * v4l2_ctrl_ptr_create(NULL) for the @p_min and @p_max arguments. 749 737 * 750 738 */ 751 739 struct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl, 752 740 const struct v4l2_ctrl_ops *ops, 753 741 u32 id, 754 - const union v4l2_ctrl_ptr p_def); 742 + const union v4l2_ctrl_ptr p_def, 743 + const union v4l2_ctrl_ptr p_min, 744 + const union v4l2_ctrl_ptr p_max); 755 745 756 746 /** 757 747 * v4l2_ctrl_new_int_menu() - Create a new standard V4L2 integer menu control.
+3
include/uapi/linux/videodev2.h
··· 1912 1912 #define V4L2_CTRL_WHICH_CUR_VAL 0 1913 1913 #define V4L2_CTRL_WHICH_DEF_VAL 0x0f000000 1914 1914 #define V4L2_CTRL_WHICH_REQUEST_VAL 0x0f010000 1915 + #define V4L2_CTRL_WHICH_MIN_VAL 0x0f020000 1916 + #define V4L2_CTRL_WHICH_MAX_VAL 0x0f030000 1915 1917 1916 1918 enum v4l2_ctrl_type { 1917 1919 V4L2_CTRL_TYPE_INTEGER = 1, ··· 2021 2019 #define V4L2_CTRL_FLAG_EXECUTE_ON_WRITE 0x0200 2022 2020 #define V4L2_CTRL_FLAG_MODIFY_LAYOUT 0x0400 2023 2021 #define V4L2_CTRL_FLAG_DYNAMIC_ARRAY 0x0800 2022 + #define V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX 0x1000 2024 2023 2025 2024 /* Query flags, to be ORed with the control ID */ 2026 2025 #define V4L2_CTRL_FLAG_NEXT_CTRL 0x80000000