IIO Subsystem

The Industrial I/O (IIO) subsystem provides a unified framework for sensors and data acquisition devices, including ADCs, DACs, accelerometers, gyroscopes, magnetometers, light sensors, and more.

Why IIO?

flowchart TB
    subgraph Before["Before IIO"]
        ADC1["ADC Driver"]
        ACCEL1["Accel Driver"]
        GYRO1["Gyro Driver"]
        CUSTOM1["Custom sysfs"]
        CUSTOM2["Custom chardev"]
        CUSTOM3["Unique API"]
    end

    subgraph After["With IIO"]
        IIOCORE["IIO Core"]
        SYSFS["Standard sysfs"]
        CHARDEV["/dev/iio:deviceN"]
        BUFFER["Triggered Buffers"]
        EVENTS["IIO Events"]
    end

    ADC1 --> CUSTOM1
    ACCEL1 --> CUSTOM2
    GYRO1 --> CUSTOM3

    IIOCORE --> SYSFS
    IIOCORE --> CHARDEV
    IIOCORE --> BUFFER
    IIOCORE --> EVENTS

    style Before fill:#8f6d72,stroke:#c62828
    style After fill:#7a8f73,stroke:#2e7d32

IIO Architecture

flowchart TB
    subgraph Userspace
        APP["Application"]
        LIBIIO["libiio"]
        SYSFS_U["/sys/bus/iio/"]
        DEV["/dev/iio:deviceN"]
    end

    subgraph Kernel["IIO Core"]
        CORE["IIO Core"]
        TRIGGER["IIO Triggers"]
        BUFFER_K["IIO Buffers"]
        EVENT["IIO Events"]
    end

    subgraph Drivers
        ADC["ADC Driver"]
        ACCEL["Accel Driver"]
        LIGHT["Light Sensor"]
    end

    APP --> LIBIIO
    APP --> SYSFS_U
    APP --> DEV

    LIBIIO --> CORE
    SYSFS_U --> CORE
    DEV --> BUFFER_K

    CORE --> ADC
    CORE --> ACCEL
    CORE --> LIGHT
    TRIGGER --> BUFFER_K
    BUFFER_K --> CORE

    style Userspace fill:#738f99,stroke:#0277bd
    style Kernel fill:#7a8f73,stroke:#2e7d32
    style Drivers fill:#8f8a73,stroke:#f9a825

Key Concepts

Channels

IIO devices expose data through channels. Each channel represents a measurement:

#include <linux/iio/iio.h>

struct iio_chan_spec {
    enum iio_chan_type type;      /* Channel type (VOLTAGE, ACCEL, etc.) */
    int channel;                   /* Channel index */
    int channel2;                  /* Modifier channel */
    unsigned long address;         /* Driver-specific address */
    int scan_index;               /* Buffer scan order */
    struct {
        char sign;                /* 's' or 'u' */
        u8 realbits;              /* Actual bits of data */
        u8 storagebits;           /* Storage bits (8, 16, 32) */
        u8 shift;                 /* Shift to apply */
        u8 repeat;                /* Number of repeated elements */
        enum iio_endian endianness;
    } scan_type;
    long info_mask_separate;       /* Per-channel attributes */
    long info_mask_shared_by_type; /* Shared attributes */
    long info_mask_shared_by_dir;  /* Direction-shared attrs */
    long info_mask_shared_by_all;  /* Global attributes */
    /* ... */
};

Channel Types

enum iio_chan_type {
    IIO_VOLTAGE,
    IIO_CURRENT,
    IIO_POWER,
    IIO_ACCEL,
    IIO_ANGL_VEL,      /* Gyroscope */
    IIO_MAGN,          /* Magnetometer */
    IIO_LIGHT,
    IIO_INTENSITY,
    IIO_PROXIMITY,
    IIO_TEMP,
    IIO_INCLI,         /* Inclinometer */
    IIO_ROT,           /* Rotation */
    IIO_ANGL,          /* Angle */
    IIO_TIMESTAMP,
    IIO_CAPACITANCE,
    IIO_ALTVOLTAGE,    /* Frequency/phase */
    IIO_CCT,           /* Color temperature */
    IIO_PRESSURE,
    IIO_HUMIDITYRELATIVE,
    IIO_ACTIVITY,
    IIO_STEPS,
    IIO_ENERGY,
    IIO_DISTANCE,
    IIO_VELOCITY,
    IIO_CONCENTRATION,
    IIO_RESISTANCE,
    IIO_PH,
    IIO_UVINDEX,
    IIO_ELECTRICALCONDUCTIVITY,
    IIO_COUNT,
    IIO_INDEX,
    IIO_GRAVITY,
    IIO_POSITIONRELATIVE,
    IIO_PHASE,
    IIO_MASSCONCENTRATION,
    /* ... */
};

Channel Modifiers

enum iio_modifier {
    IIO_NO_MOD,
    IIO_MOD_X,          /* X axis */
    IIO_MOD_Y,          /* Y axis */
    IIO_MOD_Z,          /* Z axis */
    IIO_MOD_X_AND_Y,
    IIO_MOD_X_AND_Z,
    IIO_MOD_Y_AND_Z,
    IIO_MOD_X_AND_Y_AND_Z,
    IIO_MOD_X_OR_Y,
    IIO_MOD_X_OR_Z,
    IIO_MOD_Y_OR_Z,
    IIO_MOD_X_OR_Y_OR_Z,
    IIO_MOD_LIGHT_BOTH,
    IIO_MOD_LIGHT_IR,
    IIO_MOD_LIGHT_CLEAR,
    IIO_MOD_LIGHT_RED,
    IIO_MOD_LIGHT_GREEN,
    IIO_MOD_LIGHT_BLUE,
    IIO_MOD_LIGHT_UV,
    /* ... */
};

Info Mask Attributes

/* Commonly used info masks */
IIO_CHAN_INFO_RAW           /* Raw reading */
IIO_CHAN_INFO_PROCESSED     /* Processed/scaled reading */
IIO_CHAN_INFO_SCALE         /* Scale factor */
IIO_CHAN_INFO_OFFSET        /* Offset to apply */
IIO_CHAN_INFO_CALIBSCALE    /* Calibration scale */
IIO_CHAN_INFO_CALIBBIAS     /* Calibration bias */
IIO_CHAN_INFO_PEAK          /* Peak value */
IIO_CHAN_INFO_PEAK_SCALE
IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW
IIO_CHAN_INFO_AVERAGE_RAW
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY
IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY
IIO_CHAN_INFO_SAMP_FREQ     /* Sampling frequency */
IIO_CHAN_INFO_FREQUENCY
IIO_CHAN_INFO_PHASE
IIO_CHAN_INFO_HARDWAREGAIN
IIO_CHAN_INFO_HYSTERESIS
IIO_CHAN_INFO_HYSTERESIS_RELATIVE
IIO_CHAN_INFO_INT_TIME      /* Integration time */
IIO_CHAN_INFO_ENABLE
IIO_CHAN_INFO_CALIBHEIGHT
IIO_CHAN_INFO_CALIBWEIGHT
IIO_CHAN_INFO_DEBOUNCE_COUNT
IIO_CHAN_INFO_DEBOUNCE_TIME
IIO_CHAN_INFO_OVERSAMPLING_RATIO
IIO_CHAN_INFO_THERMOCOUPLE_TYPE
IIO_CHAN_INFO_CALIBAMBIENT

sysfs Interface

/sys/bus/iio/devices/iio:device0/
├── name                    # Device name
├── dev                     # Major:minor
├── in_voltage0_raw         # Raw ADC reading
├── in_voltage_scale        # Scale factor
├── in_accel_x_raw          # Accelerometer X raw
├── in_accel_y_raw          # Accelerometer Y raw
├── in_accel_z_raw          # Accelerometer Z raw
├── in_accel_scale          # Accelerometer scale
├── sampling_frequency      # Current sample rate
├── sampling_frequency_available  # Available rates
├── buffer/
│   ├── enable              # Enable buffer capture
│   ├── length              # Buffer length
│   └── watermark           # Watermark threshold
├── scan_elements/
│   ├── in_voltage0_en      # Enable channel in buffer
│   ├── in_voltage0_type    # Data format
│   └── in_voltage0_index   # Position in buffer
└── trigger/
    └── current_trigger     # Current trigger name

Reading Sensor Data

Direct Reading via sysfs

# Read raw value
cat /sys/bus/iio/devices/iio:device0/in_voltage0_raw
# Returns: 2048

# Read scale
cat /sys/bus/iio/devices/iio:device0/in_voltage_scale
# Returns: 0.000805664

# Calculate actual value: 2048 * 0.000805664 = 1.65V

Using libiio

#include <iio.h>

struct iio_context *ctx = iio_create_local_context();
struct iio_device *dev = iio_context_find_device(ctx, "my-adc");
struct iio_channel *ch = iio_device_find_channel(dev, "voltage0", false);

double scale;
iio_channel_attr_read_double(ch, "scale", &scale);

long long raw;
iio_channel_attr_read_longlong(ch, "raw", &raw);

double voltage = raw * scale;
printf("Voltage: %.3f V\n", voltage);

iio_context_destroy(ctx);

Device Tree Binding

adc@48 {
    compatible = "vendor,my-adc";
    reg = <0x48>;
    #io-channel-cells = <1>;
    vref-supply = <&vdd_3v3>;
};

/* Consumer using the ADC */
battery_monitor {
    compatible = "simple-battery";
    io-channels = <&adc 0>;       /* Channel 0 */
    io-channel-names = "voltage";
};

Summary

  • IIO provides unified framework for sensors and DAQ devices
  • Channels represent individual measurements
  • Info masks define available attributes
  • sysfs provides human-readable interface
  • Buffered acquisition for high-speed data
  • Triggers synchronize data capture

Further Reading

Next

Learn how to implement an IIO driver.


Back to top

Linux Driver Development Guide is a community resource for learning kernel driver development. Not affiliated with the Linux Foundation. Content provided for educational purposes.

This site uses Just the Docs, a documentation theme for Jekyll.