What is IIO?

Probably everybody knows about I/O Subsystem, but what is Industrial I/O Subsystem?

IIO is a kernel subsystem for analog to digital or digital to analog converters and related hardware. It has been developed since 2009 by Jonathan Cameron and linux-iio community. Examples of devices that fall in this category are: gyroscopes, accelerometers, light sensors, magnetometers, etc.

IIO is organized on two levels, devices and channels:

  • device is the top level of the hierarchy and it represents the acquisition chip. A device is described by the structures iio_info and iio_dev.
  • channel represents a single acquisition source of the device. A channel is described by the iio_chan_spec structure.

IIO communicates with user space via sysfs and a character device. We will have a look at how users can read information from devices.

Lets have a 3-axis accelerometer, mma8452 for example. After compiling and loading the module, if we look under /sys/bus/iio/devices/iio:device0/ we should have the following entries:

roberta@bazinga:~$ ls -l /sys/bus/iio/devices/iio:device0/
-rw-r--r-- 1 root root 4096 ian 21 17:01 in_accel_sampling_frequency
-rw-r--r-- 1 root root 4096 ian 21 17:01 in_accel_scale
-rw-r--r-- 1 root root 4096 ian 21 17:01 in_accel_x_calibbias
-rw-r--r-- 1 root root 4096 ian 21 17:01 in_accel_x_raw
-rw-r--r-- 1 root root 4096 ian 21 17:01 in_accel_y_calibbias
-rw-r--r-- 1 root root 4096 ian 21 17:01 in_accel_y_raw
-rw-r--r-- 1 root root 4096 ian 21 17:01 in_accel_z_calibbias
-rw-r--r-- 1 root root 4096 ian 21 17:01 in_accel_z_raw

The channel definition which gives this entry looks something like this:

#define MMA8452_CHANNEL(axis, idx) { \
    .type = IIO_ACCEL, \
    .modified = 1, \
    .channel2 = IIO_MOD_##axis, \
    .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
    .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
    .scan_index = idx, \
    .scan_type = { \
        .sign = 's', \
        .realbits = 12, \
        .storagebits = 16, \
        .shift = 4, \
        .endianness = IIO_BE, \
    }, \
static const struct iio_chan_spec mma8452_channels[] = {
    MMA8452_CHANNEL(X, 0),
    MMA8452_CHANNEL(Y, 1),
    MMA8452_CHANNEL(Z, 2),

So what are all these fields from  iio_chan_spec structure and what are their roles?

  • .type specifies the type of measurement that the channel is making. In our case (accelerometer), this is set to IIO_ACCEL, but it can have different values, such as: IIO_LIGHT, IIO_VOLTAGE, etc.
  • .modifier specifies if a modifier applies to this channel and in that case modifier is set in .channel2 (IIO_MOD_X, IIO_MOD_Y, IIO_MOD_Z for axial-sensors about the xyz axis)
  • .scan_index and .scan_type fields are used to identify elements from a buffer, when using buffer triggers, but we will discuss more about this in a future post.
  • .info_mask_separate and .info_mask_shared_by_type indicate what information is to be exported that is specific to this channel, respectively that is shared by all channels of the same type. In the example above IIO_CHAN_INFO_RAW, IIO_CHAN_INFO_CALIBBIAS, IIO_CHAN_INFO_SCALE, IIO_CHAN_INFO_SAMP_FREQ were used, but there are also others that can be used according to the driver specifications.

So what is the connection between the entries from /sys/bus/iio/devices/iio:device0/ stated before and these masks?

For instance, reading in_accel_scale calls the read_raw hook with the mask set to IIO_CHAN_INFO_SCALE. Reading in_accel_x_raw calls the read_raw hook with the mask set to IIO_CHAN_INFO_RAW (which is actually 0 since the data should be unscaled) and the channel argument set to the structure corresponding to channel X. More information about all these can be found in documentation.

Next posts will provide a brief overview of IIO triggered buffers (used to limit the amount of reads done by an application) and IIO events (used to receive a notification from the kernel when some event related to IIO happens).

A very nice description of IIO can be found in this presentation.

Additional information: