IIO One-Shot and Buffer Data Capture
In the Linux IIO framework, once a driver has registered channels and (optionally) wired up a trigger, there are only two ways for user space to actually pull sensor readings out of it: a quick one-shot read through sysfs, or a continuous, timestamped stream through the triggered buffer and the IIO character device. This lecture walks through both paths end to end, with real sysfs commands, an original sample driver, and the exact output you should expect to see at each step, so you know precisely how iio one-shot and buffer capture behaves on a modern 6.x kernel.
Free Linux Kernel Development Course
free linux development course
free linux device drivers course
free linux kernel development course
free embedded linux course
What You Will Learn
- The difference between one-shot sysfs capture and triggered buffer capture
- How to read a raw value and scale it into a real-world unit
- The exact sysfs command sequence to arm and fire a sysfs trigger
- How to set up an hrtimer trigger through configfs
- How to read and decode the binary stream from an IIO character device
- Common mistakes, troubleshooting tips, and best practices for buffer capture
Prerequisites
- Completion of the earlier IIO lectures in this series (channel model, buffer setup, trigger types, scan_elements type attribute)
- A kernel built with
CONFIG_IIO,CONFIG_IIO_BUFFER, andCONFIG_IIO_TRIGGERED_BUFFERenabled - Basic comfort with shell commands and reading
/sysentries - A working IIO driver that has already called
devm_iio_triggered_buffer_setup(), as covered earlier in this course
Two Ways to Read IIO Sensor Data
Every IIO driver exposes its channels in one of two access modes, and it is important to pick the right one for the job.
| Access mode | Interface used | Best for | Data returned |
|---|---|---|---|
| One-shot capture | sysfs channel attributes | Occasional polling, quick sanity checks, slow-changing values like temperature | A single raw sample per read |
| Buffered capture | IIO character device (/dev/iio:deviceX) |
High-rate sampling, waveform capture, sensor fusion | A continuous stream of timestamped scan sets |
One-Shot Capture Through Sysfs
One-shot capture is the simplest way to read a channel. You simply cat the raw sysfs attribute for that channel, then apply the scale to convert it into a physical unit. Assume our sample driver ep_iio_multisensor exposes an illuminance channel:
# cd /sys/bus/iio/devices/iio:device0
# cat in_illuminance_raw
15234
# cat in_illuminance_scale
0.0025000
The processed value is always raw × scale. For this channel that gives:
15234 * 0.0025000 = 38.085
If the driver documents this channel in lux, the reading is 38.085 lux. This is exactly what a read_raw() callback with IIO_CHAN_INFO_RAW and IIO_CHAN_INFO_SCALE support returns under the hood — one-shot capture never touches the buffer subsystem at all.
Buffer Data Access Overview
Buffered capture is a different story. Before any data can flow, the driver must already implement trigger support, typically through devm_iio_triggered_buffer_setup(), as we built in the earlier lecture on triggered buffers. Once that plumbing exists, user space is responsible for a five-part setup: create or select a trigger, assign it to the device, enable the scan elements that should be captured, size the buffer, and finally enable it. Only after all of that is the trigger fired and data pulled from the character device.
Capturing Data Using the Sysfs Trigger
The sysfs trigger is the easiest trigger type to test with because it needs no timer and no external interrupt — you fire it manually with a single write. Here is the complete sequence for our ep_iio_multisensor device, which exposes four voltage channels.
Step 1 — Create the trigger. This allocates a new sysfs trigger and gives it an index:
# echo 0 > /sys/devices/iio_sysfs_trigger/add_trigger
A new directory trigger0 now appears under /sys/bus/iio/devices/, and its name attribute reads sysfstrig0.
Step 2 — Assign the trigger to the device. A device is tied to a trigger purely by name:
# echo sysfstrig0 > /sys/bus/iio/devices/iio:device0/trigger/current_trigger
# cat /sys/bus/iio/devices/iio:device0/trigger/current_trigger
sysfstrig0
Always read the value back after writing it. If the name does not match an existing trigger, the write silently does nothing.
Step 3 — Enable the scan elements you want captured. Only channels with their _en attribute set to 1 are pushed into the buffer:
# echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage0_en
# echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage1_en
# echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage2_en
# echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage3_en
Step 4 — Set the buffer length. This is the number of scan sets the kernel buffer can hold before it starts blocking or dropping data:
# echo 128 > /sys/bus/iio/devices/iio:device0/buffer/length
Step 5 — Enable the buffer. This tells the driver’s preenable/postenable callbacks to start accepting pushed data:
# echo 1 > /sys/bus/iio/devices/iio:device0/buffer/enable
Step 6 — Fire the trigger. A single manual pulse captures exactly one scan set:
# echo 1 > /sys/bus/iio/devices/trigger0/trigger_now
Step 7 — Read the character device. Each read returns raw binary scan sets, so a hex dump is the easiest way to inspect them:
# cat /dev/iio:device0 | xxd
00000000: 2c01 3900 4a02 1e00 91b4 2e77 3a9c c714 ,.9.J......w:...
Step 8 — Disable the buffer once you are done capturing:
# echo 0 > /sys/bus/iio/devices/iio:device0/buffer/enable
Step 9 — Detach the trigger so the device is free to be reused with a different trigger later:
# echo "" > /sys/bus/iio/devices/iio:device0/trigger/current_trigger
Capturing Data Using the hrtimer Trigger
The sysfs trigger is great for manual testing, but real applications almost always want periodic sampling. For that, the hrtimer trigger is created through configfs instead of a sysfs write, and it fires automatically at a fixed frequency rather than waiting for a manual pulse.
# mkdir /sys/kernel/config/iio/triggers/hrtimer/trigger0
# echo 50 > /sys/bus/iio/devices/trigger0/sampling_frequency
# echo trigger0 > /sys/bus/iio/devices/iio:device0/trigger/current_trigger
# echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage0_en
# echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage1_en
# echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage2_en
# echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage3_en
# echo 1 > /sys/bus/iio/devices/iio:device0/buffer/enable
# cat /dev/iio:device0 | xxd
00000000: 2c01 3900 4a02 1e00 d451 7a6f 3a9c c714 ,.9.J....Qzo:...
00000010: 2e01 3a00 4b02 1f00 3c7c 7a6f 3a9c c714 ..:.K...<|zo:...
With sampling_frequency set to 50, the trigger fires 50 times a second on its own, so scan sets keep arriving in the character device stream without any further manual action. Each scan set here ends with an 8-byte nanosecond timestamp, which is why you see the values changing slightly on every line — that timestamp channel was covered in the earlier lecture on scan_elements and the type attribute.
Cleanup for an hrtimer trigger uses rmdir instead of a sysfs write:
# echo 0 > /sys/bus/iio/devices/iio:device0/buffer/enable
# rmdir /sys/kernel/config/iio/triggers/hrtimer/trigger0
Sysfs Trigger vs hrtimer Trigger
| Aspect | Sysfs trigger | hrtimer trigger |
|---|---|---|
| Created via | add_trigger sysfs write |
configfs mkdir |
| Fires | Manually, once per write to trigger_now |
Automatically, at sampling_frequency Hz |
| Typical use | Bring-up, debugging, unit tests | Continuous periodic sampling in production |
| Kernel config | CONFIG_IIO_SYSFS_TRIGGER |
CONFIG_IIO_HRTIMER_TRIGGER |
Driver-Side Recap
None of the sysfs sequence above works unless the driver already registered trigger and buffer support at probe time. The short version, using the resource-managed API from earlier in this chapter, looks like this:
ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
iio_pollfunc_store_time,
ep_trigbuf_handler, NULL);
if (ret)
return dev_err_probe(&spi->dev, ret,
"triggered buffer setup failed\n");
ret = devm_iio_device_register(&spi->dev, indio_dev);
if (ret)
return dev_err_probe(&spi->dev, ret,
"iio device register failed\n");
Because both calls are devm_-managed, there is no manual teardown to write in a remove callback — the framework unwinds everything automatically when the device is unbound.
Common Mistakes and Troubleshooting
- Forgetting to read back
current_trigger. A typo in the trigger name fails silently; alwayscatit back to confirm. - Enabling the buffer before enabling scan elements. Some drivers reject this in
preenable; always enable channels first. - Buffer length too small. A tiny
buffer/lengthvalue with a fast trigger causes samples to be dropped or reads to block unexpectedly. - Reading with
caton a very slow trigger.catblocks until a full scan set is available, so a slow sysfs trigger can make it look like the command has hung. - Not detaching the trigger. A device left attached to a trigger can prevent switching to a different trigger type later.
Best Practices
- Always disable the buffer before changing scan elements, buffer length, or the trigger.
- Use the sysfs trigger for bring-up and automated tests; move to the hrtimer trigger for anything periodic.
- Decode buffers using the
scan_typeattributes from each channel rather than assuming a fixed layout. - Prefer
devm_iio_triggered_buffer_setup()in new drivers so cleanup is handled automatically.
Performance Considerations
One-shot sysfs reads involve a full sysfs round trip per channel, so they do not scale well past a few reads per second. Buffered capture amortizes that cost across many samples, which is why any application sampling faster than a few Hz, or reading more than one channel synchronously, should always use the triggered buffer path instead of polling sysfs in a loop.
Security Considerations
Sysfs IIO attributes are typically root-owned by default. If user-space applications need to control triggers or buffers without root, use udev rules to grant a dedicated group access rather than relaxing permissions on the whole IIO subsystem. Also validate any buffer length or sampling frequency values coming from configuration files before writing them to sysfs, since some drivers do not clamp these inputs in the kernel.
Real-World Use Cases
- Environmental monitors that check temperature or humidity once a minute — one-shot sysfs capture is more than enough.
- Vibration and motion-sensing applications that need continuous, timestamped accelerometer samples — triggered buffer with an hrtimer trigger.
- Automated hardware test rigs that need to fire a single deterministic sample for a golden-value comparison — sysfs trigger.
Summary / Key Takeaways
- One-shot capture reads a single raw value directly through sysfs and needs no trigger.
- Buffered capture requires a driver that already implements triggered buffer support.
- The sysfs trigger is fired manually and is best for testing; the hrtimer trigger fires automatically at a set frequency.
- The full buffer sequence is: create/assign trigger, enable scan elements, set buffer length, enable buffer, fire or wait, read the character device, then disable and detach.
Conclusion
Between one-shot sysfs reads and the triggered buffer character device, the IIO framework covers everything from a quick temperature check to a high-rate accelerometer stream. Once your driver has trigger and buffer support wired up through devm_iio_triggered_buffer_setup(), the user-space side is just a fixed sequence of sysfs writes — the same nine steps whether you are firing a sysfs trigger by hand or letting an hrtimer trigger run on its own. Master this sequence and you can validate and consume data from any IIO-based sensor driver you write.
FAQ
What is the difference between one-shot and buffered IIO capture?
One-shot capture reads a single value directly from a sysfs channel attribute with no trigger involved. Buffered capture streams continuous, timestamped scan sets through the IIO character device and requires trigger support in the driver.
Do I need a trigger for one-shot sysfs reads?
No. One-shot reads go straight through the driver’s read_raw() callback and never touch the trigger or buffer subsystem.
Why did writing to current_trigger seem to do nothing?
If the trigger name you write does not match an existing registered trigger exactly, the write is accepted but has no effect. Always read the attribute back to confirm the trigger was actually assigned.
How is the hrtimer trigger different from the sysfs trigger?
The sysfs trigger is created with a sysfs write and fires only when you manually write to trigger_now. The hrtimer trigger is created through configfs and fires automatically at the frequency you set in sampling_frequency.
Why is my buffer read blocking forever?
A read on the character device blocks until a complete scan set is available. If the buffer is enabled but the trigger is never fired (sysfs trigger) or the sampling frequency is effectively zero, the read will appear to hang.
What does buffer/length actually control?
It sets how many scan sets the kernel-side buffer can hold. A value too small for your sampling rate causes samples to be dropped once the buffer fills up before user space reads them.
Can I enable more than one trigger type on the same device at once?
No. A device has a single current_trigger at a time. You must detach the existing trigger before assigning a different one.
How do I decode the hex bytes from the character device?
Use each enabled channel’s scan_type attribute to determine byte order, sign, real bits, storage bits, and shift, exactly as covered in the earlier lecture on the scan_elements type attribute.
Which kernel config options do I need for buffer capture?
CONFIG_IIO_BUFFER and CONFIG_IIO_TRIGGERED_BUFFER are required, plus CONFIG_IIO_SYSFS_TRIGGER or CONFIG_IIO_HRTIMER_TRIGGER depending on which trigger type you plan to use.
Continue the Free Linux Kernel Development Course
Keep going with the next lecture in this IIO framework series, part of EmbeddedPathashala’s free embedded Linux course.
