From: Liam Beguin <lvb@xxxxxxxxxx> iio_convert_raw_to_processed_unlocked() assumes the offset is an integer. Make that clear to the consumer by returning an error on unsupported offset types without breaking valid implicit truncations. Signed-off-by: Liam Beguin <lvb@xxxxxxxxxx> --- drivers/iio/inkern.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index b69027690ed5..0b5667f22b1d 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -578,13 +578,37 @@ EXPORT_SYMBOL_GPL(iio_read_channel_average_raw); static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan, int raw, int *processed, unsigned int scale) { - int scale_type, scale_val, scale_val2, offset; + int scale_type, scale_val, scale_val2; + int offset_type, offset_val, offset_val2; s64 raw64 = raw; - int ret; - ret = iio_channel_read(chan, &offset, NULL, IIO_CHAN_INFO_OFFSET); - if (ret >= 0) - raw64 += offset; + offset_type = iio_channel_read(chan, &offset_val, &offset_val2, + IIO_CHAN_INFO_OFFSET); + if (offset_type >= 0) { + switch (offset_type) { + case IIO_VAL_INT: + break; + case IIO_VAL_INT_PLUS_MICRO: + if (offset_val2 > 1000) + return -EINVAL; + break; + case IIO_VAL_INT_PLUS_NANO: + if (offset_val2 > 1000000) + return -EINVAL; + case IIO_VAL_FRACTIONAL: + if (offset_val2 != 1) + return -EINVAL; + break; + case IIO_VAL_FRACTIONAL_LOG2: + if (offset_val2) + return -EINVAL; + break; + default: + return -EINVAL; + } + + raw64 += offset_val; + } scale_type = iio_channel_read(chan, &scale_val, &scale_val2, IIO_CHAN_INFO_SCALE); -- 2.30.1.489.g328c10930387