Linux IIO Userspace Tools Guide-Free Linux Device Drivers Tutorial

Linux IIO Userspace Tools Guide
Free Linux Kernel Development Course — IIO Framework, Lecture 12
Chapter: IIO Framework
Level: Intermediate
Kernel: 6.x

Keywords Covered In This Lecture
linux iio tools
free embedded systems course
free linux development course
free linux device drivers course
free linux kernel development course
iio_generic_buffer
libiio

Every Linux IIO driver you write eventually needs to be tested from user space, and this is exactly where linux iio tools come in. Instead of hand-crafting every sysfs read with cat and echo, the kernel source tree ships a small set of ready-made command line programs that talk to the IIO core the same way any application would. In this lecture — the closing lecture of our free linux device drivers course chapter on the IIO framework — we walk through lsiio, iio_event_monitor, iio_generic_buffer, and the LibIIO library, build them from source, and run them end to end against a real character device node.

What You Will Learn

  • Purpose of each userspace IIO tool
  • Building tools/iio from kernel source
  • Listing devices with lsiio
  • Watching events with iio_event_monitor
  • Capturing buffered data with iio_generic_buffer
  • Where LibIIO fits in
  • End-to-end test walkthrough

Prerequisites

  • Comfortable with sysfs-based IIO testing (earlier lectures)
  • A working IIO driver with a chardev node (ep_iio_multisensor from the previous lecture works well)
  • Basic C toolchain: gcc, make
  • Downloaded or cloned Linux kernel source tree

Why Userspace IIO Tools Exist

Up to this lecture we tested every driver by hand: cat on a sysfs attribute, echo into a trigger file, or a raw read() on /dev/iio:deviceX. That works, but it does not scale once a device exposes dozens of channels and a triggered buffer. The kernel tree keeps four small reference programs under tools/iio/ precisely so driver authors have a known-good client to test against before writing a production application. They are intentionally minimal — meant to be read, not just run.

How The Tools Sit On Top Of IIO
lsiio / iio_event_monitor / iio_generic_buffer / libiio apps
sysfs attributes + /dev/iio:deviceX chardev
IIO core (industrialio)
Your IIO driver

lsiio: Enumerating Devices And Triggers

lsiio is the simplest of the four. It walks /sys/bus/iio/devices, prints every registered IIO device along with its channels, and lists any triggers currently available on the system. Think of it as the IIO equivalent of lsusb or lspci — a quick sanity check that your driver actually probed and registered correctly.

Building And Running lsiio

$ cd linux/tools/iio
$ make lsiio
$ sudo ./lsiio

Expected output once ep_iio_multisensor from the previous lecture is loaded:

Device 000: ep_iio_multisensor
  Channel 000: voltage0
  Channel 001: voltage1
  Channel 002: voltage2
  Channel 003: intensity_ir
  Channel 004: illuminance
Trigger 000: hrtimer-ep_trig0

iio_event_monitor: Watching IIO Events

Some IIO channels can raise asynchronous events — a threshold crossing on a light sensor, a magnitude spike on an accelerometer, and so on — through the IIO_GET_EVENT_FD_IOCTL interface on the chardev node. iio_event_monitor opens that event file descriptor, blocks in a loop, and decodes every event structure it receives into a readable line.

Running iio_event_monitor

$ sudo ./iio_event_monitor ep_iio_multisensor

Sample decoded output when a threshold event fires on the illuminance channel:

Event: time: 1737045213123456789, type: thresh, channel: 0, evtype: rising, value: over

If a driver never calls iio_push_event(), this tool simply blocks forever — which is itself a useful negative test while bringing up event support in a new driver.

iio_generic_buffer: Reading Triggered Buffer Data

This is the tool you will use the most. It enables the requested scan elements, sets a buffer length, arms the trigger, reads raw scan samples off /dev/iio:deviceX, and prints each one decoded according to the channel’s type attribute (endianness, sign, storage bits, shift — everything we covered in the scan_elements lecture).

Modernization Note

In current mainline kernel source, this program is named iio_generic_buffer.c. Older trees (including the one this course chapter was originally written against) shipped it as generic_buffer.c. The behaviour and command-line flags are unchanged — only the filename moved. Always check tools/iio/ in the kernel version you are building against.

Running iio_generic_buffer

$ sudo ./iio_generic_buffer -N ep_iio_multisensor -c 10 -l 64

Flag meanings: -N selects the device by name, -c requests a sample count, -l sets the buffer length. Expected decoded output:

voltage0: 1024  voltage1: 2048  voltage2: 512  intensity_ir: 300
voltage0: 1030  voltage1: 2041  voltage2: 509  intensity_ir: 298
...

LibIIO: Beyond The Reference Tools

The three programs above are deliberately small teaching examples. For a real product — a data-logging app, a Qt GUI, a Python analysis script — you normally link against LibIIO instead of reimplementing sysfs parsing yourself. LibIIO is a C library maintained outside the kernel tree that wraps device discovery, channel attribute access, and buffered capture behind a stable API, with bindings for C++, Python, and C#. It also ships its own command-line utility, iio_info, which prints the same device/channel tree as lsiio but with full attribute values expanded.

A minimal LibIIO-based reader looks like this in C:

#include <iio.h>
#include <stdio.h>

int main(void)
{
    struct iio_context *ctx = iio_create_local_context();
    if (!ctx) {
        fprintf(stderr, "no IIO context found\n");
        return 1;
    }

    unsigned int count = iio_context_get_devices_count(ctx);
    printf("found %u IIO devices\n", count);

    for (unsigned int i = 0; i < count; i++) {
        struct iio_device *dev = iio_context_get_device(ctx, i);
        printf("  %s\n", iio_device_get_name(dev));
    }

    iio_context_destroy(ctx);
    return 0;
}

This is an original teaching snippet written for this course, compiled with gcc reader.c -liio -o reader and run as ./reader; it enumerates the same ep_iio_multisensor device that lsiio found above.

End-To-End Walkthrough

Bring the four tools together against the multi-channel driver from the previous lecture:

# 1. Load the driver
$ sudo insmod ep_iio_multisensor.ko

# 2. Confirm it registered
$ sudo ./lsiio

# 3. Watch for threshold events in one terminal
$ sudo ./iio_event_monitor ep_iio_multisensor &

# 4. Capture 20 triggered samples in another terminal
$ sudo ./iio_generic_buffer -N ep_iio_multisensor -c 20 -l 128

# 5. Cross-check a single channel manually via sysfs
$ cat /sys/bus/iio/devices/iio:device0/in_voltage0_raw

# 6. Unload
$ sudo rmmod ep_iio_multisensor

Seeing the same values through lsiio, iio_generic_buffer, and a raw sysfs cat agree with each other is the fastest way to convince yourself a new driver’s read_raw() and buffer push path are both correct.

IIO Framework Chapter Recap

What This Chapter Covered

  • iio_dev and channel model
  • read_raw / write_raw callbacks
  • Indexed and modified channels
  • Triggers: interrupt, hrtimer, sysfs
  • Triggered buffers and setup_ops
  • scan_elements and the type attribute
  • Full probe() walkthrough
  • One-shot vs buffered capture
  • Userspace tools (this lecture)

That closes the IIO framework chapter of this free linux kernel development course. You now have every piece needed to take a sensor from a datasheet to a fully buffered, triggerable IIO driver, and to verify it with the same tools the kernel community uses to test upstream drivers.

Next in this free linux device drivers course, we move away from sensors and into one of the most heavily used resources on any system: kernel memory management — allocators, pages, and how your driver should request memory safely.

Frequently Asked Questions

Where do I get lsiio, iio_event_monitor, and iio_generic_buffer?

They live under tools/iio/ in the Linux kernel source tree and are built with a plain make inside that directory once you have the kernel headers checked out.

Do these tools require root privileges?

Usually yes, because sysfs and the IIO chardev nodes are typically owned by root unless you have added udev rules to relax permissions for a specific device.

Why was generic_buffer.c renamed to iio_generic_buffer.c?

The kernel maintainers renamed it for a consistent iio_ prefix across all the tools. Functionally it is the same program with the same command-line flags.

Is LibIIO part of the kernel source tree?

No. LibIIO is a separate userspace project maintained outside the kernel, built and installed independently, though it talks to the exact same sysfs and chardev interfaces these kernel tools use.

Can iio_generic_buffer decode any channel automatically?

Yes, it reads each channel’s type attribute (endianness, signedness, storage bits, shift) at runtime and decodes samples accordingly, which is why getting scan_type right in your driver matters.

What if iio_event_monitor never prints anything?

It blocks until an event actually fires. If your driver never calls iio_push_event(), or no threshold has been crossed, the tool will simply wait — that is expected behaviour, not a bug.

Do I need LibIIO to follow this free embedded systems course?

No, the kernel reference tools are enough for every driver test in this course. LibIIO is introduced here only so you know it exists for real applications.

What comes after the IIO framework chapter?

The course moves on to Linux kernel memory management, covering allocators and how drivers should request and free memory correctly.

Continue The Free Linux Kernel Development Course

 

Leave a Reply

Your email address will not be published. Required fields are marked *