IIO: core: Introduce read_raw_multi
authorSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Mon, 28 Apr 2014 23:51:00 +0000 (00:51 +0100)
committerJonathan Cameron <jic23@kernel.org>
Tue, 29 Apr 2014 21:05:32 +0000 (22:05 +0100)
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.

Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
drivers/iio/iio_core.h
drivers/iio/industrialio-core.c
drivers/iio/industrialio-event.c
drivers/iio/inkern.c
include/linux/iio/iio.h
include/linux/iio/types.h

index f6db6af36ba6de20ceb2cf9dc159dff9f53a1987..5f0ea77fe7176ee21374e1d124d70b8f663929b3 100644 (file)
@@ -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 *vals);
 
 /* Event interface flags */
 #define IIO_BUSY_BIT_POS 1
index 184444db62acaca683c8ebce22b0870c1ff7ebac..59540859bfae6baeb23b8e04b91c854c4b8c0cf8 100644 (file)
@@ -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);
 }
 
 /**
index dddfb0f90d342e5b324bba657c5d194df6205a2d..258a973a1fb8da2d23457fe3afc139f0f9befcff 100644 (file)
@@ -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,
index adeba5a0ecf70ff79ed4e3ed653ee6e4bf27b0ca..d833d55052eadf965424bfc2f3b5044cc0ad8167 100644 (file)
@@ -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)
index 5f2d00e7e488a7135023ec8f3b2a6f1a46ddeb44..5629c92eeadfe93e1a7ea466feb9c34d2e4668cf 100644 (file)
@@ -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,
index 084d882fe01b9d9f6a5714f19b520efa2eff7991..a13c2241abce5f5711d233abab606d0fee43d0f9 100644 (file)
@@ -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