From: Rodrigo Alencar <[email protected]> Add parent-child relationship between iio channels by creating a parent pointer field in iio_chan_spec struct and exposing a sysfs attribute that returns the parent channel prefix.
Signed-off-by: Rodrigo Alencar <[email protected]> --- drivers/iio/industrialio-core.c | 40 ++++++++++++++++++++++++++++++++++++++++ include/linux/iio/iio.h | 5 +++++ 2 files changed, 45 insertions(+) diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 78a3c27d17a1..36a05fd77d47 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -848,6 +848,22 @@ static ssize_t iio_read_channel_label(struct device *dev, to_iio_dev_attr(attr)->c, buf); } +static ssize_t iio_read_channel_parent(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + const struct iio_chan_spec *chan = to_iio_dev_attr(attr)->c->parent; + ssize_t len; + + len = __iio_chan_prefix_emit(dev, chan, IIO_SEPARATE, buf, PAGE_SIZE); + if (len < 0) + return len; + + buf[len] = '\n'; + + return len + 1; +} + static ssize_t iio_read_channel_info(struct device *dev, struct device_attribute *attr, char *buf) @@ -1261,6 +1277,25 @@ static int iio_device_add_channel_label(struct iio_dev *indio_dev, return 1; } +static int iio_device_add_channel_parent_attr(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan) +{ + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); + int ret; + + if (!chan->parent) + return 0; + + ret = __iio_add_chan_devattr("parent", chan, + &iio_read_channel_parent, NULL, + 0, IIO_SEPARATE, &indio_dev->dev, NULL, + &iio_dev_opaque->channel_attr_list); + if (ret < 0) + return ret; + + return 1; +} + static int iio_device_add_info_mask_type(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, enum iio_shared_by shared_by, @@ -1399,6 +1434,11 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, return ret; attrcount += ret; + ret = iio_device_add_channel_parent_attr(indio_dev, chan); + if (ret < 0) + return ret; + attrcount += ret; + if (chan->ext_info) { unsigned int i = 0; diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index cd17703274a6..0f006b8ad555 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -264,6 +264,10 @@ struct iio_scan_type { * @ext_info: Array of extended info attributes for this channel. * The array is NULL terminated, the last element should * have its name field set to NULL. + * @parent: Optional pointer to the parent channel spec for + * hierarchical channel relationships. When set, a read-only + * "parent" sysfs attribute is created containing the + * parent channel's sysfs name prefix (e.g. "in_voltage0"). * @extend_name: Allows labeling of channel attributes with an * informative name. Note this has no effect codes etc, * unlike modifiers. @@ -309,6 +313,7 @@ struct iio_chan_spec { const struct iio_event_spec *event_spec; unsigned int num_event_specs; const struct iio_chan_spec_ext_info *ext_info; + const struct iio_chan_spec *parent; const char *extend_name; const char *datasheet_name; unsigned int modified:1; -- 2.43.0

