iio: industrialio-core: Add IIO_OUT type
[deliverable/linux.git] / drivers / staging / iio / industrialio-core.c
index 94d3bfaa061d8e3b0ee3002f0d85ce10bfbcda95..8fa2be6f566fec5fbab1e445c07e75304a56fe6c 100644 (file)
@@ -47,6 +47,7 @@ static const char * const iio_chan_type_name_spec_shared[] = {
        [IIO_TIMESTAMP] = "timestamp",
        [IIO_ACCEL] = "accel",
        [IIO_IN] = "in",
+       [IIO_OUT] = "out",
        [IIO_CURRENT] = "current",
        [IIO_POWER] = "power",
        [IIO_IN_DIFF] = "in-in",
@@ -396,6 +397,11 @@ static ssize_t iio_read_channel_info(struct device *dev,
                        return sprintf(buf, "-%d.%06u\n", val, -val2);
                else
                        return sprintf(buf, "%d.%06u\n", val, val2);
+       } else if (ret == IIO_VAL_INT_PLUS_NANO) {
+               if (val2 < 0)
+                       return sprintf(buf, "-%d.%09u\n", val, -val2);
+               else
+                       return sprintf(buf, "%d.%09u\n", val, val2);
        } else
                return 0;
 }
@@ -407,25 +413,40 @@ static ssize_t iio_write_channel_info(struct device *dev,
 {
        struct iio_dev *indio_dev = dev_get_drvdata(dev);
        struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-       int ret, integer = 0, micro = 0, micro_mult = 100000;
+       int ret, integer = 0, fract = 0, fract_mult = 100000;
        bool integer_part = true, negative = false;
 
        /* Assumes decimal - precision based on number of digits */
        if (!indio_dev->info->write_raw)
                return -EINVAL;
+
+       if (indio_dev->info->write_raw_get_fmt)
+               switch (indio_dev->info->write_raw_get_fmt(indio_dev,
+                       this_attr->c, this_attr->address)) {
+               case IIO_VAL_INT_PLUS_MICRO:
+                       fract_mult = 100000;
+                       break;
+               case IIO_VAL_INT_PLUS_NANO:
+                       fract_mult = 100000000;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+
        if (buf[0] == '-') {
                negative = true;
                buf++;
        }
+
        while (*buf) {
                if ('0' <= *buf && *buf <= '9') {
                        if (integer_part)
                                integer = integer*10 + *buf - '0';
                        else {
-                               micro += micro_mult*(*buf - '0');
-                               if (micro_mult == 1)
+                               fract += fract_mult*(*buf - '0');
+                               if (fract_mult == 1)
                                        break;
-                               micro_mult /= 10;
+                               fract_mult /= 10;
                        }
                } else if (*buf == '\n') {
                        if (*(buf + 1) == '\0')
@@ -443,11 +464,11 @@ static ssize_t iio_write_channel_info(struct device *dev,
                if (integer)
                        integer = -integer;
                else
-                       micro = -micro;
+                       fract = -fract;
        }
 
        ret = indio_dev->info->write_raw(indio_dev, this_attr->c,
-                                        integer, micro, this_attr->address);
+                                        integer, fract, this_attr->address);
        if (ret)
                return ret;
 
@@ -655,7 +676,8 @@ static int iio_device_add_channel_sysfs(struct iio_dev *dev_info,
        else
                ret = __iio_add_chan_devattr("raw", NULL, chan,
                                             &iio_read_channel_info,
-                                            NULL,
+                                            (chan->type == IIO_OUT ?
+                                            &iio_write_channel_info : NULL),
                                             0,
                                             0,
                                             &dev_info->dev,
This page took 0.028082 seconds and 5 git commands to generate.