diff mbox series

[3/4] iio: add helper function for reading channel offset in buffer

Message ID 20220817105643.95710-4-contact@artur-rojek.eu (mailing list archive)
State Handled Elsewhere
Headers show
Series iio/adc-joystick: buffer data parsing fixes | expand

Commit Message

Artur Rojek Aug. 17, 2022, 10:56 a.m. UTC
This is useful for consumers that wish to parse raw buffer data.

Tested-by: Paul Cercueil <paul@crapouillou.net>
Signed-off-by: Artur Rojek <contact@artur-rojek.eu>
---
 drivers/iio/industrialio-buffer.c | 28 ++++++++++++++++++++++++++++
 include/linux/iio/buffer.h        |  4 ++++
 2 files changed, 32 insertions(+)

Comments

Andy Shevchenko Aug. 19, 2022, 8:17 a.m. UTC | #1
On Wed, Aug 17, 2022 at 1:58 PM Artur Rojek <contact@artur-rojek.eu> wrote:
>
> This is useful for consumers that wish to parse raw buffer data.

...

> +int iio_find_channel_offset_in_buffer(struct iio_dev *indio_dev,
> +                                     const struct iio_chan_spec *chan,
> +                                     struct iio_buffer *buffer)
> +{
> +       int length, offset = 0;
> +       unsigned int si;
> +
> +       if (chan->scan_index < 0 ||
> +           !test_bit(chan->scan_index, buffer->scan_mask)) {
> +               return -EINVAL;
> +       }

Have you run checkpatch? The {} are redundant. But personally I would
split this into two separate conditionals.

> +       for (si = 0; si < chan->scan_index; ++si) {

Just a side crying: where did you, people, get this pre-increment pattern from?!

> +               if (!test_bit(si, buffer->scan_mask))
> +                       continue;

NIH for_each_set_bit()

> +               length = iio_storage_bytes_for_si(indio_dev, si);
> +
> +               /* Account for channel alignment. */
> +               if (offset % length)
> +                       offset += length - (offset % length);
> +               offset += length;
> +       }
> +
> +       return offset;
> +}
> +EXPORT_SYMBOL_GPL(iio_find_channel_offset_in_buffer);

Same Q as per previous patch: IIO namespace?
Artur Rojek Aug. 19, 2022, 10:33 a.m. UTC | #2
On 2022-08-19 10:17, Andy Shevchenko wrote:
> On Wed, Aug 17, 2022 at 1:58 PM Artur Rojek <contact@artur-rojek.eu> 
> wrote:
>> 
>> This is useful for consumers that wish to parse raw buffer data.
> 
> ...
> 
>> +int iio_find_channel_offset_in_buffer(struct iio_dev *indio_dev,
>> +                                     const struct iio_chan_spec 
>> *chan,
>> +                                     struct iio_buffer *buffer)
>> +{
>> +       int length, offset = 0;
>> +       unsigned int si;
>> +
>> +       if (chan->scan_index < 0 ||
>> +           !test_bit(chan->scan_index, buffer->scan_mask)) {
>> +               return -EINVAL;
>> +       }
> 
> Have you run checkpatch? The {} are redundant. But personally I would
> split this into two separate conditionals.
I did run checkpatch on it - all patches were ready for submission.
I don't find the {} redundant for multi-line statements, like this one,
and I personally prefer to check conditions that return the same error
type together.
> 
>> +       for (si = 0; si < chan->scan_index; ++si) {
> 
> Just a side crying: where did you, people, get this pre-increment 
> pattern from?!
> 
>> +               if (!test_bit(si, buffer->scan_mask))
>> +                       continue;
> 
> NIH for_each_set_bit()
> 
>> +               length = iio_storage_bytes_for_si(indio_dev, si);
>> +
>> +               /* Account for channel alignment. */
>> +               if (offset % length)
>> +                       offset += length - (offset % length);
>> +               offset += length;
>> +       }
>> +
>> +       return offset;
>> +}
>> +EXPORT_SYMBOL_GPL(iio_find_channel_offset_in_buffer);
> 
> Same Q as per previous patch: IIO namespace?
Andy Shevchenko Aug. 19, 2022, 10:36 a.m. UTC | #3
On Fri, Aug 19, 2022 at 1:33 PM Artur Rojek <contact@artur-rojek.eu> wrote:
> On 2022-08-19 10:17, Andy Shevchenko wrote:
> > On Wed, Aug 17, 2022 at 1:58 PM Artur Rojek <contact@artur-rojek.eu>
> > wrote:

...

> >> +       if (chan->scan_index < 0 ||
> >> +           !test_bit(chan->scan_index, buffer->scan_mask)) {
> >> +               return -EINVAL;
> >> +       }
> >
> > Have you run checkpatch? The {} are redundant. But personally I would
> > split this into two separate conditionals.
> I did run checkpatch on it - all patches were ready for submission.
> I don't find the {} redundant for multi-line statements, like this one,

This is a one-line conditional. So, *unlike* this one.

> and I personally prefer to check conditions that return the same error
> type together.

I see that the maintainer's input is needed here, because even if the
error code is the same, the semantics are different and I consider
that to prevail on the combining.
Jonathan Cameron Aug. 19, 2022, 5:49 p.m. UTC | #4
On Wed, 17 Aug 2022 12:56:42 +0200
Artur Rojek <contact@artur-rojek.eu> wrote:

> This is useful for consumers that wish to parse raw buffer data.
> 
> Tested-by: Paul Cercueil <paul@crapouillou.net>
> Signed-off-by: Artur Rojek <contact@artur-rojek.eu>
> ---
>  drivers/iio/industrialio-buffer.c | 28 ++++++++++++++++++++++++++++
>  include/linux/iio/buffer.h        |  4 ++++
>  2 files changed, 32 insertions(+)
> 
> diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
> index 228598b82a2f..cf23736610d9 100644
> --- a/drivers/iio/industrialio-buffer.c
> +++ b/drivers/iio/industrialio-buffer.c
> @@ -691,6 +691,34 @@ static unsigned int iio_storage_bytes_for_si(struct iio_dev *indio_dev,
>  	return bytes;
>  }
>  
> +int iio_find_channel_offset_in_buffer(struct iio_dev *indio_dev,
> +				      const struct iio_chan_spec *chan,
> +				      struct iio_buffer *buffer)
> +{
> +	int length, offset = 0;
> +	unsigned int si;
> +
> +	if (chan->scan_index < 0 ||
> +	    !test_bit(chan->scan_index, buffer->scan_mask)) {
> +		return -EINVAL;
> +	}
> +
> +	for (si = 0; si < chan->scan_index; ++si) {
> +		if (!test_bit(si, buffer->scan_mask))

You are walking channels that the consumer should not even know about
here.

I think you can establish the same easily enough from the channels it
does know about.  It would be fiddly if you had lots of channels (as
you might be best off sorting them) but for small numbers of channels
loop over the array to find lowest scan_index - compute offset due
to that then move on to next one etc until you reach the scan index
of the channel you want.


> +			continue;
> +
> +		length = iio_storage_bytes_for_si(indio_dev, si);
> +
> +		/* Account for channel alignment. */
> +		if (offset % length)
> +			offset += length - (offset % length);
> +		offset += length;
> +	}
> +
> +	return offset;
> +}
> +EXPORT_SYMBOL_GPL(iio_find_channel_offset_in_buffer);
> +
>  static unsigned int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev)
>  {
>  	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
> diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h
> index 418b1307d3f2..b1db74772e77 100644
> --- a/include/linux/iio/buffer.h
> +++ b/include/linux/iio/buffer.h
> @@ -16,6 +16,10 @@ enum iio_buffer_direction {
>  	IIO_BUFFER_DIRECTION_OUT,
>  };
>  
> +int iio_find_channel_offset_in_buffer(struct iio_dev *indio_dev,
> +				      const struct iio_chan_spec *chan,
> +				      struct iio_buffer *buffer);
> +
>  int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data);
>  
>  int iio_pop_from_buffer(struct iio_buffer *buffer, void *data);
diff mbox series

Patch

diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 228598b82a2f..cf23736610d9 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -691,6 +691,34 @@  static unsigned int iio_storage_bytes_for_si(struct iio_dev *indio_dev,
 	return bytes;
 }
 
+int iio_find_channel_offset_in_buffer(struct iio_dev *indio_dev,
+				      const struct iio_chan_spec *chan,
+				      struct iio_buffer *buffer)
+{
+	int length, offset = 0;
+	unsigned int si;
+
+	if (chan->scan_index < 0 ||
+	    !test_bit(chan->scan_index, buffer->scan_mask)) {
+		return -EINVAL;
+	}
+
+	for (si = 0; si < chan->scan_index; ++si) {
+		if (!test_bit(si, buffer->scan_mask))
+			continue;
+
+		length = iio_storage_bytes_for_si(indio_dev, si);
+
+		/* Account for channel alignment. */
+		if (offset % length)
+			offset += length - (offset % length);
+		offset += length;
+	}
+
+	return offset;
+}
+EXPORT_SYMBOL_GPL(iio_find_channel_offset_in_buffer);
+
 static unsigned int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev)
 {
 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h
index 418b1307d3f2..b1db74772e77 100644
--- a/include/linux/iio/buffer.h
+++ b/include/linux/iio/buffer.h
@@ -16,6 +16,10 @@  enum iio_buffer_direction {
 	IIO_BUFFER_DIRECTION_OUT,
 };
 
+int iio_find_channel_offset_in_buffer(struct iio_dev *indio_dev,
+				      const struct iio_chan_spec *chan,
+				      struct iio_buffer *buffer);
+
 int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data);
 
 int iio_pop_from_buffer(struct iio_buffer *buffer, void *data);