IIO_LE,
 };
 
+struct iio_chan_spec;
+struct iio_dev;
+
+/**
+ * struct iio_chan_spec_ext_info - Extended channel info attribute
+ * @name:      Info attribute name
+ * @shared:    Whether this attribute is shared between all channels.
+ * @read:      Read callback for this info attribute, may be NULL.
+ * @write:     Write callback for this info attribute, may be NULL.
+ */
+struct iio_chan_spec_ext_info {
+       const char *name;
+       bool shared;
+       ssize_t (*read)(struct iio_dev *, struct iio_chan_spec const *,
+                       char *buf);
+       ssize_t (*write)(struct iio_dev *, struct iio_chan_spec const *,
+                       const char *buf, size_t len);
+};
+
 /**
  * struct iio_chan_spec - specification of a single channel
  * @type:              What type of measurement is the channel making.
  * @info_mask:         What information is to be exported about this channel.
  *                     This includes calibbias, scale etc.
  * @event_mask:        What events can this channel produce.
+ * @ext_info:          Array of extended info attributes for this channel.
+ *                     The array is NULL terminated, the last element should
+ *                     have it's name field set to NULL.
  * @extend_name:       Allows labeling of channel attributes with an
  *                     informative name. Note this has no effect codes etc,
  *                     unlike modifiers.
        } scan_type;
        long                    info_mask;
        long                    event_mask;
+       const struct iio_chan_spec_ext_info *ext_info;
        char                    *extend_name;
        const char              *datasheet_name;
        unsigned                processed_val:1;
 
        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)
                                        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;
                        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;