summaryrefslogtreecommitdiffstats
path: root/drivers/staging/iio/industrialio-core.c
diff options
context:
space:
mode:
authorLars-Peter Clausen2012-02-21 18:38:12 +0100
committerGreg Kroah-Hartman2012-02-24 21:12:24 +0100
commit5f420b42079c115daf3b45bbd15bcb6b7b05ad21 (patch)
tree748a58b40d17bebbe57e2e90c5f1d5f871561199 /drivers/staging/iio/industrialio-core.c
parentstaging:iio: Convert remaining drivers to module_spi_driver (diff)
downloadkernel-qcow2-linux-5f420b42079c115daf3b45bbd15bcb6b7b05ad21.tar.gz
kernel-qcow2-linux-5f420b42079c115daf3b45bbd15bcb6b7b05ad21.tar.xz
kernel-qcow2-linux-5f420b42079c115daf3b45bbd15bcb6b7b05ad21.zip
staging:iio: Add extended IIO channel info
Sometimes devices have per channel properties which either do not map nicely to the current channel info scheme (e.g. string properties) or are very device specific, so it does not make sense to add generic support for them. Currently drivers define these attributes by hand for each channel. Depending on the number of channels this can amount to quite a few lines of boilerplate code. Especially if a driver supports multiple variations of a chip with different numbers of channels. In this case it becomes necessary to have a individual attribute list per chip variation and also a individual iio_info struct. This patch introduces a new scheme for handling such per channel attributes called extended channel info attributes. A extended channel info attribute consist of a name, a flag whether it is shared and read and write callbacks. The read and write callbacks are similar to the {read,write}_raw callbacks and take a IIO device and a channel as their first parameters, but instead of pre-parsed integer values they directly get passed the raw string value, which has been written to the sysfs file. It is possible to assign a list of extended channel info attributes to a channel. For each extended channel info attribute the IIO core will create a new sysfs attribute conforming to the IIO channel naming spec for the channels type, similar as for normal info attributes. Read and write access to this sysfs attribute will be redirected to the extended channel info attributes read and write callbacks. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Acked-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/iio/industrialio-core.c')
-rw-r--r--drivers/staging/iio/industrialio-core.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c
index 3a2d08026624..645bb45c89e8 100644
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/staging/iio/industrialio-core.c
@@ -144,6 +144,33 @@ static void __exit iio_exit(void)
bus_unregister(&iio_bus_type);
}
+static ssize_t iio_read_channel_ext_info(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ const struct iio_chan_spec_ext_info *ext_info;
+
+ ext_info = &this_attr->c->ext_info[this_attr->address];
+
+ return ext_info->read(indio_dev, this_attr->c, buf);
+}
+
+static ssize_t iio_write_channel_ext_info(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ const struct iio_chan_spec_ext_info *ext_info;
+
+ ext_info = &this_attr->c->ext_info[this_attr->address];
+
+ return ext_info->write(indio_dev, this_attr->c, buf, len);
+}
+
static ssize_t iio_read_channel_info(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -423,6 +450,7 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan)
{
int ret, i, attrcount = 0;
+ const struct iio_chan_spec_ext_info *ext_info;
if (chan->channel < 0)
return 0;
@@ -457,6 +485,31 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
goto error_ret;
attrcount++;
}
+
+ if (chan->ext_info) {
+ unsigned int i = 0;
+ for (ext_info = chan->ext_info; ext_info->name; ext_info++) {
+ ret = __iio_add_chan_devattr(ext_info->name,
+ chan,
+ ext_info->read ?
+ &iio_read_channel_ext_info : NULL,
+ ext_info->write ?
+ &iio_write_channel_ext_info : NULL,
+ i,
+ ext_info->shared,
+ &indio_dev->dev,
+ &indio_dev->channel_attr_list);
+ i++;
+ if (ret == -EBUSY && ext_info->shared)
+ continue;
+
+ if (ret)
+ goto error_ret;
+
+ attrcount++;
+ }
+ }
+
ret = attrcount;
error_ret:
return ret;