diff options
author | Sylwester Nawrocki <sylvester.nawrocki@gmail.com> | 2013-01-19 13:51:55 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-02-05 12:04:06 -0500 |
commit | 2ccbe779bcdee130ea7f1525670dc9d60318a981 (patch) | |
tree | f667acca6ab42a0565b062616b3a6f176508e874 | |
parent | af9bb33aa33d4beb5d0ac505d48530a56856f66c (diff) |
[media] v4l2-ctrl: Add helper function for the controls range update
This patch adds a helper function that allows to modify range,
i.e. minimum, maximum, step and default value of a v4l2 control,
after the control has been created and initialized. This is helpful
in situations when range of a control depends on user configurable
parameters, e.g. camera sensor absolute exposure time depending on
an output image resolution and frame rate.
v4l2_ctrl_modify_range() function allows to modify range of an
INTEGER, BOOL, MENU, INTEGER_MENU and BITMASK type controls.
Based on a patch from Hans Verkuil http://patchwork.linuxtv.org/patch/8654.
Signed-off-by: Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | Documentation/DocBook/media/v4l/compat.xml | 4 | ||||
-rw-r--r-- | Documentation/DocBook/media/v4l/v4l2.xml | 4 | ||||
-rw-r--r-- | Documentation/DocBook/media/v4l/vidioc-dqevent.xml | 6 | ||||
-rw-r--r-- | drivers/media/v4l2-core/v4l2-ctrls.c | 143 | ||||
-rw-r--r-- | include/media/v4l2-ctrls.h | 20 | ||||
-rw-r--r-- | include/uapi/linux/videodev2.h | 1 |
6 files changed, 138 insertions, 40 deletions
diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml index ebd2bfd1ee8e..104a1a2b8849 100644 --- a/Documentation/DocBook/media/v4l/compat.xml +++ b/Documentation/DocBook/media/v4l/compat.xml | |||
@@ -2486,6 +2486,10 @@ that used it. It was originally scheduled for removal in 2.6.35. | |||
2486 | <structname>v4l2_buffer</structname>. See <xref | 2486 | <structname>v4l2_buffer</structname>. See <xref |
2487 | linkend="buffer-flags" />.</para> | 2487 | linkend="buffer-flags" />.</para> |
2488 | </listitem> | 2488 | </listitem> |
2489 | <listitem> | ||
2490 | <para>Added <constant>V4L2_EVENT_CTRL_CH_RANGE</constant> control event | ||
2491 | changes flag. See <xref linkend="changes-flags"/>.</para> | ||
2492 | </listitem> | ||
2489 | </orderedlist> | 2493 | </orderedlist> |
2490 | </section> | 2494 | </section> |
2491 | 2495 | ||
diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml index 8fe29427c8e4..c3851a2fb50d 100644 --- a/Documentation/DocBook/media/v4l/v4l2.xml +++ b/Documentation/DocBook/media/v4l/v4l2.xml | |||
@@ -142,10 +142,12 @@ applications. --> | |||
142 | <revision> | 142 | <revision> |
143 | <revnumber>3.9</revnumber> | 143 | <revnumber>3.9</revnumber> |
144 | <date>2012-12-03</date> | 144 | <date>2012-12-03</date> |
145 | <authorinitials>sa</authorinitials> | 145 | <authorinitials>sa, sn</authorinitials> |
146 | <revremark>Added timestamp types to | 146 | <revremark>Added timestamp types to |
147 | <structname>v4l2_buffer</structname>, see <xref | 147 | <structname>v4l2_buffer</structname>, see <xref |
148 | linkend="buffer-flags" />. | 148 | linkend="buffer-flags" />. |
149 | Added <constant>V4L2_EVENT_CTRL_CH_RANGE</constant> control | ||
150 | event changes flag, see <xref linkend="changes-flags"/>. | ||
149 | </revremark> | 151 | </revremark> |
150 | </revision> | 152 | </revision> |
151 | 153 | ||
diff --git a/Documentation/DocBook/media/v4l/vidioc-dqevent.xml b/Documentation/DocBook/media/v4l/vidioc-dqevent.xml index 98a856f9ec30..89891adb928a 100644 --- a/Documentation/DocBook/media/v4l/vidioc-dqevent.xml +++ b/Documentation/DocBook/media/v4l/vidioc-dqevent.xml | |||
@@ -261,6 +261,12 @@ | |||
261 | <entry>This control event was triggered because the control flags | 261 | <entry>This control event was triggered because the control flags |
262 | changed.</entry> | 262 | changed.</entry> |
263 | </row> | 263 | </row> |
264 | <row> | ||
265 | <entry><constant>V4L2_EVENT_CTRL_CH_RANGE</constant></entry> | ||
266 | <entry>0x0004</entry> | ||
267 | <entry>This control event was triggered because the minimum, | ||
268 | maximum, step or the default value of the control changed.</entry> | ||
269 | </row> | ||
264 | </tbody> | 270 | </tbody> |
265 | </tgroup> | 271 | </tgroup> |
266 | </table> | 272 | </table> |
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 7b486ac3f4d9..3f27571b814d 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c | |||
@@ -1158,8 +1158,7 @@ static int new_to_user(struct v4l2_ext_control *c, | |||
1158 | } | 1158 | } |
1159 | 1159 | ||
1160 | /* Copy the new value to the current value. */ | 1160 | /* Copy the new value to the current value. */ |
1161 | static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, | 1161 | static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags) |
1162 | bool update_inactive) | ||
1163 | { | 1162 | { |
1164 | bool changed = false; | 1163 | bool changed = false; |
1165 | 1164 | ||
@@ -1183,8 +1182,8 @@ static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, | |||
1183 | ctrl->cur.val = ctrl->val; | 1182 | ctrl->cur.val = ctrl->val; |
1184 | break; | 1183 | break; |
1185 | } | 1184 | } |
1186 | if (update_inactive) { | 1185 | if (ch_flags & V4L2_EVENT_CTRL_CH_FLAGS) { |
1187 | /* Note: update_inactive can only be true for auto clusters. */ | 1186 | /* Note: CH_FLAGS is only set for auto clusters. */ |
1188 | ctrl->flags &= | 1187 | ctrl->flags &= |
1189 | ~(V4L2_CTRL_FLAG_INACTIVE | V4L2_CTRL_FLAG_VOLATILE); | 1188 | ~(V4L2_CTRL_FLAG_INACTIVE | V4L2_CTRL_FLAG_VOLATILE); |
1190 | if (!is_cur_manual(ctrl->cluster[0])) { | 1189 | if (!is_cur_manual(ctrl->cluster[0])) { |
@@ -1194,14 +1193,13 @@ static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, | |||
1194 | } | 1193 | } |
1195 | fh = NULL; | 1194 | fh = NULL; |
1196 | } | 1195 | } |
1197 | if (changed || update_inactive) { | 1196 | if (changed || ch_flags) { |
1198 | /* If a control was changed that was not one of the controls | 1197 | /* If a control was changed that was not one of the controls |
1199 | modified by the application, then send the event to all. */ | 1198 | modified by the application, then send the event to all. */ |
1200 | if (!ctrl->is_new) | 1199 | if (!ctrl->is_new) |
1201 | fh = NULL; | 1200 | fh = NULL; |
1202 | send_event(fh, ctrl, | 1201 | send_event(fh, ctrl, |
1203 | (changed ? V4L2_EVENT_CTRL_CH_VALUE : 0) | | 1202 | (changed ? V4L2_EVENT_CTRL_CH_VALUE : 0) | ch_flags); |
1204 | (update_inactive ? V4L2_EVENT_CTRL_CH_FLAGS : 0)); | ||
1205 | if (ctrl->call_notify && changed && ctrl->handler->notify) | 1203 | if (ctrl->call_notify && changed && ctrl->handler->notify) |
1206 | ctrl->handler->notify(ctrl, ctrl->handler->notify_priv); | 1204 | ctrl->handler->notify(ctrl, ctrl->handler->notify_priv); |
1207 | } | 1205 | } |
@@ -1257,6 +1255,41 @@ static int cluster_changed(struct v4l2_ctrl *master) | |||
1257 | return diff; | 1255 | return diff; |
1258 | } | 1256 | } |
1259 | 1257 | ||
1258 | /* Control range checking */ | ||
1259 | static int check_range(enum v4l2_ctrl_type type, | ||
1260 | s32 min, s32 max, u32 step, s32 def) | ||
1261 | { | ||
1262 | switch (type) { | ||
1263 | case V4L2_CTRL_TYPE_BOOLEAN: | ||
1264 | if (step != 1 || max > 1 || min < 0) | ||
1265 | return -ERANGE; | ||
1266 | /* fall through */ | ||
1267 | case V4L2_CTRL_TYPE_INTEGER: | ||
1268 | if (step <= 0 || min > max || def < min || def > max) | ||
1269 | return -ERANGE; | ||
1270 | return 0; | ||
1271 | case V4L2_CTRL_TYPE_BITMASK: | ||
1272 | if (step || min || !max || (def & ~max)) | ||
1273 | return -ERANGE; | ||
1274 | return 0; | ||
1275 | case V4L2_CTRL_TYPE_MENU: | ||
1276 | case V4L2_CTRL_TYPE_INTEGER_MENU: | ||
1277 | if (min > max || def < min || def > max) | ||
1278 | return -ERANGE; | ||
1279 | /* Note: step == menu_skip_mask for menu controls. | ||
1280 | So here we check if the default value is masked out. */ | ||
1281 | if (step && ((1 << def) & step)) | ||
1282 | return -EINVAL; | ||
1283 | return 0; | ||
1284 | case V4L2_CTRL_TYPE_STRING: | ||
1285 | if (min > max || min < 0 || step < 1 || def) | ||
1286 | return -ERANGE; | ||
1287 | return 0; | ||
1288 | default: | ||
1289 | return 0; | ||
1290 | } | ||
1291 | } | ||
1292 | |||
1260 | /* Validate a new control */ | 1293 | /* Validate a new control */ |
1261 | static int validate_new(const struct v4l2_ctrl *ctrl, | 1294 | static int validate_new(const struct v4l2_ctrl *ctrl, |
1262 | struct v4l2_ext_control *c) | 1295 | struct v4l2_ext_control *c) |
@@ -1529,30 +1562,21 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, | |||
1529 | { | 1562 | { |
1530 | struct v4l2_ctrl *ctrl; | 1563 | struct v4l2_ctrl *ctrl; |
1531 | unsigned sz_extra = 0; | 1564 | unsigned sz_extra = 0; |
1565 | int err; | ||
1532 | 1566 | ||
1533 | if (hdl->error) | 1567 | if (hdl->error) |
1534 | return NULL; | 1568 | return NULL; |
1535 | 1569 | ||
1536 | /* Sanity checks */ | 1570 | /* Sanity checks */ |
1537 | if (id == 0 || name == NULL || id >= V4L2_CID_PRIVATE_BASE || | 1571 | if (id == 0 || name == NULL || id >= V4L2_CID_PRIVATE_BASE || |
1538 | (type == V4L2_CTRL_TYPE_INTEGER && step == 0) || | ||
1539 | (type == V4L2_CTRL_TYPE_BITMASK && max == 0) || | ||
1540 | (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) || | 1572 | (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) || |
1541 | (type == V4L2_CTRL_TYPE_INTEGER_MENU && qmenu_int == NULL) || | 1573 | (type == V4L2_CTRL_TYPE_INTEGER_MENU && qmenu_int == NULL)) { |
1542 | (type == V4L2_CTRL_TYPE_STRING && max == 0)) { | ||
1543 | handler_set_err(hdl, -ERANGE); | ||
1544 | return NULL; | ||
1545 | } | ||
1546 | if (type != V4L2_CTRL_TYPE_BITMASK && max < min) { | ||
1547 | handler_set_err(hdl, -ERANGE); | 1574 | handler_set_err(hdl, -ERANGE); |
1548 | return NULL; | 1575 | return NULL; |
1549 | } | 1576 | } |
1550 | if ((type == V4L2_CTRL_TYPE_INTEGER || | 1577 | err = check_range(type, min, max, step, def); |
1551 | type == V4L2_CTRL_TYPE_MENU || | 1578 | if (err) { |
1552 | type == V4L2_CTRL_TYPE_INTEGER_MENU || | 1579 | handler_set_err(hdl, err); |
1553 | type == V4L2_CTRL_TYPE_BOOLEAN) && | ||
1554 | (def < min || def > max)) { | ||
1555 | handler_set_err(hdl, -ERANGE); | ||
1556 | return NULL; | 1580 | return NULL; |
1557 | } | 1581 | } |
1558 | if (type == V4L2_CTRL_TYPE_BITMASK && ((def & ~max) || min || step)) { | 1582 | if (type == V4L2_CTRL_TYPE_BITMASK && ((def & ~max) || min || step)) { |
@@ -2426,8 +2450,8 @@ EXPORT_SYMBOL(v4l2_ctrl_g_ctrl_int64); | |||
2426 | /* Core function that calls try/s_ctrl and ensures that the new value is | 2450 | /* Core function that calls try/s_ctrl and ensures that the new value is |
2427 | copied to the current value on a set. | 2451 | copied to the current value on a set. |
2428 | Must be called with ctrl->handler->lock held. */ | 2452 | Must be called with ctrl->handler->lock held. */ |
2429 | static int try_or_set_cluster(struct v4l2_fh *fh, | 2453 | static int try_or_set_cluster(struct v4l2_fh *fh, struct v4l2_ctrl *master, |
2430 | struct v4l2_ctrl *master, bool set) | 2454 | bool set, u32 ch_flags) |
2431 | { | 2455 | { |
2432 | bool update_flag; | 2456 | bool update_flag; |
2433 | int ret; | 2457 | int ret; |
@@ -2465,7 +2489,8 @@ static int try_or_set_cluster(struct v4l2_fh *fh, | |||
2465 | /* If OK, then make the new values permanent. */ | 2489 | /* If OK, then make the new values permanent. */ |
2466 | update_flag = is_cur_manual(master) != is_new_manual(master); | 2490 | update_flag = is_cur_manual(master) != is_new_manual(master); |
2467 | for (i = 0; i < master->ncontrols; i++) | 2491 | for (i = 0; i < master->ncontrols; i++) |
2468 | new_to_cur(fh, master->cluster[i], update_flag && i > 0); | 2492 | new_to_cur(fh, master->cluster[i], ch_flags | |
2493 | ((update_flag && i > 0) ? V4L2_EVENT_CTRL_CH_FLAGS : 0)); | ||
2469 | return 0; | 2494 | return 0; |
2470 | } | 2495 | } |
2471 | 2496 | ||
@@ -2592,7 +2617,7 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, | |||
2592 | } while (!ret && idx); | 2617 | } while (!ret && idx); |
2593 | 2618 | ||
2594 | if (!ret) | 2619 | if (!ret) |
2595 | ret = try_or_set_cluster(fh, master, set); | 2620 | ret = try_or_set_cluster(fh, master, set, 0); |
2596 | 2621 | ||
2597 | /* Copy the new values back to userspace. */ | 2622 | /* Copy the new values back to userspace. */ |
2598 | if (!ret) { | 2623 | if (!ret) { |
@@ -2638,10 +2663,9 @@ EXPORT_SYMBOL(v4l2_subdev_s_ext_ctrls); | |||
2638 | 2663 | ||
2639 | /* Helper function for VIDIOC_S_CTRL compatibility */ | 2664 | /* Helper function for VIDIOC_S_CTRL compatibility */ |
2640 | static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, | 2665 | static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, |
2641 | struct v4l2_ext_control *c) | 2666 | struct v4l2_ext_control *c, u32 ch_flags) |
2642 | { | 2667 | { |
2643 | struct v4l2_ctrl *master = ctrl->cluster[0]; | 2668 | struct v4l2_ctrl *master = ctrl->cluster[0]; |
2644 | int ret; | ||
2645 | int i; | 2669 | int i; |
2646 | 2670 | ||
2647 | /* String controls are not supported. The user_to_new() and | 2671 | /* String controls are not supported. The user_to_new() and |
@@ -2651,12 +2675,6 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, | |||
2651 | if (ctrl->type == V4L2_CTRL_TYPE_STRING) | 2675 | if (ctrl->type == V4L2_CTRL_TYPE_STRING) |
2652 | return -EINVAL; | 2676 | return -EINVAL; |
2653 | 2677 | ||
2654 | ret = validate_new(ctrl, c); | ||
2655 | if (ret) | ||
2656 | return ret; | ||
2657 | |||
2658 | v4l2_ctrl_lock(ctrl); | ||
2659 | |||
2660 | /* Reset the 'is_new' flags of the cluster */ | 2678 | /* Reset the 'is_new' flags of the cluster */ |
2661 | for (i = 0; i < master->ncontrols; i++) | 2679 | for (i = 0; i < master->ncontrols; i++) |
2662 | if (master->cluster[i]) | 2680 | if (master->cluster[i]) |
@@ -2670,10 +2688,22 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, | |||
2670 | update_from_auto_cluster(master); | 2688 | update_from_auto_cluster(master); |
2671 | 2689 | ||
2672 | user_to_new(c, ctrl); | 2690 | user_to_new(c, ctrl); |
2673 | ret = try_or_set_cluster(fh, master, true); | 2691 | return try_or_set_cluster(fh, master, true, ch_flags); |
2674 | cur_to_user(c, ctrl); | 2692 | } |
2675 | 2693 | ||
2676 | v4l2_ctrl_unlock(ctrl); | 2694 | /* Helper function for VIDIOC_S_CTRL compatibility */ |
2695 | static int set_ctrl_lock(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, | ||
2696 | struct v4l2_ext_control *c) | ||
2697 | { | ||
2698 | int ret = validate_new(ctrl, c); | ||
2699 | |||
2700 | if (!ret) { | ||
2701 | v4l2_ctrl_lock(ctrl); | ||
2702 | ret = set_ctrl(fh, ctrl, c, 0); | ||
2703 | if (!ret) | ||
2704 | cur_to_user(c, ctrl); | ||
2705 | v4l2_ctrl_unlock(ctrl); | ||
2706 | } | ||
2677 | return ret; | 2707 | return ret; |
2678 | } | 2708 | } |
2679 | 2709 | ||
@@ -2691,7 +2721,7 @@ int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, | |||
2691 | return -EACCES; | 2721 | return -EACCES; |
2692 | 2722 | ||
2693 | c.value = control->value; | 2723 | c.value = control->value; |
2694 | ret = set_ctrl(fh, ctrl, &c); | 2724 | ret = set_ctrl_lock(fh, ctrl, &c); |
2695 | control->value = c.value; | 2725 | control->value = c.value; |
2696 | return ret; | 2726 | return ret; |
2697 | } | 2727 | } |
@@ -2710,7 +2740,7 @@ int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val) | |||
2710 | /* It's a driver bug if this happens. */ | 2740 | /* It's a driver bug if this happens. */ |
2711 | WARN_ON(!type_is_int(ctrl)); | 2741 | WARN_ON(!type_is_int(ctrl)); |
2712 | c.value = val; | 2742 | c.value = val; |
2713 | return set_ctrl(NULL, ctrl, &c); | 2743 | return set_ctrl_lock(NULL, ctrl, &c); |
2714 | } | 2744 | } |
2715 | EXPORT_SYMBOL(v4l2_ctrl_s_ctrl); | 2745 | EXPORT_SYMBOL(v4l2_ctrl_s_ctrl); |
2716 | 2746 | ||
@@ -2721,7 +2751,7 @@ int v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val) | |||
2721 | /* It's a driver bug if this happens. */ | 2751 | /* It's a driver bug if this happens. */ |
2722 | WARN_ON(ctrl->type != V4L2_CTRL_TYPE_INTEGER64); | 2752 | WARN_ON(ctrl->type != V4L2_CTRL_TYPE_INTEGER64); |
2723 | c.value64 = val; | 2753 | c.value64 = val; |
2724 | return set_ctrl(NULL, ctrl, &c); | 2754 | return set_ctrl_lock(NULL, ctrl, &c); |
2725 | } | 2755 | } |
2726 | EXPORT_SYMBOL(v4l2_ctrl_s_ctrl_int64); | 2756 | EXPORT_SYMBOL(v4l2_ctrl_s_ctrl_int64); |
2727 | 2757 | ||
@@ -2741,6 +2771,41 @@ void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void | |||
2741 | } | 2771 | } |
2742 | EXPORT_SYMBOL(v4l2_ctrl_notify); | 2772 | EXPORT_SYMBOL(v4l2_ctrl_notify); |
2743 | 2773 | ||
2774 | int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl, | ||
2775 | s32 min, s32 max, u32 step, s32 def) | ||
2776 | { | ||
2777 | int ret = check_range(ctrl->type, min, max, step, def); | ||
2778 | struct v4l2_ext_control c; | ||
2779 | |||
2780 | switch (ctrl->type) { | ||
2781 | case V4L2_CTRL_TYPE_INTEGER: | ||
2782 | case V4L2_CTRL_TYPE_BOOLEAN: | ||
2783 | case V4L2_CTRL_TYPE_MENU: | ||
2784 | case V4L2_CTRL_TYPE_INTEGER_MENU: | ||
2785 | case V4L2_CTRL_TYPE_BITMASK: | ||
2786 | if (ret) | ||
2787 | return ret; | ||
2788 | break; | ||
2789 | default: | ||
2790 | return -EINVAL; | ||
2791 | } | ||
2792 | v4l2_ctrl_lock(ctrl); | ||
2793 | ctrl->minimum = min; | ||
2794 | ctrl->maximum = max; | ||
2795 | ctrl->step = step; | ||
2796 | ctrl->default_value = def; | ||
2797 | c.value = ctrl->cur.val; | ||
2798 | if (validate_new(ctrl, &c)) | ||
2799 | c.value = def; | ||
2800 | if (c.value != ctrl->cur.val) | ||
2801 | ret = set_ctrl(NULL, ctrl, &c, V4L2_EVENT_CTRL_CH_RANGE); | ||
2802 | else | ||
2803 | send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE); | ||
2804 | v4l2_ctrl_unlock(ctrl); | ||
2805 | return ret; | ||
2806 | } | ||
2807 | EXPORT_SYMBOL(v4l2_ctrl_modify_range); | ||
2808 | |||
2744 | static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems) | 2809 | static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems) |
2745 | { | 2810 | { |
2746 | struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id); | 2811 | struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id); |
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index c4cc04136074..91125b6f05a5 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h | |||
@@ -518,6 +518,26 @@ void v4l2_ctrl_activate(struct v4l2_ctrl *ctrl, bool active); | |||
518 | */ | 518 | */ |
519 | void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed); | 519 | void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed); |
520 | 520 | ||
521 | /** v4l2_ctrl_modify_range() - Update the range of a control. | ||
522 | * @ctrl: The control to update. | ||
523 | * @min: The control's minimum value. | ||
524 | * @max: The control's maximum value. | ||
525 | * @step: The control's step value | ||
526 | * @def: The control's default value. | ||
527 | * | ||
528 | * Update the range of a control on the fly. This works for control types | ||
529 | * INTEGER, BOOLEAN, MENU, INTEGER MENU and BITMASK. For menu controls the | ||
530 | * @step value is interpreted as a menu_skip_mask. | ||
531 | * | ||
532 | * An error is returned if one of the range arguments is invalid for this | ||
533 | * control type. | ||
534 | * | ||
535 | * This function assumes that the control handler is not locked and will | ||
536 | * take the lock itself. | ||
537 | */ | ||
538 | int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl, | ||
539 | s32 min, s32 max, u32 step, s32 def); | ||
540 | |||
521 | /** v4l2_ctrl_lock() - Helper function to lock the handler | 541 | /** v4l2_ctrl_lock() - Helper function to lock the handler |
522 | * associated with the control. | 542 | * associated with the control. |
523 | * @ctrl: The control to lock. | 543 | * @ctrl: The control to lock. |
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 94cbe26e9f00..928799c2e2d9 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h | |||
@@ -1822,6 +1822,7 @@ struct v4l2_event_vsync { | |||
1822 | /* Payload for V4L2_EVENT_CTRL */ | 1822 | /* Payload for V4L2_EVENT_CTRL */ |
1823 | #define V4L2_EVENT_CTRL_CH_VALUE (1 << 0) | 1823 | #define V4L2_EVENT_CTRL_CH_VALUE (1 << 0) |
1824 | #define V4L2_EVENT_CTRL_CH_FLAGS (1 << 1) | 1824 | #define V4L2_EVENT_CTRL_CH_FLAGS (1 << 1) |
1825 | #define V4L2_EVENT_CTRL_CH_RANGE (1 << 2) | ||
1825 | 1826 | ||
1826 | struct v4l2_event_ctrl { | 1827 | struct v4l2_event_ctrl { |
1827 | __u32 changes; | 1828 | __u32 changes; |