aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2014-07-26 12:02:59 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-07-27 16:51:37 -0400
commit9c9cb1fad865b3d9e9c4d7bbfbd20ca04cdc79b3 (patch)
treea5c73516fb21deb7d7fc60dd7d841d2900d106bc /drivers/media
parent5b8c8d41919ac4985dfacd31a860e4f00f52d3a6 (diff)
[media] v4l2-ctrls: fix rounding calculation
Commit 958c7c7e65 ("[media] v4l2-ctrls: fix corner case in round-to-range code") broke controls that use a negative range. The cause was a s32/u32 mixup: ctrl->step is unsigned while all others are signed. So the result type of the expression '(ctrl)->maximum - ((ctrl)->step / 2)' became unsigned, making 'val >= (ctrl)->maximum - ((ctrl)->step / 2)' true, since '((u32)-128) > 128' (if val = -128, maximum = 128 and step = 1). So carefully cast (step / 2) to s32. There was one cast of step to s32 where it should have been u32 because both offset and step are unsigned, so casting to signed makes no sense there. You do need a cast to u32 there, because otherwise architectures that have no 64-bit division start complaining (step is a u64). Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Reported-by: Frank Schäfer <fschaefer.oss@googlemail.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/v4l2-core/v4l2-ctrls.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 2d8ced8ad80b..f030d6a9e044 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1347,14 +1347,14 @@ static void std_log(const struct v4l2_ctrl *ctrl)
1347({ \ 1347({ \
1348 offset_type offset; \ 1348 offset_type offset; \
1349 if ((ctrl)->maximum >= 0 && \ 1349 if ((ctrl)->maximum >= 0 && \
1350 val >= (ctrl)->maximum - ((ctrl)->step / 2)) \ 1350 val >= (ctrl)->maximum - (s32)((ctrl)->step / 2)) \
1351 val = (ctrl)->maximum; \ 1351 val = (ctrl)->maximum; \
1352 else \ 1352 else \
1353 val += (ctrl)->step / 2; \ 1353 val += (s32)((ctrl)->step / 2); \
1354 val = clamp_t(typeof(val), val, \ 1354 val = clamp_t(typeof(val), val, \
1355 (ctrl)->minimum, (ctrl)->maximum); \ 1355 (ctrl)->minimum, (ctrl)->maximum); \
1356 offset = (val) - (ctrl)->minimum; \ 1356 offset = (val) - (ctrl)->minimum; \
1357 offset = (ctrl)->step * (offset / (s32)(ctrl)->step); \ 1357 offset = (ctrl)->step * (offset / (u32)(ctrl)->step); \
1358 val = (ctrl)->minimum + offset; \ 1358 val = (ctrl)->minimum + offset; \
1359 0; \ 1359 0; \
1360}) 1360})
@@ -1376,10 +1376,10 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
1376 * the u64 divide that needs special care. 1376 * the u64 divide that needs special care.
1377 */ 1377 */
1378 val = ptr.p_s64[idx]; 1378 val = ptr.p_s64[idx];
1379 if (ctrl->maximum >= 0 && val >= ctrl->maximum - ctrl->step / 2) 1379 if (ctrl->maximum >= 0 && val >= ctrl->maximum - (s64)(ctrl->step / 2))
1380 val = ctrl->maximum; 1380 val = ctrl->maximum;
1381 else 1381 else
1382 val += ctrl->step / 2; 1382 val += (s64)(ctrl->step / 2);
1383 val = clamp_t(s64, val, ctrl->minimum, ctrl->maximum); 1383 val = clamp_t(s64, val, ctrl->minimum, ctrl->maximum);
1384 offset = val - ctrl->minimum; 1384 offset = val - ctrl->minimum;
1385 do_div(offset, ctrl->step); 1385 do_div(offset, ctrl->step);