summaryrefslogtreecommitdiff
path: root/drivers/media/v4l2-core/v4l2-ctrls.c
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2014-07-17 12:31:23 -0300
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-07-17 12:44:38 -0300
commit0d5e8c4313c83dc2d60519a219d517a13ba8a432 (patch)
tree5a9f6581e1cc493f7dc624e51e7b65598a419005 /drivers/media/v4l2-core/v4l2-ctrls.c
parent028e2b4fb69f03a294a69b27c99f05002b8ac021 (diff)
[media] Fix 64-bit division fall-out from 64-bit control ranges
Commit 0ba2aeb6dab80920edd9cf5b93b1ea4d6913b8f3 increased the internal control ranges to 64 bit, but that caused problems in drivers that use the minimum/maximum/step/default_value control values in a division or modulus operations since not all architectures support those natively. Luckily, in almost all cases it is possible to just cast to 32 bits (the control value is known to be 32 bits, so it is safe to cast). Only in v4l2-ctrls.c was it necessary to use do_div in one function. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-ctrls.c')
-rw-r--r--drivers/media/v4l2-core/v4l2-ctrls.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 5c3b8de82e35..8552c832074a 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1303,7 +1303,7 @@ static void std_log(const struct v4l2_ctrl *ctrl)
val = clamp_t(typeof(val), val, \
(ctrl)->minimum, (ctrl)->maximum); \
offset = (val) - (ctrl)->minimum; \
- offset = (ctrl)->step * (offset / (ctrl)->step); \
+ offset = (ctrl)->step * (offset / (s32)(ctrl)->step); \
val = (ctrl)->minimum + offset; \
0; \
})
@@ -1313,12 +1313,24 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
union v4l2_ctrl_ptr ptr)
{
size_t len;
+ u64 offset;
+ s64 val;
switch (ctrl->type) {
case V4L2_CTRL_TYPE_INTEGER:
return ROUND_TO_RANGE(ptr.p_s32[idx], u32, ctrl);
case V4L2_CTRL_TYPE_INTEGER64:
- return ROUND_TO_RANGE(ptr.p_s64[idx], u64, ctrl);
+ /*
+ * We can't use the ROUND_TO_RANGE define here due to
+ * the u64 divide that needs special care.
+ */
+ val = ptr.p_s64[idx];
+ val += ctrl->step / 2;
+ val = clamp_t(s64, val, ctrl->minimum, ctrl->maximum);
+ offset = val - ctrl->minimum;
+ do_div(offset, ctrl->step);
+ ptr.p_s64[idx] = ctrl->minimum + offset * ctrl->step;
+ return 0;
case V4L2_CTRL_TYPE_U8:
return ROUND_TO_RANGE(ptr.p_u8[idx], u8, ctrl);
case V4L2_CTRL_TYPE_U16:
@@ -1353,7 +1365,7 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
len = strlen(ptr.p_char + idx);
if (len < ctrl->minimum)
return -ERANGE;
- if ((len - ctrl->minimum) % ctrl->step)
+ if ((len - (u32)ctrl->minimum) % (u32)ctrl->step)
return -ERANGE;
return 0;