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 label.
Signed-off-by: Rodrigo Alencar <[email protected]> --- drivers/iio/industrialio-core.c | 38 ++++++++++++++++++++++++++++++++++++++ include/linux/iio/iio.h | 5 +++++ 2 files changed, 43 insertions(+) diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 5c8404efd0a5..348ac7a59738 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -776,6 +776,14 @@ 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) +{ + return do_iio_read_channel_label(dev_to_iio_dev(dev), + to_iio_dev_attr(attr)->c->parent, buf); +} + static ssize_t iio_read_channel_info(struct device *dev, struct device_attribute *attr, char *buf) @@ -1263,6 +1271,31 @@ static int iio_device_add_channel_label(struct iio_dev *indio_dev, return 1; } +static int iio_device_add_channel_parent(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 || (!indio_dev->info->read_label && + !chan->parent->extend_name)) + 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, @@ -1401,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(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 86d17ee69e05..09a97518e4bd 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -258,6 +258,10 @@ struct iio_scan_type { * by all channels. * @info_mask_shared_by_all_available: What availability information is to be * exported that is shared by all channels. + * @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 label. * @event_spec: Array of events which should be registered for this * channel. * @num_event_specs: Size of the event_spec array. @@ -306,6 +310,7 @@ struct iio_chan_spec { unsigned long info_mask_shared_by_dir_available; unsigned long info_mask_shared_by_all; unsigned long info_mask_shared_by_all_available; + const struct iio_chan_spec *parent; const struct iio_event_spec *event_spec; unsigned int num_event_specs; const struct iio_chan_spec_ext_info *ext_info; -- 2.43.0

