| @@ -1158,8 +1158,7 @@ static int new_to_user(struct v4l2_ext_control *c, · 1157 unmodified lines |
| 1158 | 1158 | } |
| 1159 | 1159 | |
| 1160 | 1160 | /* Copy the new value to the current value. */ |
| 1161 | | −static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, |
| 1162 | | − bool update_inactive) |
| 1161 | +static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags) |
| 1163 | 1162 | { |
| 1164 | 1163 | bool changed = false; |
| 1165 | 1164 | |
| @@ -1183,8 +1182,8 @@ static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, · 17 unmodified lines |
| 1183 | 1182 | ctrl->cur.val = ctrl->val; |
| 1184 | 1183 | break; |
| 1185 | 1184 | } |
| 1186 | | − if (update_inactive) { |
| 1187 | | − /* Note: update_inactive can only be true for auto clusters. */ |
| 1185 | + if (ch_flags & V4L2_EVENT_CTRL_CH_FLAGS) { |
| 1186 | + /* Note: CH_FLAGS is only set for auto clusters. */ |
| 1188 | 1187 | ctrl->flags &= |
| 1189 | 1188 | ~(V4L2_CTRL_FLAG_INACTIVE | V4L2_CTRL_FLAG_VOLATILE); |
| 1190 | 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, · 3 unmodified lines |
| 1194 | 1193 | } |
| 1195 | 1194 | fh = NULL; |
| 1196 | 1195 | } |
| 1197 | | − if (changed || update_inactive) { |
| 1196 | + if (changed || ch_flags) { |
| 1198 | 1197 | /* If a control was changed that was not one of the controls |
| 1199 | 1198 | modified by the application, then send the event to all. */ |
| 1200 | 1199 | if (!ctrl->is_new) |
| 1201 | 1200 | fh = NULL; |
| 1202 | 1201 | send_event(fh, ctrl, |
| 1203 | | − (changed ? V4L2_EVENT_CTRL_CH_VALUE : 0) | |
| 1204 | | − (update_inactive ? V4L2_EVENT_CTRL_CH_FLAGS : 0)); |
| 1202 | + (changed ? V4L2_EVENT_CTRL_CH_VALUE : 0) | ch_flags); |
| 1205 | 1203 | if (ctrl->call_notify && changed && ctrl->handler->notify) |
| 1206 | 1204 | ctrl->handler->notify(ctrl, ctrl->handler->notify_priv); |
| 1207 | 1205 | } |
| @@ -1257,6 +1255,41 @@ static int cluster_changed(struct v4l2_ctrl *master) · 49 unmodified lines |
| 1257 | 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 | 1293 | /* Validate a new control */ |
| 1261 | 1294 | static int validate_new(const struct v4l2_ctrl *ctrl, |
| 1262 | 1295 | struct v4l2_ext_control *c) |
| @@ -1529,30 +1562,21 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, · 266 unmodified lines |
| 1529 | 1562 | { |
| 1530 | 1563 | struct v4l2_ctrl *ctrl; |
| 1531 | 1564 | unsigned sz_extra = 0; |
| 1565 | + int err; |
| 1532 | 1566 | |
| 1533 | 1567 | if (hdl->error) |
| 1534 | 1568 | return NULL; |
| 1535 | 1569 | |
| 1536 | 1570 | /* Sanity checks */ |
| 1537 | 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 | 1572 | (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) || |
| 1541 | | − (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) { |
| 1573 | + (type == V4L2_CTRL_TYPE_INTEGER_MENU && qmenu_int == NULL)) { |
| 1547 | 1574 | handler_set_err(hdl, -ERANGE); |
| 1548 | 1575 | return NULL; |
| 1549 | 1576 | } |
| 1550 | | − if ((type == V4L2_CTRL_TYPE_INTEGER || |
| 1551 | | − type == V4L2_CTRL_TYPE_MENU || |
| 1552 | | − type == V4L2_CTRL_TYPE_INTEGER_MENU || |
| 1553 | | − type == V4L2_CTRL_TYPE_BOOLEAN) && |
| 1554 | | − (def < min || def > max)) { |
| 1555 | | − handler_set_err(hdl, -ERANGE); |
| 1577 | + err = check_range(type, min, max, step, def); |
| 1578 | + if (err) { |
| 1579 | + handler_set_err(hdl, err); |
| 1556 | 1580 | return NULL; |
| 1557 | 1581 | } |
| 1558 | 1582 | if (type == V4L2_CTRL_TYPE_BITMASK && ((def & ~max) || min || step)) { |
| @@ -2426,8 +2450,8 @@ EXPORT_SYMBOL(v4l2_ctrl_g_ctrl_int64); · 867 unmodified lines |
| 2426 | 2450 | /* Core function that calls try/s_ctrl and ensures that the new value is |
| 2427 | 2451 | copied to the current value on a set. |
| 2428 | 2452 | Must be called with ctrl->handler->lock held. */ |
| 2429 | | −static int try_or_set_cluster(struct v4l2_fh *fh, |
| 2430 | | − struct v4l2_ctrl *master, bool set) |
| 2453 | +static int try_or_set_cluster(struct v4l2_fh *fh, struct v4l2_ctrl *master, |
| 2454 | + bool set, u32 ch_flags) |
| 2431 | 2455 | { |
| 2432 | 2456 | bool update_flag; |
| 2433 | 2457 | int ret; |
| @@ -2465,7 +2489,8 @@ static int try_or_set_cluster(struct v4l2_fh *fh, · 31 unmodified lines |
| 2465 | 2489 | /* If OK, then make the new values permanent. */ |
| 2466 | 2490 | update_flag = is_cur_manual(master) != is_new_manual(master); |
| 2467 | 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 | 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, · 120 unmodified lines |
| 2592 | 2617 | } while (!ret && idx); |
| 2593 | 2618 | |
| 2594 | 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 | 2622 | /* Copy the new values back to userspace. */ |
| 2598 | 2623 | if (!ret) { |
| @@ -2638,10 +2663,9 @@ EXPORT_SYMBOL(v4l2_subdev_s_ext_ctrls); · 39 unmodified lines |
| 2638 | 2663 | |
| 2639 | 2664 | /* Helper function for VIDIOC_S_CTRL compatibility */ |
| 2640 | 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 | 2668 | struct v4l2_ctrl *master = ctrl->cluster[0]; |
| 2644 | | − int ret; |
| 2645 | 2669 | int i; |
| 2646 | 2670 | |
| 2647 | 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, · 3 unmodified lines |
| 2651 | 2675 | if (ctrl->type == V4L2_CTRL_TYPE_STRING) |
| 2652 | 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 | 2678 | /* Reset the 'is_new' flags of the cluster */ |
| 2661 | 2679 | for (i = 0; i < master->ncontrols; i++) |
| 2662 | 2680 | if (master->cluster[i]) |
| @@ -2670,10 +2688,22 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, · 7 unmodified lines |
| 2670 | 2688 | update_from_auto_cluster(master); |
| 2671 | 2689 | |
| 2672 | 2690 | user_to_new(c, ctrl); |
| 2673 | | − ret = try_or_set_cluster(fh, master, true); |
| 2674 | | − cur_to_user(c, ctrl); |
| 2691 | + return try_or_set_cluster(fh, master, true, ch_flags); |
| 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 | 2707 | return ret; |
| 2678 | 2708 | } |
| 2679 | 2709 | |
| @@ -2691,7 +2721,7 @@ int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, · 11 unmodified lines |
| 2691 | 2721 | return -EACCES; |
| 2692 | 2722 | |
| 2693 | 2723 | c.value = control->value; |
| 2694 | | − ret = set_ctrl(fh, ctrl, &c); |
| 2724 | + ret = set_ctrl_lock(fh, ctrl, &c); |
| 2695 | 2725 | control->value = c.value; |
| 2696 | 2726 | return ret; |
| 2697 | 2727 | } |
| @@ -2710,7 +2740,7 @@ int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val) · 12 unmodified lines |
| 2710 | 2740 | /* It's a driver bug if this happens. */ |
| 2711 | 2741 | WARN_ON(!type_is_int(ctrl)); |
| 2712 | 2742 | c.value = val; |
| 2713 | | − return set_ctrl(NULL, ctrl, &c); |
| 2743 | + return set_ctrl_lock(NULL, ctrl, &c); |
| 2714 | 2744 | } |
| 2715 | 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) · 4 unmodified lines |
| 2721 | 2751 | /* It's a driver bug if this happens. */ |
| 2722 | 2752 | WARN_ON(ctrl->type != V4L2_CTRL_TYPE_INTEGER64); |
| 2723 | 2753 | c.value64 = val; |
| 2724 | | − return set_ctrl(NULL, ctrl, &c); |
| 2754 | + return set_ctrl_lock(NULL, ctrl, &c); |
| 2725 | 2755 | } |
| 2726 | 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 · 13 unmodified lines |
| 2741 | 2771 | } |
| 2742 | 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 | 2809 | static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems) |
| 2745 | 2810 | { |
| 2746 | 2811 | struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id); |