> This callback is introduced to overcome some limitations of existing > read_raw callback. The functionality of both existing read_raw and > read_raw_multi is similar, both are used to request values from the > device. The current read_raw callback allows only two return values. > The new read_raw_multi allows returning multiple values. Instead of > passing just address of val and val2, it passes length and pointer > to values. Depending on the type and length of passed buffer, iio > client drivers can return multiple values. > --- > drivers/iio/iio_core.h | 2 +- > drivers/iio/industrialio-core.c | 65 ++++++++++++++++++++++++++-------------- > drivers/iio/industrialio-event.c | 6 ++-- > drivers/iio/inkern.c | 16 ++++++++-- > include/linux/iio/iio.h | 17 +++++++++++ > include/linux/iio/types.h | 1 + > 6 files changed, 80 insertions(+), 27 deletions(-) > > diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h > index f6db6af..30327ad 100644 > --- a/drivers/iio/iio_core.h > +++ b/drivers/iio/iio_core.h > @@ -35,7 +35,7 @@ int __iio_add_chan_devattr(const char *postfix, > struct list_head *attr_list); > void iio_free_chan_devattr_list(struct list_head *attr_list); > > -ssize_t iio_format_value(char *buf, unsigned int type, int val, int val2); > +ssize_t iio_format_value(char *buf, unsigned int type, int size, int *val); last parameter of prototype should be *vals to match the naming of the implementation > /* Event interface flags */ > #define IIO_BUSY_BIT_POS 1 > diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c > index ede16aec..e22a984 100644 > --- a/drivers/iio/industrialio-core.c > +++ b/drivers/iio/industrialio-core.c > @@ -373,41 +373,53 @@ EXPORT_SYMBOL_GPL(iio_enum_write); > * @buf: The buffer to which the formated value gets written > * @type: One of the IIO_VAL_... constants. This decides how the val and val2 > * parameters are formatted. > - * @val: First part of the value, exact meaning depends on the type parameter. > - * @val2: Second part of the value, exact meaning depends on the type parameter. > + * @vals: pointer to the values, exact meaning depends on the type parameter. > */ > -ssize_t iio_format_value(char *buf, unsigned int type, int val, int val2) > +ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals) > { > unsigned long long tmp; > bool scale_db = false; > > switch (type) { > case IIO_VAL_INT: > - return sprintf(buf, "%d\n", val); > + return sprintf(buf, "%d\n", vals[0]); > case IIO_VAL_INT_PLUS_MICRO_DB: > scale_db = true; > case IIO_VAL_INT_PLUS_MICRO: > - if (val2 < 0) > - return sprintf(buf, "-%ld.%06u%s\n", abs(val), -val2, > + if (vals[1] < 0) > + return sprintf(buf, "-%ld.%06u%s\n", abs(vals[0]), > + -vals[1], > scale_db ? " dB" : ""); > else > - return sprintf(buf, "%d.%06u%s\n", val, val2, > + return sprintf(buf, "%d.%06u%s\n", vals[0], vals[1], > scale_db ? " dB" : ""); > case IIO_VAL_INT_PLUS_NANO: > - if (val2 < 0) > - return sprintf(buf, "-%ld.%09u\n", abs(val), -val2); > + if (vals[1] < 0) > + return sprintf(buf, "-%ld.%09u\n", abs(vals[0]), > + -vals[1]); > else > - return sprintf(buf, "%d.%09u\n", val, val2); > + return sprintf(buf, "%d.%09u\n", vals[0], vals[1]); > case IIO_VAL_FRACTIONAL: > - tmp = div_s64((s64)val * 1000000000LL, val2); > - val2 = do_div(tmp, 1000000000LL); > - val = tmp; > - return sprintf(buf, "%d.%09u\n", val, val2); > + tmp = div_s64((s64)vals[0] * 1000000000LL, vals[1]); > + vals[1] = do_div(tmp, 1000000000LL); > + vals[0] = tmp; > + return sprintf(buf, "%d.%09u\n", vals[0], vals[1]); > case IIO_VAL_FRACTIONAL_LOG2: > - tmp = (s64)val * 1000000000LL >> val2; > - val2 = do_div(tmp, 1000000000LL); > - val = tmp; > - return sprintf(buf, "%d.%09u\n", val, val2); > + tmp = (s64)vals[0] * 1000000000LL >> vals[1]; > + vals[1] = do_div(tmp, 1000000000LL); > + vals[0] = tmp; > + return sprintf(buf, "%d.%09u\n", vals[0], vals[1]); > + case IIO_VAL_INT_MULTIPLE: > + { > + int i; > + int len = 0; > + > + for (i = 0; i < size; ++i) > + len += snprintf(&buf[len], PAGE_SIZE - len, "%d ", > + vals[i]); > + len += snprintf(&buf[len], PAGE_SIZE - len, "\n"); > + return len; > + } > default: > return 0; > } > @@ -419,14 +431,23 @@ static ssize_t iio_read_channel_info(struct device *dev, > { > struct iio_dev *indio_dev = dev_to_iio_dev(dev); > struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); > - int val, val2; > - int ret = indio_dev->info->read_raw(indio_dev, this_attr->c, > - &val, &val2, this_attr->address); > + int vals[INDIO_MAX_RAW_ELEMENTS]; > + int ret; > + int val_len = 2; > + > + if (indio_dev->info->read_raw_multi) > + ret = indio_dev->info->read_raw_multi(indio_dev, this_attr->c, > + INDIO_MAX_RAW_ELEMENTS, > + vals, &val_len, > + this_attr->address); > + else > + ret = indio_dev->info->read_raw(indio_dev, this_attr->c, > + &vals[0], &vals[1], this_attr->address); > > if (ret < 0) > return ret; > > - return iio_format_value(buf, ret, val, val2); > + return iio_format_value(buf, ret, val_len, vals); > } > > /** > diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c > index ea6e06b..1b4f31b 100644 > --- a/drivers/iio/industrialio-event.c > +++ b/drivers/iio/industrialio-event.c > @@ -270,7 +270,7 @@ static ssize_t iio_ev_value_show(struct device *dev, > { > struct iio_dev *indio_dev = dev_to_iio_dev(dev); > struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); > - int val, val2; > + int val, val2, val_arr[2]; > int ret; > > ret = indio_dev->info->read_event_value(indio_dev, > @@ -279,7 +279,9 @@ static ssize_t iio_ev_value_show(struct device *dev, > &val, &val2); > if (ret < 0) > return ret; > - return iio_format_value(buf, ret, val, val2); > + val_arr[0] = val; > + val_arr[1] = val2; > + return iio_format_value(buf, ret, 2, val_arr); > } > > static ssize_t iio_ev_value_store(struct device *dev, > diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c > index 0cf5f8e..75e5386 100644 > --- a/drivers/iio/inkern.c > +++ b/drivers/iio/inkern.c > @@ -417,12 +417,24 @@ static int iio_channel_read(struct iio_channel *chan, int *val, int *val2, > enum iio_chan_info_enum info) > { > int unused; > + int vals[INDIO_MAX_RAW_ELEMENTS]; > + int ret; > + int val_len = 2; > > if (val2 == NULL) > val2 = &unused; > > - return chan->indio_dev->info->read_raw(chan->indio_dev, chan->channel, > - val, val2, info); > + if (chan->indio_dev->info->read_raw_multi) { > + ret = chan->indio_dev->info->read_raw_multi(chan->indio_dev, > + chan->channel, INDIO_MAX_RAW_ELEMENTS, > + vals, &val_len, info); > + *val = vals[0]; > + *val2 = vals[1]; > + } else > + ret = chan->indio_dev->info->read_raw(chan->indio_dev, > + chan->channel, val, val2, info); > + > + return ret; > } > > int iio_read_channel_raw(struct iio_channel *chan, int *val) > diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h > index 5f2d00e..5629c92 100644 > --- a/include/linux/iio/iio.h > +++ b/include/linux/iio/iio.h > @@ -288,6 +288,8 @@ static inline s64 iio_get_time_ns(void) > #define INDIO_ALL_BUFFER_MODES \ > (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE) > > +#define INDIO_MAX_RAW_ELEMENTS 4 > + > struct iio_trigger; /* forward declaration */ > struct iio_dev; > > @@ -302,6 +304,14 @@ struct iio_dev; > * the channel in question. Return value will specify the > * type of value returned by the device. val and val2 will > * contain the elements making up the returned value. > + * @read_raw_multi: function to return values from the device. > + * mask specifies which value. Note 0 means a reading of > + * the channel in question. Return value will specify the > + * type of value returned by the device. vals pointer > + * contain the elements making up the returned value. > + * max_len specifies maximum number of elements > + * vals pointer can contain. val_len is used to return > + * length of valid elements in vals. > * @write_raw: function to write a value to the device. > * Parameters are the same as for read_raw. > * @write_raw_get_fmt: callback function to query the expected > @@ -328,6 +338,13 @@ struct iio_info { > int *val2, > long mask); > > + int (*read_raw_multi)(struct iio_dev *indio_dev, > + struct iio_chan_spec const *chan, > + int max_len, > + int *vals, > + int *val_len, > + long mask); > + > int (*write_raw)(struct iio_dev *indio_dev, > struct iio_chan_spec const *chan, > int val, > diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h > index 084d882..a13c224 100644 > --- a/include/linux/iio/types.h > +++ b/include/linux/iio/types.h > @@ -79,6 +79,7 @@ enum iio_event_direction { > #define IIO_VAL_INT_PLUS_MICRO 2 > #define IIO_VAL_INT_PLUS_NANO 3 > #define IIO_VAL_INT_PLUS_MICRO_DB 4 > +#define IIO_VAL_INT_MULTIPLE 5 > #define IIO_VAL_FRACTIONAL 10 > #define IIO_VAL_FRACTIONAL_LOG2 11 > > -- Peter Meerwald +43-664-2444418 (mobile) -- To unsubscribe from this list: send the line "unsubscribe linux-iio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html