2015-07-31 14:20:00

by Daniel Baluta

[permalink] [raw]
Subject: [PATCH v4] DocBook documentation for IIO

In our effort to support vendors writing drivers for their own
sensors we introduce IIO documentation in DocBook format.

It documents Industrial I/O core including IIO devices, buffers, triggers and
triggered buffers. It also offers a short list of online resources
for the IIO subsystem.

This is far from being complete any suggestions are welcomed. At a first
glance we also need to add documentation for events. We are also working
on auto-generating template drivers based on the type of the IIO sensors.

Generated html files should be available online here http://dbaluta.github.io/
or you could run make htmldocs in the root of your kernel repo to get them.


Changes since v3:
* addressed feedback from Crt Mori
* http://marc.info/?l=linux-iio&m=143815719008296&w=2

Changes since v2:
* addressed feedback from Lars-Peter
* http://marc.info/?l=linux-iio&m=143774991802816&w=2
* Many thanks to Lars-Peter Clausen for scan_index paragraph.

Changes since v1:
* mostly typos and clarifications
* addressed comments from Jonathan Corbet and Jonathan Cameron
* http://marc.info/?l=linux-iio&m=143704226629498&w=2
* http://marc.info/?l=linux-iio&m=143707511006898&w=2
* for DocBook warnings reported by Randy, Cristina sent
this patchseries:
http://marc.info/?l=linux-iio&m=143774363900903&w=2

Daniel Baluta (1):
DocBook: Add initial documentation for IIO

Documentation/DocBook/Makefile | 2 +-
Documentation/DocBook/iio.tmpl | 702 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 703 insertions(+), 1 deletion(-)
create mode 100644 Documentation/DocBook/iio.tmpl

--
1.9.1


2015-07-31 14:19:32

by Daniel Baluta

[permalink] [raw]
Subject: [PATCH v4] DocBook: Add initial documentation for IIO

This is intended to help developers faster find their way
inside the Industrial I/O core and reduce time spent on IIO
drivers development.

Signed-off-by: Daniel Baluta <[email protected]>
---
Documentation/DocBook/Makefile | 2 +-
Documentation/DocBook/iio.tmpl | 702 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 703 insertions(+), 1 deletion(-)
create mode 100644 Documentation/DocBook/iio.tmpl

diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index b6a6a2e..9e08606 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -15,7 +15,7 @@ DOCBOOKS := z8530book.xml device-drivers.xml \
80211.xml debugobjects.xml sh.xml regulator.xml \
alsa-driver-api.xml writing-an-alsa-driver.xml \
tracepoint.xml drm.xml media_api.xml w1.xml \
- writing_musb_glue_layer.xml crypto-API.xml
+ writing_musb_glue_layer.xml crypto-API.xml iio.xml

include Documentation/DocBook/media/Makefile

diff --git a/Documentation/DocBook/iio.tmpl b/Documentation/DocBook/iio.tmpl
new file mode 100644
index 0000000..b39b3e9
--- /dev/null
+++ b/Documentation/DocBook/iio.tmpl
@@ -0,0 +1,702 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="iioid">
+ <bookinfo>
+ <title>Industrial I/O driver developer's guide </title>
+
+ <authorgroup>
+ <author>
+ <firstname>Daniel</firstname>
+ <surname>Baluta</surname>
+ <affiliation>
+ <address>
+ <email>[email protected]</email>
+ </address>
+ </affiliation>
+ </author>
+ </authorgroup>
+
+ <copyright>
+ <year>2015</year>
+ <holder>Intel Corporation</holder>
+ </copyright>
+
+ <legalnotice>
+ <para>
+ This documentation is free software; you can redistribute
+ it and/or modify it under the terms of the GNU General Public
+ License version 2.
+ </para>
+ </legalnotice>
+ </bookinfo>
+
+ <toc></toc>
+
+ <chapter id="intro">
+ <title>Introduction</title>
+ <para>
+ The main purpose of the Industrial I/O subsystem (IIO) is to provide
+ support for devices that in some sense perform either analog-to-digital
+ conversion (ADC) or digital-to-analog conversion (DAC) or both. The aim
+ is to fill the gap between the somewhat similar hwmon and input
+ subsystems.
+ Hwmon is directed at low sample rate sensors used to monitor and
+ control the system itself, like fan speed control or temperature
+ measurement. Input is, as its name suggests, focused on human interaction
+ input devices (keyboard, mouse, touchscreen). In some cases there is
+ considerable overlap between these and IIO.
+ </para>
+ <para>
+ Devices that fall into this category include:
+ <itemizedlist>
+ <listitem>
+ analog to digital converters (ADCs)
+ </listitem>
+ <listitem>
+ accelerometers
+ </listitem>
+ <listitem>
+ capacitance to digital converters (CDCs)
+ </listitem>
+ <listitem>
+ digital to analog converters (DACs)
+ </listitem>
+ <listitem>
+ gyroscopes
+ </listitem>
+ <listitem>
+ inertial measurement units (IMUs)
+ </listitem>
+ <listitem>
+ color and light sensors
+ </listitem>
+ <listitem>
+ magnetometers
+ </listitem>
+ <listitem>
+ pressure sensors
+ </listitem>
+ <listitem>
+ proximity sensors
+ </listitem>
+ <listitem>
+ temperature sensors
+ </listitem>
+ </itemizedlist>
+ Usually these sensors are connected via SPI or I2C. A common use case of the
+ sensors devices is to have combined functionality (e.g. light plus proximity
+ sensor).
+ </para>
+ </chapter>
+ <chapter id='iiosubsys'>
+ <title>Industrial I/O core</title>
+ <para>
+ The Industrial I/O core offers:
+ <itemizedlist>
+ <listitem>
+ a unified framework for writing drivers for many different types of
+ embedded sensors.
+ </listitem>
+ <listitem>
+ a standard interface to user space applications manipulating sensors.
+ </listitem>
+ </itemizedlist>
+ The implementation can be found under <filename>
+ drivers/iio/industrialio-*</filename>
+ </para>
+ <sect1 id="iiodevice">
+ <title> Industrial I/O devices </title>
+
+!Finclude/linux/iio/iio.h iio_dev
+!Fdrivers/iio/industrialio-core.c iio_device_alloc
+!Fdrivers/iio/industrialio-core.c iio_device_free
+!Fdrivers/iio/industrialio-core.c iio_device_register
+!Fdrivers/iio/industrialio-core.c iio_device_unregister
+
+ <para>
+ An IIO device usually corresponds to a single hardware sensor and it
+ provides all the information needed by a driver handling a device.
+ Let's first have a look at the functionality embedded in an IIO
+ device then we will show how a device driver makes use of an IIO
+ device.
+ </para>
+ <para>
+ There are two ways for a user space application to interact
+ with an IIO driver.
+ <itemizedlist>
+ <listitem>
+ <filename>/sys/bus/iio/iio:deviceX/</filename>, this
+ represents a hardware sensor and groups together the data
+ channels of the same chip.
+ </listitem>
+ <listitem>
+ <filename>/dev/iio:deviceX</filename>, character device node
+ interface used for faster data transfer and for events information
+ retrieval.
+ </listitem>
+ </itemizedlist>
+ </para>
+ A typical IIO driver will register itself as an I2C or SPI driver and will
+ create two routines, <function> probe </function> and <function> remove
+ </function>. At <function>probe</function>:
+ <itemizedlist>
+ <listitem>call <function>iio_device_alloc</function>, which allocates memory
+ for an IIO device.
+ </listitem>
+ <listitem> initialize IIO device fields with driver specific information
+ (e.g. device name, device channels).
+ </listitem>
+ <listitem>call <function> iio_device_register</function>, this registers the
+ device with the IIO core. After this call the device is ready to accept
+ requests from user space applications.
+ </listitem>
+ </itemizedlist>
+ At <function>remove</function>, we free the resources allocated in
+ <function>probe</function> in reverse order:
+ <itemizedlist>
+ <listitem><function>iio_device_unregister</function>, unregister the device
+ from the IIO core.
+ </listitem>
+ <listitem><function>iio_device_free</function>, free the memory allocated
+ for the IIO device.
+ </listitem>
+ </itemizedlist>
+
+ <sect2 id="iioattr"> <title> IIO device sysfs interface </title>
+ <para>
+ Attributes are sysfs files used to expose chip info and also allowing
+ applications to set various configuration parameters. For device
+ with index X, attributes can be found under
+ <filename>/sys/bus/iio/iio:deviceX/ </filename> directory.
+ Common attributes are:
+ <itemizedlist>
+ <listitem><filename>name</filename>, description of the physical
+ chip.
+ </listitem>
+ <listitem><filename>dev</filename>, shows the major:minor pair
+ associated with <filename>/dev/iio:deviceX</filename> node.
+ </listitem>
+ <listitem><filename>sampling_frequency_available</filename>,
+ available discrete set of sampling frequency values for
+ device.
+ </listitem>
+ </itemizedlist>
+ Available standard attributes for IIO devices are described in the
+ <filename>Documentation/ABI/testing/sysfs-bus-iio </filename> file
+ in the Linux kernel sources.
+ </para>
+ </sect2>
+ <sect2 id="iiochannel"> <title> IIO device channels </title>
+!Finclude/linux/iio/iio.h iio_chan_spec structure.
+ <para>
+ An IIO device channel is a representation of a data channel. An
+ IIO device can have one or multiple channels. For example:
+ <itemizedlist>
+ <listitem>
+ a thermometer sensor has one channel representing the
+ temperature measurement.
+ </listitem>
+ <listitem>
+ a light sensor with two channels indicating the measurements in
+ the visible and infrared spectrum.
+ </listitem>
+ <listitem>
+ an accelerometer can have up to 3 channels representing
+ acceleration on X, Y and Z axes.
+ </listitem>
+ </itemizedlist>
+ An IIO channel is described by the <type> struct iio_chan_spec
+ </type>. A thermometer driver for the temperature sensor in the
+ example above would have to describe its channel as follows:
+ <programlisting>
+ static const struct iio_chan_spec temp_channel[] = {
+ {
+ .type = IIO_TEMP,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ },
+ };
+
+ </programlisting>
+ Channel sysfs attributes exposed to userspace are specified in
+ the form of <emphasis>bitmasks</emphasis>. Depending on their
+ shared info, attributes can be set in one of the following masks:
+ <itemizedlist>
+ <listitem><emphasis>info_mask_separate</emphasis>, attributes will
+ be specific to this channel</listitem>
+ <listitem><emphasis>info_mask_shared_by_type</emphasis>,
+ attributes are shared by all channels of the same type</listitem>
+ <listitem><emphasis>info_mask_shared_by_dir</emphasis>, attributes
+ are shared by all channels of the same direction </listitem>
+ <listitem><emphasis>info_mask_shared_by_all</emphasis>,
+ attributes are shared by all channels</listitem>
+ </itemizedlist>
+ When there are multiple data channels per sensor type there are two
+ ways to distinguish between them:
+ <itemizedlist>
+ <listitem> set <emphasis> .modified</emphasis> field of <type>
+ iio_chan_spec</type> to 1. Modifiers are specified using
+ <emphasis>.channel2</emphasis> field of the same
+ <type>iio_chan_spec</type> structure and are used to indicate a
+ physically unique characteristic of the channel such as its direction
+ or spectral response. For example, a light sensor can have two channels,
+ one for infrared light and one for both infrared and visible light.
+ </listitem>
+ <listitem> set <emphasis>.indexed </emphasis> field of
+ <type>iio_chan_spec</type> to 1. In this case the channel is
+ simply another instance with an index specified by the
+ <emphasis>.channel</emphasis> field.
+ </listitem>
+ </itemizedlist>
+ Here is how we can make use of the channel's modifiers:
+ <programlisting>
+ static const struct iio_chan_spec light_channels[] = {
+ {
+ .type = IIO_INTENSITY,
+ .modified = 1,
+ .channel2 = IIO_MOD_LIGHT_IR,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ },
+ {
+ .type = IIO_INTENSITY,
+ .modified = 1,
+ .channel2 = IIO_MOD_LIGHT_BOTH,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ },
+ {
+ .type = IIO_LIGHT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ },
+
+ }
+ </programlisting>
+ This channel's definition will generate two separate sysfs files
+ for raw data retrieval:
+ <itemizedlist>
+ <listitem>
+ <filename>/sys/bus/iio/iio:deviceX/in_intensity_ir_raw</filename>
+ </listitem>
+ <listitem>
+ <filename>/sys/bus/iio/iio:deviceX/in_intensity_both_raw</filename>
+ </listitem>
+ </itemizedlist>
+ one file for processed data:
+ <itemizedlist>
+ <listitem>
+ <filename>/sys/bus/iio/iio:deviceX/in_illuminance_input
+ </filename>
+ </listitem>
+ </itemizedlist>
+ and one shared sysfs file for sampling frequency:
+ <itemizedlist>
+ <listitem>
+ <filename>/sys/bus/iio/iio:deviceX/in_intensity_sampling_frequency.
+ </filename>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Here is how we can make use of the channel's indexing:
+ <programlisting>
+ static const struct iio_chan_spec light_channels[] = {
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ },
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ },
+ }
+ </programlisting>
+ This will generate two separate attributes files for raw data
+ retrieval:
+ <itemizedlist>
+ <listitem>
+ <filename>/sys/bus/iio/devices/iio:deviceX/in_voltage0_raw</filename>,
+ representing voltage measurement for channel 0.
+ </listitem>
+ <listitem>
+ <filename>/sys/bus/iio/devices/iio:deviceX/in_voltage1_raw</filename>,
+ representing voltage measurement for channel 1.
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="iiobuffer"> <title> Industrial I/O buffers </title>
+!Finclude/linux/iio/buffer.h iio_buffer
+!Edrivers/iio/industrialio-buffer.c
+
+ <para>
+ The Industrial I/O core offers a way for continuous data capture
+ based on a trigger source. Multiple data channels can be read at once
+ from <filename>/dev/iio:deviceX</filename> character device node,
+ thus reducing the CPU load.
+ </para>
+
+ <sect2 id="iiobuffersysfs">
+ <title>IIO buffer sysfs interface </title>
+ <para>
+ An IIO buffer has an associated attributes directory under <filename>
+ /sys/bus/iio/iio:deviceX/buffer/</filename>. Here are the existing
+ attributes:
+ <itemizedlist>
+ <listitem>
+ <emphasis>length</emphasis>, number of data samples contained by the
+ buffer.
+ </listitem>
+ <listitem>
+ <emphasis>enable</emphasis>, activate buffer capture.
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect2>
+ <sect2 id="iiobuffersetup"> <title> IIO buffer setup </title>
+ <para>The meta information associated with a channel reading
+ placed in a buffer is called a <emphasis> scan element </emphasis>.
+ The important bits configuring scan elements are exposed to
+ userspace applications via the <filename>
+ /sys/bus/iio/iio:deviceX/scan_elements/</filename> directory. This
+ file contains attributes of the following form:
+ <itemizedlist>
+ <listitem><emphasis>enable</emphasis>, used for enabling a channel.
+ If and only if its attribute is non zero, then a triggered capture
+ will contain data samples for this channel.
+ </listitem>
+ <listitem><emphasis>type</emphasis>, description of the scan element
+ data storage within the buffer and hence the form in which it is
+ read from user space. Format is <emphasis>
+ [be|le]:[s|u]bits/storagebitsXrepeat[>>shift] </emphasis>.
+ <itemizedlist>
+ <listitem> <emphasis>be</emphasis> or <emphasis>le</emphasis> specifies
+ big or little endian.
+ </listitem>
+ <listitem>
+ <emphasis>s </emphasis>or <emphasis>u</emphasis> specifies if
+ signed (2's complement) or unsigned.
+ </listitem>
+ <listitem><emphasis>bits</emphasis> is the number of bits of data
+ </listitem>
+ <listitem><emphasis>storagebits</emphasis> is the space (after padding)
+ that it occupies in the buffer.
+ </listitem>
+ <listitem>
+ <emphasis>shift</emphasis> if specified, is the shift that needs
+ to be a applied prior to masking out unused bits
+ </listitem>
+ <listitem>
+ <emphasis>repeat</emphasis>, specifies the number of real/storage bits
+ repetitions. When the repeat element is 0 or 1, then the repeat
+ value is omitted.
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ For example, a driver for a 3-axis accelerometer with 12 bit
+ resolution where data is stored in two 8-bits registers as
+ follows:
+ <programlisting>
+ 7 6 5 4 3 2 1 0
+ +---+---+---+---+---+---+---+---+
+ |D3 |D2 |D1 |D0 | X | X | X | X | (LOW byte, address 0x06)
+ +---+---+---+---+---+---+---+---+
+
+ 7 6 5 4 3 2 1 0
+ +---+---+---+---+---+---+---+---+
+ |D11|D10|D9 |D8 |D7 |D6 |D5 |D4 | (HIGH byte, address 0x07)
+ +---+---+---+---+---+---+---+---+
+ </programlisting>
+
+ will have the following scan element type for each axis:
+ <programlisting>
+ $ cat /sys/bus/iio/devices/iio:device0/scan_elements/in_accel_y_type
+ le:s12/16>>4
+ </programlisting>
+ The userspace applications will interpret data samples read from buffer
+ as two byte little endian signed data, that needs a 4 bits right
+ shift before masking out the only 12 valid bits of real data.
+ </para>
+ <para>
+ For implementing buffer support a driver should initialize the following
+ fields in <type>iio_chan_spec</type> definition:
+ <programlisting>
+ struct iio_chan_spec {
+ /* other members */
+ int scan_index
+ struct {
+ char sign;
+ u8 realbits;
+ u8 storagebits;
+ u8 shift;
+ u8 repeat;
+ enum iio_endian endianness;
+ } scan_type;
+ };
+ </programlisting>
+ The driver implementing the accelerometer described above will
+ have the following channel definition:
+ <programlisting>
+ struct struct iio_chan_spec accel_channels[] = {
+ {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ /* other stuff here */
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 12,
+ .storgebits = 16,
+ .shift = 4,
+ .endianness = IIO_LE,
+ },
+ }
+ /* similar for Y and Z axis */
+ }
+ </programlisting>
+ </para>
+ <para>
+ Here <emphasis> scan_index </emphasis> defines the relative order in which
+ the enabled channels are placed inside the buffer. Channels with a lower
+ scan_index will be placed before channels with a higher index. Each
+ channel needs to have a unique scan_index.
+ </para>
+ <para>
+ It is important to realize that the scan_index does not define the
+ absolute position in the buffer. E.g. a channel with the scan_index = 3
+ will not be at offset 3 bytes or 3 words, but rather will be placed in the
+ buffer after any channel with a scan_index lower than 3 and before
+ any channel with a scan_index larger than 3.
+ Furthermore the scan indices do not have to be consecutive. E.g. A
+ channel spec array that defines 3 channels with the indices 1, 2 and 3 is
+ just as valid as a channel spec that uses the indices 100, 200, 300. The
+ relative order of the channels will be the same.
+ </para>
+ <para>
+ Setting scan_index to -1 can be used to indicate that the specific
+ channel does not support buffered capture. In this case no entries will
+ be created for the channel in the scan_elements directory.
+ </para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="iiotrigger"> <title> Industrial I/O triggers </title>
+!Finclude/linux/iio/trigger.h iio_trigger
+!Edrivers/iio/industrialio-trigger.c
+ <para>
+ In many situations it is useful for a driver to be able to
+ capture data based on some external event (trigger) as opposed
+ to periodically polling for data. An IIO trigger can be provided
+ by a device driver that also has an IIO device based on hardware
+ generated events (e.g. data ready or threshold exceeded) or
+ provided by a separate driver from an independent interrupt
+ source (e.g. GPIO line connected to some external system, timer
+ interrupt or user space reading a specific file in sysfs). A
+ trigger may initialize data capture for a number of sensors and
+ also it may be completely unrelated to the sensor itself.
+ </para>
+
+ <sect2 id="iiotrigsysfs"> <title> IIO trigger sysfs interface </title>
+ There are two locations in sysfs related to triggers:
+ <itemizedlist>
+ <listitem><filename>/sys/bus/iio/devices/triggerY</filename>,
+ this file is created once an IIO triggered is registered with
+ the IIO core and corresponds to trigger with index Y. Because
+ triggers can be very different depending on type there are few
+ standard attributes that we can describe here:
+ <itemizedlist>
+ <listitem>
+ <emphasis>name</emphasis>, trigger name that can be later
+ used to for association with a device.
+ </listitem>
+ <listitem>
+ <emphasis>sampling_frequency</emphasis>, some timer based
+ triggers use this attribute to specify the frequency for
+ trigger calls.
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem>
+ <filename>/sys/bus/iio/devices/iio:deviceX/trigger/</filename>, this
+ directory is created once the device supports a triggered
+ buffer. We can associate a trigger with our device by writing
+ trigger's name in the<filename>current_trigger</filename> file.
+ </listitem>
+ </itemizedlist>
+ </sect2>
+
+ <sect2 id="iiotrigattr"> <title> IIO trigger setup</title>
+
+ <para>
+ Let's see a simple example of how to setup a trigger to be used
+ by a driver.
+
+ <programlisting>
+ struct iio_trigger_ops trigger_ops = {
+ .set_trigger_state = sample_trigger_state,
+ .validate_device = sample_validate_device,
+ }
+
+ struct iio_trigger *trig;
+
+ /* first, allocate memory for our trigger */
+ trig = iio_trigger_alloc(dev, "trig-%s-%d", name, idx);
+
+ /* setup trigger operations field */
+ trig->ops = &amp;trigger_ops;
+
+ /* now register the trigger with the IIO core */
+ iio_trigger_register(trig);
+ </programlisting>
+ </para>
+ </sect2>
+
+ <sect2 id="iiotrigsetup"> <title> IIO trigger ops</title>
+!Finclude/linux/iio/trigger.h iio_trigger_ops
+ <para>
+ Notice that a trigger has a set of operations attached:
+ <itemizedlist>
+ <listitem>
+ <function>set_trigger_state</function>, switch the trigger on/off
+ on demand.
+ </listitem>
+ <listitem>
+ <function>validate_device</function>, function to validate the
+ device when the current trigger gets changed.
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect2>
+ </sect1>
+ <sect1 id="iiotriggered_buffer">
+ <title> Industrial I/O triggered buffers </title>
+ <para>
+ Now that we know what buffers and triggers are let's see how they
+ work together.
+ </para>
+ <sect2 id="iiotrigbufsetup"> <title> IIO triggered buffer setup</title>
+!Edrivers/iio/industrialio-triggered-buffer.c
+!Finclude/linux/iio/iio.h iio_buffer_setup_ops
+
+
+ <para>
+ A typical triggered buffer setup looks like this:
+ <programlisting>
+ const struct iio_buffer_setup_ops sensor_buffer_setup_ops = {
+ .preenable = sensor_buffer_preenable,
+ .postenable = sensor_buffer_postenable,
+ .postdisable = sensor_buffer_postdisable,
+ .predisable = sensor_buffer_predisable,
+ };
+
+ irqreturn_t sensor_iio_pollfunc(int irq, void *p)
+ {
+ pf->timestamp = iio_get_time_ns();
+ return IRQ_WAKE_THREAD;
+ }
+
+ irqreturn_t sensor_trigger_handler(int irq, void *p)
+ {
+ u16 buf[8];
+
+ /* read data for each active channel */
+ for_each_set_bit(bit, active_scan_mask, masklength)
+ buf[i++] = sensor_get_data(bit)
+
+ iio_push_to_buffers_with_timestamp(indio_dev, buffer, timestamp);
+
+ iio_trigger_notify_done(trigger);
+ }
+
+ /* setup triggered buffer, usually in probe function */
+ iio_triggered_buffer_setup(indio_dev, sensor_iio_polfunc,
+ sensor_trigger_handler,
+ sensor_buffer_setup_ops);
+ </programlisting>
+ </para>
+ The important things to notice here are:
+ <itemizedlist>
+ <listitem><function> iio_buffer_setup_ops</function>, the buffer setup
+ functions to be called at predefined points in buffer configuration
+ sequence (e.g. before enable, after disable). If not specified, the
+ IIO core uses the default <type>iio_triggered_buffer_setup_ops</type>.
+ </listitem>
+ <listitem><function>sensor_iio_pollfunc</function>, the function that
+ will be used as top half of poll function. It should do as little
+ processing as possible, because it runs in interrupt context. The most
+ common operation is recording of the current timestamp and for this reason
+ one can use the IIO core defined <function>iio_pollfunc_store_time
+ </function> function.
+ </listitem>
+ <listitem><function>sensor_trigger_handler</function>, the function that
+ will be used as bottom half of the poll function. This runs in the
+ context of a kernel thread and all the processing takes place here.
+ It usually reads data from the device and stores it in the internal
+ buffer together with the timestamp recorded in the top half.
+ </listitem>
+ </itemizedlist>
+ </sect2>
+ </sect1>
+ </chapter>
+ <chapter id='iioresources'>
+ <title> Resources </title>
+ IIO core may change during time so the best documentation to read is the
+ source code. There are several locations where you should look:
+ <itemizedlist>
+ <listitem>
+ <filename>drivers/iio/</filename>, contains the IIO core plus
+ and directories for each sensor type (e.g. accel, magnetometer,
+ etc.)
+ </listitem>
+ <listitem>
+ <filename>include/linux/iio/</filename>, contains the header
+ files, nice to read for the internal kernel interfaces.
+ </listitem>
+ <listitem>
+ <filename>include/uapi/linux/iio/</filename>, contains files to be
+ used by user space applications.
+ </listitem>
+ <listitem>
+ <filename>tools/iio/</filename>, contains tools for rapidly
+ testing buffers, events and device creation.
+ </listitem>
+ <listitem>
+ <filename>drivers/staging/iio/</filename>, contains code for some
+ drivers or experimental features that are not yet mature enough
+ to be moved out.
+ </listitem>
+ </itemizedlist>
+ <para>
+ Besides the code, there are some good online documentation sources:
+ <itemizedlist>
+ <listitem>
+ <ulink url="http://marc.info/?l=linux-iio"> Industrial I/O mailing
+ list </ulink>
+ </listitem>
+ <listitem>
+ <ulink url="http://wiki.analog.com/software/linux/docs/iio/iio">
+ Analog Device IIO wiki page </ulink>
+ </listitem>
+ <listitem>
+ <ulink url="https://fosdem.org/2015/schedule/event/iiosdr/">
+ Using the Linux IIO framework for SDR, Lars-Peter Clausen's
+ presentation at FOSDEM </ulink>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </chapter>
+</book>
+
+<!--
+vim: softtabstop=2:shiftwidth=2:expandtab:textwidth=72
+-->
--
1.9.1

2015-08-03 08:14:24

by Lars-Peter Clausen

[permalink] [raw]
Subject: Re: [PATCH v4] DocBook: Add initial documentation for IIO

On 07/31/2015 04:04 PM, Daniel Baluta wrote:
> This is intended to help developers faster find their way
> inside the Industrial I/O core and reduce time spent on IIO
> drivers development.
>
> Signed-off-by: Daniel Baluta <[email protected]>

Looks good to me. Thanks again.

Reviewed-by: Lars-Peter Clausen <[email protected]>

2015-08-03 08:29:59

by Crt Mori

[permalink] [raw]
Subject: Re: [PATCH v4] DocBook: Add initial documentation for IIO

On 3 August 2015 at 10:14, Lars-Peter Clausen <[email protected]> wrote:
> On 07/31/2015 04:04 PM, Daniel Baluta wrote:
>> This is intended to help developers faster find their way
>> inside the Industrial I/O core and reduce time spent on IIO
>> drivers development.
>>
>> Signed-off-by: Daniel Baluta <[email protected]>
>
> Looks good to me. Thanks again.
>
> Reviewed-by: Lars-Peter Clausen <[email protected]>
Acked-by: Crt Mori <[email protected]>

2015-08-03 09:24:08

by Peter Meerwald-Stadler

[permalink] [raw]
Subject: Re: [PATCH v4] DocBook: Add initial documentation for IIO

On Fri, 31 Jul 2015, Daniel Baluta wrote:

> This is intended to help developers faster find their way
> inside the Industrial I/O core and reduce time spent on IIO
> drivers development.

comments inline below

> Signed-off-by: Daniel Baluta <[email protected]>
> ---
> Documentation/DocBook/Makefile | 2 +-
> Documentation/DocBook/iio.tmpl | 702 +++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 703 insertions(+), 1 deletion(-)
> create mode 100644 Documentation/DocBook/iio.tmpl
>
> diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
> index b6a6a2e..9e08606 100644
> --- a/Documentation/DocBook/Makefile
> +++ b/Documentation/DocBook/Makefile
> @@ -15,7 +15,7 @@ DOCBOOKS := z8530book.xml device-drivers.xml \
> 80211.xml debugobjects.xml sh.xml regulator.xml \
> alsa-driver-api.xml writing-an-alsa-driver.xml \
> tracepoint.xml drm.xml media_api.xml w1.xml \
> - writing_musb_glue_layer.xml crypto-API.xml
> + writing_musb_glue_layer.xml crypto-API.xml iio.xml
>
> include Documentation/DocBook/media/Makefile
>
> diff --git a/Documentation/DocBook/iio.tmpl b/Documentation/DocBook/iio.tmpl
> new file mode 100644
> index 0000000..b39b3e9
> --- /dev/null
> +++ b/Documentation/DocBook/iio.tmpl
> @@ -0,0 +1,702 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
> + "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
> +
> +<book id="iioid">
> + <bookinfo>
> + <title>Industrial I/O driver developer's guide </title>
> +
> + <authorgroup>
> + <author>
> + <firstname>Daniel</firstname>
> + <surname>Baluta</surname>
> + <affiliation>
> + <address>
> + <email>[email protected]</email>
> + </address>
> + </affiliation>
> + </author>
> + </authorgroup>
> +
> + <copyright>
> + <year>2015</year>
> + <holder>Intel Corporation</holder>
> + </copyright>
> +
> + <legalnotice>
> + <para>
> + This documentation is free software; you can redistribute
> + it and/or modify it under the terms of the GNU General Public
> + License version 2.
> + </para>
> + </legalnotice>
> + </bookinfo>
> +
> + <toc></toc>
> +
> + <chapter id="intro">
> + <title>Introduction</title>
> + <para>
> + The main purpose of the Industrial I/O subsystem (IIO) is to provide
> + support for devices that in some sense perform either analog-to-digital
> + conversion (ADC) or digital-to-analog conversion (DAC) or both. The aim
> + is to fill the gap between the somewhat similar hwmon and input
> + subsystems.
> + Hwmon is directed at low sample rate sensors used to monitor and
> + control the system itself, like fan speed control or temperature
> + measurement. Input is, as its name suggests, focused on human interaction
> + input devices (keyboard, mouse, touchscreen). In some cases there is
> + considerable overlap between these and IIO.
> + </para>
> + <para>
> + Devices that fall into this category include:
> + <itemizedlist>
> + <listitem>
> + analog to digital converters (ADCs)
> + </listitem>
> + <listitem>
> + accelerometers
> + </listitem>
> + <listitem>
> + capacitance to digital converters (CDCs)
> + </listitem>
> + <listitem>
> + digital to analog converters (DACs)
> + </listitem>
> + <listitem>
> + gyroscopes
> + </listitem>
> + <listitem>
> + inertial measurement units (IMUs)
> + </listitem>
> + <listitem>
> + color and light sensors
> + </listitem>
> + <listitem>
> + magnetometers
> + </listitem>
> + <listitem>
> + pressure sensors
> + </listitem>
> + <listitem>
> + proximity sensors
> + </listitem>
> + <listitem>
> + temperature sensors
> + </listitem>
> + </itemizedlist>
> + Usually these sensors are connected via SPI or I2C. A common use case of the
> + sensors devices is to have combined functionality (e.g. light plus proximity

sorsor devices

> + sensor).
> + </para>
> + </chapter>
> + <chapter id='iiosubsys'>
> + <title>Industrial I/O core</title>
> + <para>
> + The Industrial I/O core offers:
> + <itemizedlist>
> + <listitem>
> + a unified framework for writing drivers for many different types of
> + embedded sensors.
> + </listitem>
> + <listitem>
> + a standard interface to user space applications manipulating sensors.
> + </listitem>
> + </itemizedlist>
> + The implementation can be found under <filename>
> + drivers/iio/industrialio-*</filename>
> + </para>
> + <sect1 id="iiodevice">
> + <title> Industrial I/O devices </title>

extra spaces after/before tag, here and elsewhere

> +
> +!Finclude/linux/iio/iio.h iio_dev
> +!Fdrivers/iio/industrialio-core.c iio_device_alloc
> +!Fdrivers/iio/industrialio-core.c iio_device_free
> +!Fdrivers/iio/industrialio-core.c iio_device_register
> +!Fdrivers/iio/industrialio-core.c iio_device_unregister
> +
> + <para>
> + An IIO device usually corresponds to a single hardware sensor and it
> + provides all the information needed by a driver handling a device.
> + Let's first have a look at the functionality embedded in an IIO
> + device then we will show how a device driver makes use of an IIO
> + device.
> + </para>
> + <para>
> + There are two ways for a user space application to interact
> + with an IIO driver.
> + <itemizedlist>
> + <listitem>
> + <filename>/sys/bus/iio/iio:deviceX/</filename>, this
> + represents a hardware sensor and groups together the data
> + channels of the same chip.
> + </listitem>
> + <listitem>
> + <filename>/dev/iio:deviceX</filename>, character device node
> + interface used for faster data transfer and for events information

maybe refer to buffered data transfer?

> + retrieval.
> + </listitem>
> + </itemizedlist>
> + </para>
> + A typical IIO driver will register itself as an I2C or SPI driver and will
> + create two routines, <function> probe </function> and <function> remove
> + </function>. At <function>probe</function>:
> + <itemizedlist>
> + <listitem>call <function>iio_device_alloc</function>, which allocates memory
> + for an IIO device.
> + </listitem>
> + <listitem> initialize IIO device fields with driver specific information
> + (e.g. device name, device channels).
> + </listitem>
> + <listitem>call <function> iio_device_register</function>, this registers the
> + device with the IIO core. After this call the device is ready to accept
> + requests from user space applications.
> + </listitem>
> + </itemizedlist>
> + At <function>remove</function>, we free the resources allocated in
> + <function>probe</function> in reverse order:
> + <itemizedlist>
> + <listitem><function>iio_device_unregister</function>, unregister the device
> + from the IIO core.
> + </listitem>
> + <listitem><function>iio_device_free</function>, free the memory allocated
> + for the IIO device.
> + </listitem>
> + </itemizedlist>
> +
> + <sect2 id="iioattr"> <title> IIO device sysfs interface </title>
> + <para>
> + Attributes are sysfs files used to expose chip info and also allowing
> + applications to set various configuration parameters. For device
> + with index X, attributes can be found under
> + <filename>/sys/bus/iio/iio:deviceX/ </filename> directory.
> + Common attributes are:
> + <itemizedlist>
> + <listitem><filename>name</filename>, description of the physical
> + chip.
> + </listitem>
> + <listitem><filename>dev</filename>, shows the major:minor pair
> + associated with <filename>/dev/iio:deviceX</filename> node.
> + </listitem>
> + <listitem><filename>sampling_frequency_available</filename>,
> + available discrete set of sampling frequency values for

sampling_frequency is rather specific and not found for all devices;
it may also appear under events/

> + device.
> + </listitem>
> + </itemizedlist>
> + Available standard attributes for IIO devices are described in the
> + <filename>Documentation/ABI/testing/sysfs-bus-iio </filename> file
> + in the Linux kernel sources.
> + </para>
> + </sect2>
> + <sect2 id="iiochannel"> <title> IIO device channels </title>
> +!Finclude/linux/iio/iio.h iio_chan_spec structure.
> + <para>
> + An IIO device channel is a representation of a data channel. An
> + IIO device can have one or multiple channels. For example:
> + <itemizedlist>
> + <listitem>
> + a thermometer sensor has one channel representing the
> + temperature measurement.
> + </listitem>
> + <listitem>
> + a light sensor with two channels indicating the measurements in
> + the visible and infrared spectrum.
> + </listitem>
> + <listitem>
> + an accelerometer can have up to 3 channels representing
> + acceleration on X, Y and Z axes.
> + </listitem>
> + </itemizedlist>
> + An IIO channel is described by the <type> struct iio_chan_spec
> + </type>. A thermometer driver for the temperature sensor in the
> + example above would have to describe its channel as follows:
> + <programlisting>
> + static const struct iio_chan_spec temp_channel[] = {
> + {
> + .type = IIO_TEMP,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),

_RAW vs. _PROCESSED?

> + },
> + };
> +
> + </programlisting>
> + Channel sysfs attributes exposed to userspace are specified in
> + the form of <emphasis>bitmasks</emphasis>. Depending on their
> + shared info, attributes can be set in one of the following masks:
> + <itemizedlist>
> + <listitem><emphasis>info_mask_separate</emphasis>, attributes will
> + be specific to this channel</listitem>
> + <listitem><emphasis>info_mask_shared_by_type</emphasis>,
> + attributes are shared by all channels of the same type</listitem>
> + <listitem><emphasis>info_mask_shared_by_dir</emphasis>, attributes
> + are shared by all channels of the same direction </listitem>
> + <listitem><emphasis>info_mask_shared_by_all</emphasis>,
> + attributes are shared by all channels</listitem>
> + </itemizedlist>
> + When there are multiple data channels per sensor type there are two

per channel type?

> + ways to distinguish between them:
> + <itemizedlist>
> + <listitem> set <emphasis> .modified</emphasis> field of <type>
> + iio_chan_spec</type> to 1. Modifiers are specified using
> + <emphasis>.channel2</emphasis> field of the same
> + <type>iio_chan_spec</type> structure and are used to indicate a
> + physically unique characteristic of the channel such as its direction
> + or spectral response. For example, a light sensor can have two channels,
> + one for infrared light and one for both infrared and visible light.
> + </listitem>
> + <listitem> set <emphasis>.indexed </emphasis> field of
> + <type>iio_chan_spec</type> to 1. In this case the channel is
> + simply another instance with an index specified by the
> + <emphasis>.channel</emphasis> field.
> + </listitem>
> + </itemizedlist>
> + Here is how we can make use of the channel's modifiers:
> + <programlisting>
> + static const struct iio_chan_spec light_channels[] = {
> + {
> + .type = IIO_INTENSITY,
> + .modified = 1,
> + .channel2 = IIO_MOD_LIGHT_IR,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> + .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
> + },
> + {
> + .type = IIO_INTENSITY,
> + .modified = 1,
> + .channel2 = IIO_MOD_LIGHT_BOTH,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> + .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
> + },
> + {
> + .type = IIO_LIGHT,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
> + .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
> + },
> +
> + }
> + </programlisting>
> + This channel's definition will generate two separate sysfs files
> + for raw data retrieval:
> + <itemizedlist>
> + <listitem>
> + <filename>/sys/bus/iio/iio:deviceX/in_intensity_ir_raw</filename>
> + </listitem>
> + <listitem>
> + <filename>/sys/bus/iio/iio:deviceX/in_intensity_both_raw</filename>
> + </listitem>
> + </itemizedlist>
> + one file for processed data:
> + <itemizedlist>
> + <listitem>
> + <filename>/sys/bus/iio/iio:deviceX/in_illuminance_input
> + </filename>
> + </listitem>
> + </itemizedlist>
> + and one shared sysfs file for sampling frequency:

this is a bit of a corner case: why is there just one _sampling_frequency
channel? it could also have been named in_illuminance_sampling_frequency

> + <itemizedlist>
> + <listitem>
> + <filename>/sys/bus/iio/iio:deviceX/in_intensity_sampling_frequency.
> + </filename>
> + </listitem>
> + </itemizedlist>
> + </para>
> + <para>
> + Here is how we can make use of the channel's indexing:
> + <programlisting>
> + static const struct iio_chan_spec light_channels[] = {
> + {
> + .type = IIO_VOLTAGE,
> + .indexed = 1,
> + .channel = 0,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> + },
> + {
> + .type = IIO_VOLTAGE,
> + .indexed = 1,
> + .channel = 1,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> + },
> + }
> + </programlisting>
> + This will generate two separate attributes files for raw data
> + retrieval:
> + <itemizedlist>
> + <listitem>
> + <filename>/sys/bus/iio/devices/iio:deviceX/in_voltage0_raw</filename>,
> + representing voltage measurement for channel 0.
> + </listitem>
> + <listitem>
> + <filename>/sys/bus/iio/devices/iio:deviceX/in_voltage1_raw</filename>,
> + representing voltage measurement for channel 1.
> + </listitem>
> + </itemizedlist>
> + </para>
> + </sect2>
> + </sect1>
> +
> + <sect1 id="iiobuffer"> <title> Industrial I/O buffers </title>
> +!Finclude/linux/iio/buffer.h iio_buffer
> +!Edrivers/iio/industrialio-buffer.c
> +
> + <para>
> + The Industrial I/O core offers a way for continuous data capture
> + based on a trigger source. Multiple data channels can be read at once
> + from <filename>/dev/iio:deviceX</filename> character device node,
> + thus reducing the CPU load.
> + </para>
> +
> + <sect2 id="iiobuffersysfs">
> + <title>IIO buffer sysfs interface </title>
> + <para>
> + An IIO buffer has an associated attributes directory under <filename>
> + /sys/bus/iio/iio:deviceX/buffer/</filename>. Here are the existing
> + attributes:
> + <itemizedlist>
> + <listitem>
> + <emphasis>length</emphasis>, number of data samples contained by the
> + buffer.

wording is not very clean; length is is the buffer length/capacity, not
the number of samples currently in the buffer

> + </listitem>
> + <listitem>
> + <emphasis>enable</emphasis>, activate buffer capture.
> + </listitem>
> + </itemizedlist>
> + </para>
> + </sect2>
> + <sect2 id="iiobuffersetup"> <title> IIO buffer setup </title>
> + <para>The meta information associated with a channel reading
> + placed in a buffer is called a <emphasis> scan element </emphasis>.
> + The important bits configuring scan elements are exposed to
> + userspace applications via the <filename>
> + /sys/bus/iio/iio:deviceX/scan_elements/</filename> directory. This
> + file contains attributes of the following form:
> + <itemizedlist>
> + <listitem><emphasis>enable</emphasis>, used for enabling a channel.
> + If and only if its attribute is non zero, then a triggered capture
> + will contain data samples for this channel.
> + </listitem>
> + <listitem><emphasis>type</emphasis>, description of the scan element
> + data storage within the buffer and hence the form in which it is
> + read from user space. Format is <emphasis>
> + [be|le]:[s|u]bits/storagebitsXrepeat[>>shift] </emphasis>.
> + <itemizedlist>
> + <listitem> <emphasis>be</emphasis> or <emphasis>le</emphasis> specifies
> + big or little endian.
> + </listitem>
> + <listitem>
> + <emphasis>s </emphasis>or <emphasis>u</emphasis> specifies if
> + signed (2's complement) or unsigned.
> + </listitem>
> + <listitem><emphasis>bits</emphasis> is the number of bits of data

number of data bits

> + </listitem>
> + <listitem><emphasis>storagebits</emphasis> is the space (after padding)
> + that it occupies in the buffer.

is the number of bits (after padding) that...

> + </listitem>
> + <listitem>
> + <emphasis>shift</emphasis> if specified, is the shift that needs
> + to be a applied prior to masking out unused bits

that needs to be applied -- delete a

> + </listitem>
> + <listitem>
> + <emphasis>repeat</emphasis>, specifies the number of real/storage bits

what is real? -- undefined at this point;
"real/storage" doesn't make it clear if the padded or unpadded data bits
are repeated -- I think the later
maybe: "specifies the number of unpadded data repetitions"

> + repetitions. When the repeat element is 0 or 1, then the repeat
> + value is omitted.
> + </listitem>
> + </itemizedlist>
> + </listitem>
> + </itemizedlist>
> + For example, a driver for a 3-axis accelerometer with 12 bit
> + resolution where data is stored in two 8-bits registers as
> + follows:
> + <programlisting>
> + 7 6 5 4 3 2 1 0
> + +---+---+---+---+---+---+---+---+
> + |D3 |D2 |D1 |D0 | X | X | X | X | (LOW byte, address 0x06)
> + +---+---+---+---+---+---+---+---+
> +
> + 7 6 5 4 3 2 1 0
> + +---+---+---+---+---+---+---+---+
> + |D11|D10|D9 |D8 |D7 |D6 |D5 |D4 | (HIGH byte, address 0x07)
> + +---+---+---+---+---+---+---+---+
> + </programlisting>
> +
> + will have the following scan element type for each axis:
> + <programlisting>
> + $ cat /sys/bus/iio/devices/iio:device0/scan_elements/in_accel_y_type
> + le:s12/16>>4
> + </programlisting>
> + The userspace applications will interpret data samples read from buffer

user space -- inconsistent
maybe "A user space application will..."
the buffer -- the

> + as two byte little endian signed data, that needs a 4 bits right
> + shift before masking out the only 12 valid bits of real data.

masking out the 12 valid bits of data

> + </para>
> + <para>
> + For implementing buffer support a driver should initialize the following
> + fields in <type>iio_chan_spec</type> definition:
> + <programlisting>
> + struct iio_chan_spec {
> + /* other members */
> + int scan_index
> + struct {
> + char sign;
> + u8 realbits;
> + u8 storagebits;
> + u8 shift;
> + u8 repeat;
> + enum iio_endian endianness;
> + } scan_type;
> + };
> + </programlisting>
> + The driver implementing the accelerometer described above will
> + have the following channel definition:
> + <programlisting>
> + struct struct iio_chan_spec accel_channels[] = {
> + {
> + .type = IIO_ACCEL,
> + .modified = 1,
> + .channel2 = IIO_MOD_X,
> + /* other stuff here */
> + .scan_index = 0,
> + .scan_type = {
> + .sign = 's',
> + .realbits = 12,
> + .storgebits = 16,
> + .shift = 4,
> + .endianness = IIO_LE,
> + },
> + }
> + /* similar for Y and Z axis */

two spaces before Z
maybe: "similar for Y (with channel2 = IIO_MOD_Y, scan_index = 1) and Z
(with channel2 = IIO_MOD_Z, scan_index=2) axis"

> + }
> + </programlisting>
> + </para>
> + <para>
> + Here <emphasis> scan_index </emphasis> defines the relative order in which

why relative?
it is simply the order

> + the enabled channels are placed inside the buffer. Channels with a lower
> + scan_index will be placed before channels with a higher index. Each
> + channel needs to have a unique scan_index.
> + </para>
> + <para>
> + It is important to realize that the scan_index does not define the
> + absolute position in the buffer. E.g. a channel with the scan_index = 3
> + will not be at offset 3 bytes or 3 words, but rather will be placed in the
> + buffer after any channel with a scan_index lower than 3 and before
> + any channel with a scan_index larger than 3.

I'd drop the paragraph above, this is just confusing; better mention that
there are padding rules (e.g. for the timestamp channel) and it follows
that the scan_index is not a byte offset into the buffer

> + Furthermore the scan indices do not have to be consecutive. E.g. A
> + channel spec array that defines 3 channels with the indices 1, 2 and 3 is
> + just as valid as a channel spec that uses the indices 100, 200, 300. The
> + relative order of the channels will be the same.
> + </para>
> + <para>
> + Setting scan_index to -1 can be used to indicate that the specific
> + channel does not support buffered capture. In this case no entries will
> + be created for the channel in the scan_elements directory.
> + </para>
> + </sect2>
> + </sect1>
> +
> + <sect1 id="iiotrigger"> <title> Industrial I/O triggers </title>
> +!Finclude/linux/iio/trigger.h iio_trigger
> +!Edrivers/iio/industrialio-trigger.c
> + <para>
> + In many situations it is useful for a driver to be able to
> + capture data based on some external event (trigger) as opposed
> + to periodically polling for data. An IIO trigger can be provided
> + by a device driver that also has an IIO device based on hardware
> + generated events (e.g. data ready or threshold exceeded) or
> + provided by a separate driver from an independent interrupt
> + source (e.g. GPIO line connected to some external system, timer
> + interrupt or user space reading a specific file in sysfs). A

writing a specific file

> + trigger may initialize data capture for a number of sensors and

initiate -- not initialize

> + also it may be completely unrelated to the sensor itself.
> + </para>
> +
> + <sect2 id="iiotrigsysfs"> <title> IIO trigger sysfs interface </title>
> + There are two locations in sysfs related to triggers:
> + <itemizedlist>
> + <listitem><filename>/sys/bus/iio/devices/triggerY</filename>,
> + this file is created once an IIO triggered is registered with

an IIO trigger

> + the IIO core and corresponds to trigger with index Y. Because
> + triggers can be very different depending on type there are few
> + standard attributes that we can describe here:
> + <itemizedlist>
> + <listitem>
> + <emphasis>name</emphasis>, trigger name that can be later
> + used to for association with a device.

used for association

> + </listitem>
> + <listitem>
> + <emphasis>sampling_frequency</emphasis>, some timer based
> + triggers use this attribute to specify the frequency for
> + trigger calls.
> + </listitem>
> + </itemizedlist>
> + </listitem>
> + <listitem>
> + <filename>/sys/bus/iio/devices/iio:deviceX/trigger/</filename>, this
> + directory is created once the device supports a triggered
> + buffer. We can associate a trigger with our device by writing
> + trigger's name in the<filename>current_trigger</filename> file.

the trigger's name -- the
the <filename> -- add space before tag

> + </listitem>
> + </itemizedlist>
> + </sect2>
> +
> + <sect2 id="iiotrigattr"> <title> IIO trigger setup</title>
> +
> + <para>
> + Let's see a simple example of how to setup a trigger to be used
> + by a driver.
> +
> + <programlisting>
> + struct iio_trigger_ops trigger_ops = {
> + .set_trigger_state = sample_trigger_state,
> + .validate_device = sample_validate_device,
> + }
> +
> + struct iio_trigger *trig;
> +
> + /* first, allocate memory for our trigger */
> + trig = iio_trigger_alloc(dev, "trig-%s-%d", name, idx);
> +
> + /* setup trigger operations field */
> + trig->ops = &amp;trigger_ops;
> +
> + /* now register the trigger with the IIO core */
> + iio_trigger_register(trig);
> + </programlisting>
> + </para>
> + </sect2>
> +
> + <sect2 id="iiotrigsetup"> <title> IIO trigger ops</title>
> +!Finclude/linux/iio/trigger.h iio_trigger_ops
> + <para>
> + Notice that a trigger has a set of operations attached:
> + <itemizedlist>
> + <listitem>
> + <function>set_trigger_state</function>, switch the trigger on/off
> + on demand.
> + </listitem>
> + <listitem>
> + <function>validate_device</function>, function to validate the
> + device when the current trigger gets changed.
> + </listitem>
> + </itemizedlist>
> + </para>
> + </sect2>
> + </sect1>
> + <sect1 id="iiotriggered_buffer">
> + <title> Industrial I/O triggered buffers </title>
> + <para>
> + Now that we know what buffers and triggers are let's see how they
> + work together.
> + </para>
> + <sect2 id="iiotrigbufsetup"> <title> IIO triggered buffer setup</title>
> +!Edrivers/iio/industrialio-triggered-buffer.c
> +!Finclude/linux/iio/iio.h iio_buffer_setup_ops
> +
> +
> + <para>
> + A typical triggered buffer setup looks like this:
> + <programlisting>
> + const struct iio_buffer_setup_ops sensor_buffer_setup_ops = {
> + .preenable = sensor_buffer_preenable,
> + .postenable = sensor_buffer_postenable,
> + .postdisable = sensor_buffer_postdisable,
> + .predisable = sensor_buffer_predisable,
> + };
> +
> + irqreturn_t sensor_iio_pollfunc(int irq, void *p)
> + {
> + pf->timestamp = iio_get_time_ns();
> + return IRQ_WAKE_THREAD;
> + }
> +
> + irqreturn_t sensor_trigger_handler(int irq, void *p)
> + {
> + u16 buf[8];

int i = 0;

> +
> + /* read data for each active channel */
> + for_each_set_bit(bit, active_scan_mask, masklength)
> + buf[i++] = sensor_get_data(bit)
> +
> + iio_push_to_buffers_with_timestamp(indio_dev, buffer, timestamp);

buf -- not buffer

> +
> + iio_trigger_notify_done(trigger);

return IRQ_HANDLED;

> + }
> +
> + /* setup triggered buffer, usually in probe function */
> + iio_triggered_buffer_setup(indio_dev, sensor_iio_polfunc,
> + sensor_trigger_handler,
> + sensor_buffer_setup_ops);
> + </programlisting>
> + </para>
> + The important things to notice here are:
> + <itemizedlist>
> + <listitem><function> iio_buffer_setup_ops</function>, the buffer setup
> + functions to be called at predefined points in buffer configuration

the buffer configuration -- the

> + sequence (e.g. before enable, after disable). If not specified, the
> + IIO core uses the default <type>iio_triggered_buffer_setup_ops</type>.
> + </listitem>
> + <listitem><function>sensor_iio_pollfunc</function>, the function that
> + will be used as top half of poll function. It should do as little
> + processing as possible, because it runs in interrupt context. The most
> + common operation is recording of the current timestamp and for this reason
> + one can use the IIO core defined <function>iio_pollfunc_store_time
> + </function> function.
> + </listitem>
> + <listitem><function>sensor_trigger_handler</function>, the function that
> + will be used as bottom half of the poll function. This runs in the
> + context of a kernel thread and all the processing takes place here.
> + It usually reads data from the device and stores it in the internal
> + buffer together with the timestamp recorded in the top half.
> + </listitem>
> + </itemizedlist>
> + </sect2>
> + </sect1>
> + </chapter>
> + <chapter id='iioresources'>
> + <title> Resources </title>
> + IIO core may change during time so the best documentation to read is the
> + source code. There are several locations where you should look:
> + <itemizedlist>
> + <listitem>
> + <filename>drivers/iio/</filename>, contains the IIO core plus
> + and directories for each sensor type (e.g. accel, magnetometer,
> + etc.)
> + </listitem>
> + <listitem>
> + <filename>include/linux/iio/</filename>, contains the header
> + files, nice to read for the internal kernel interfaces.
> + </listitem>
> + <listitem>
> + <filename>include/uapi/linux/iio/</filename>, contains files to be
> + used by user space applications.
> + </listitem>
> + <listitem>
> + <filename>tools/iio/</filename>, contains tools for rapidly
> + testing buffers, events and device creation.
> + </listitem>
> + <listitem>
> + <filename>drivers/staging/iio/</filename>, contains code for some
> + drivers or experimental features that are not yet mature enough
> + to be moved out.
> + </listitem>
> + </itemizedlist>
> + <para>
> + Besides the code, there are some good online documentation sources:
> + <itemizedlist>
> + <listitem>
> + <ulink url="http://marc.info/?l=linux-iio"> Industrial I/O mailing
> + list </ulink>
> + </listitem>
> + <listitem>
> + <ulink url="http://wiki.analog.com/software/linux/docs/iio/iio">
> + Analog Device IIO wiki page </ulink>
> + </listitem>
> + <listitem>
> + <ulink url="https://fosdem.org/2015/schedule/event/iiosdr/">
> + Using the Linux IIO framework for SDR, Lars-Peter Clausen's
> + presentation at FOSDEM </ulink>
> + </listitem>
> + </itemizedlist>
> + </para>
> + </chapter>
> +</book>
> +
> +<!--
> +vim: softtabstop=2:shiftwidth=2:expandtab:textwidth=72
> +-->
>

--

Peter Meerwald
+43-664-2444418 (mobile)

2015-08-04 08:59:41

by Daniel Baluta

[permalink] [raw]
Subject: Re: [PATCH v4] DocBook: Add initial documentation for IIO

On Mon, Aug 3, 2015 at 12:24 PM, Peter Meerwald <[email protected]> wrote:
> On Fri, 31 Jul 2015, Daniel Baluta wrote:
>
>> This is intended to help developers faster find their way
>> inside the Industrial I/O core and reduce time spent on IIO
>> drivers development.
>
> comments inline below

Hi Peter,

thanks a lot for your review. I've addressed most of your comments and
will send asap v5.

>
>> Signed-off-by: Daniel Baluta <[email protected]>
>> ---
>> Documentation/DocBook/Makefile | 2 +-
>> Documentation/DocBook/iio.tmpl | 702 +++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 703 insertions(+), 1 deletion(-)
>> create mode 100644 Documentation/DocBook/iio.tmpl
>>
>> diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
>> index b6a6a2e..9e08606 100644
>> --- a/Documentation/DocBook/Makefile
>> +++ b/Documentation/DocBook/Makefile
>> @@ -15,7 +15,7 @@ DOCBOOKS := z8530book.xml device-drivers.xml \
>> 80211.xml debugobjects.xml sh.xml regulator.xml \
>> alsa-driver-api.xml writing-an-alsa-driver.xml \
>> tracepoint.xml drm.xml media_api.xml w1.xml \
>> - writing_musb_glue_layer.xml crypto-API.xml
>> + writing_musb_glue_layer.xml crypto-API.xml iio.xml
>>
>> include Documentation/DocBook/media/Makefile
>>
>> diff --git a/Documentation/DocBook/iio.tmpl b/Documentation/DocBook/iio.tmpl
>> new file mode 100644
>> index 0000000..b39b3e9
>> --- /dev/null
>> +++ b/Documentation/DocBook/iio.tmpl
>> @@ -0,0 +1,702 @@
>> +<?xml version="1.0" encoding="UTF-8"?>
>> +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
>> + "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
>> +
>> +<book id="iioid">
>> + <bookinfo>
>> + <title>Industrial I/O driver developer's guide </title>
>> +
>> + <authorgroup>
>> + <author>
>> + <firstname>Daniel</firstname>
>> + <surname>Baluta</surname>
>> + <affiliation>
>> + <address>
>> + <email>[email protected]</email>
>> + </address>
>> + </affiliation>
>> + </author>
>> + </authorgroup>
>> +
>> + <copyright>
>> + <year>2015</year>
>> + <holder>Intel Corporation</holder>
>> + </copyright>
>> +
>> + <legalnotice>
>> + <para>
>> + This documentation is free software; you can redistribute
>> + it and/or modify it under the terms of the GNU General Public
>> + License version 2.
>> + </para>
>> + </legalnotice>
>> + </bookinfo>
>> +
>> + <toc></toc>
>> +
>> + <chapter id="intro">
>> + <title>Introduction</title>
>> + <para>
>> + The main purpose of the Industrial I/O subsystem (IIO) is to provide
>> + support for devices that in some sense perform either analog-to-digital
>> + conversion (ADC) or digital-to-analog conversion (DAC) or both. The aim
>> + is to fill the gap between the somewhat similar hwmon and input
>> + subsystems.
>> + Hwmon is directed at low sample rate sensors used to monitor and
>> + control the system itself, like fan speed control or temperature
>> + measurement. Input is, as its name suggests, focused on human interaction
>> + input devices (keyboard, mouse, touchscreen). In some cases there is
>> + considerable overlap between these and IIO.
>> + </para>
>> + <para>
>> + Devices that fall into this category include:
>> + <itemizedlist>
>> + <listitem>
>> + analog to digital converters (ADCs)
>> + </listitem>
>> + <listitem>
>> + accelerometers
>> + </listitem>
>> + <listitem>
>> + capacitance to digital converters (CDCs)
>> + </listitem>
>> + <listitem>
>> + digital to analog converters (DACs)
>> + </listitem>
>> + <listitem>
>> + gyroscopes
>> + </listitem>
>> + <listitem>
>> + inertial measurement units (IMUs)
>> + </listitem>
>> + <listitem>
>> + color and light sensors
>> + </listitem>
>> + <listitem>
>> + magnetometers
>> + </listitem>
>> + <listitem>
>> + pressure sensors
>> + </listitem>
>> + <listitem>
>> + proximity sensors
>> + </listitem>
>> + <listitem>
>> + temperature sensors
>> + </listitem>
>> + </itemizedlist>
>> + Usually these sensors are connected via SPI or I2C. A common use case of the
>> + sensors devices is to have combined functionality (e.g. light plus proximity
>
> sorsor devices

:), sensor devices. Got it :).

>
>> + sensor).
>> + </para>
>> + </chapter>
>> + <chapter id='iiosubsys'>
>> + <title>Industrial I/O core</title>
>> + <para>
>> + The Industrial I/O core offers:
>> + <itemizedlist>
>> + <listitem>
>> + a unified framework for writing drivers for many different types of
>> + embedded sensors.
>> + </listitem>
>> + <listitem>
>> + a standard interface to user space applications manipulating sensors.
>> + </listitem>
>> + </itemizedlist>
>> + The implementation can be found under <filename>
>> + drivers/iio/industrialio-*</filename>
>> + </para>
>> + <sect1 id="iiodevice">
>> + <title> Industrial I/O devices </title>
>
> extra spaces after/before tag, here and elsewhere

Nice catch. Fixed.

>
>> +
>> +!Finclude/linux/iio/iio.h iio_dev
>> +!Fdrivers/iio/industrialio-core.c iio_device_alloc
>> +!Fdrivers/iio/industrialio-core.c iio_device_free
>> +!Fdrivers/iio/industrialio-core.c iio_device_register
>> +!Fdrivers/iio/industrialio-core.c iio_device_unregister
>> +
>> + <para>
>> + An IIO device usually corresponds to a single hardware sensor and it
>> + provides all the information needed by a driver handling a device.
>> + Let's first have a look at the functionality embedded in an IIO
>> + device then we will show how a device driver makes use of an IIO
>> + device.
>> + </para>
>> + <para>
>> + There are two ways for a user space application to interact
>> + with an IIO driver.
>> + <itemizedlist>
>> + <listitem>
>> + <filename>/sys/bus/iio/iio:deviceX/</filename>, this
>> + represents a hardware sensor and groups together the data
>> + channels of the same chip.
>> + </listitem>
>> + <listitem>
>> + <filename>/dev/iio:deviceX</filename>, character device node
>> + interface used for faster data transfer and for events information
>
> maybe refer to buffered data transfer?

ok.

>
>> + retrieval.
>> + </listitem>
>> + </itemizedlist>
>> + </para>
>> + A typical IIO driver will register itself as an I2C or SPI driver and will
>> + create two routines, <function> probe </function> and <function> remove
>> + </function>. At <function>probe</function>:
>> + <itemizedlist>
>> + <listitem>call <function>iio_device_alloc</function>, which allocates memory
>> + for an IIO device.
>> + </listitem>
>> + <listitem> initialize IIO device fields with driver specific information
>> + (e.g. device name, device channels).
>> + </listitem>
>> + <listitem>call <function> iio_device_register</function>, this registers the
>> + device with the IIO core. After this call the device is ready to accept
>> + requests from user space applications.
>> + </listitem>
>> + </itemizedlist>
>> + At <function>remove</function>, we free the resources allocated in
>> + <function>probe</function> in reverse order:
>> + <itemizedlist>
>> + <listitem><function>iio_device_unregister</function>, unregister the device
>> + from the IIO core.
>> + </listitem>
>> + <listitem><function>iio_device_free</function>, free the memory allocated
>> + for the IIO device.
>> + </listitem>
>> + </itemizedlist>
>> +
>> + <sect2 id="iioattr"> <title> IIO device sysfs interface </title>
>> + <para>
>> + Attributes are sysfs files used to expose chip info and also allowing
>> + applications to set various configuration parameters. For device
>> + with index X, attributes can be found under
>> + <filename>/sys/bus/iio/iio:deviceX/ </filename> directory.
>> + Common attributes are:
>> + <itemizedlist>
>> + <listitem><filename>name</filename>, description of the physical
>> + chip.
>> + </listitem>
>> + <listitem><filename>dev</filename>, shows the major:minor pair
>> + associated with <filename>/dev/iio:deviceX</filename> node.
>> + </listitem>
>> + <listitem><filename>sampling_frequency_available</filename>,
>> + available discrete set of sampling frequency values for
>
> sampling_frequency is rather specific and not found for all devices;
> it may also appear under events/

Most of the devices I use have a configurable sampling_frequency (e.g
gyro, accels, magnetometers). I think it's not far from true that
sampling_frequency
is a common attribute. Or I could change 'common' to something else?

>
>> + device.
>> + </listitem>
>> + </itemizedlist>
>> + Available standard attributes for IIO devices are described in the
>> + <filename>Documentation/ABI/testing/sysfs-bus-iio </filename> file
>> + in the Linux kernel sources.
>> + </para>
>> + </sect2>
>> + <sect2 id="iiochannel"> <title> IIO device channels </title>
>> +!Finclude/linux/iio/iio.h iio_chan_spec structure.
>> + <para>
>> + An IIO device channel is a representation of a data channel. An
>> + IIO device can have one or multiple channels. For example:
>> + <itemizedlist>
>> + <listitem>
>> + a thermometer sensor has one channel representing the
>> + temperature measurement.
>> + </listitem>
>> + <listitem>
>> + a light sensor with two channels indicating the measurements in
>> + the visible and infrared spectrum.
>> + </listitem>
>> + <listitem>
>> + an accelerometer can have up to 3 channels representing
>> + acceleration on X, Y and Z axes.
>> + </listitem>
>> + </itemizedlist>
>> + An IIO channel is described by the <type> struct iio_chan_spec
>> + </type>. A thermometer driver for the temperature sensor in the
>> + example above would have to describe its channel as follows:
>> + <programlisting>
>> + static const struct iio_chan_spec temp_channel[] = {
>> + {
>> + .type = IIO_TEMP,
>> + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
>
> _RAW vs. _PROCESSED?

Not sure I understand this. PROCESSED because I want to avoid exposing now
scale and offset. Also, it's just an example.

>
>> + },
>> + };
>> +
>> + </programlisting>
>> + Channel sysfs attributes exposed to userspace are specified in
>> + the form of <emphasis>bitmasks</emphasis>. Depending on their
>> + shared info, attributes can be set in one of the following masks:
>> + <itemizedlist>
>> + <listitem><emphasis>info_mask_separate</emphasis>, attributes will
>> + be specific to this channel</listitem>
>> + <listitem><emphasis>info_mask_shared_by_type</emphasis>,
>> + attributes are shared by all channels of the same type</listitem>
>> + <listitem><emphasis>info_mask_shared_by_dir</emphasis>, attributes
>> + are shared by all channels of the same direction </listitem>
>> + <listitem><emphasis>info_mask_shared_by_all</emphasis>,
>> + attributes are shared by all channels</listitem>
>> + </itemizedlist>
>> + When there are multiple data channels per sensor type there are two
>
> per channel type?

Ok.

>
>> + ways to distinguish between them:
>> + <itemizedlist>
>> + <listitem> set <emphasis> .modified</emphasis> field of <type>
>> + iio_chan_spec</type> to 1. Modifiers are specified using
>> + <emphasis>.channel2</emphasis> field of the same
>> + <type>iio_chan_spec</type> structure and are used to indicate a
>> + physically unique characteristic of the channel such as its direction
>> + or spectral response. For example, a light sensor can have two channels,
>> + one for infrared light and one for both infrared and visible light.
>> + </listitem>
>> + <listitem> set <emphasis>.indexed </emphasis> field of
>> + <type>iio_chan_spec</type> to 1. In this case the channel is
>> + simply another instance with an index specified by the
>> + <emphasis>.channel</emphasis> field.
>> + </listitem>
>> + </itemizedlist>
>> + Here is how we can make use of the channel's modifiers:
>> + <programlisting>
>> + static const struct iio_chan_spec light_channels[] = {
>> + {
>> + .type = IIO_INTENSITY,
>> + .modified = 1,
>> + .channel2 = IIO_MOD_LIGHT_IR,
>> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
>> + .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
>> + },
>> + {
>> + .type = IIO_INTENSITY,
>> + .modified = 1,
>> + .channel2 = IIO_MOD_LIGHT_BOTH,
>> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
>> + .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
>> + },
>> + {
>> + .type = IIO_LIGHT,
>> + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
>> + .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
>> + },
>> +
>> + }
>> + </programlisting>
>> + This channel's definition will generate two separate sysfs files
>> + for raw data retrieval:
>> + <itemizedlist>
>> + <listitem>
>> + <filename>/sys/bus/iio/iio:deviceX/in_intensity_ir_raw</filename>
>> + </listitem>
>> + <listitem>
>> + <filename>/sys/bus/iio/iio:deviceX/in_intensity_both_raw</filename>
>> + </listitem>
>> + </itemizedlist>
>> + one file for processed data:
>> + <itemizedlist>
>> + <listitem>
>> + <filename>/sys/bus/iio/iio:deviceX/in_illuminance_input
>> + </filename>
>> + </listitem>
>> + </itemizedlist>
>> + and one shared sysfs file for sampling frequency:
>
> this is a bit of a corner case: why is there just one _sampling_frequency
> channel? it could also have been named in_illuminance_sampling_frequency

In fact, the attribute will be called sampling frequency, the field name is
wrong it should by info_mask_shared_by_all :).

>
>> + <itemizedlist>
>> + <listitem>
>> + <filename>/sys/bus/iio/iio:deviceX/in_intensity_sampling_frequency.
>> + </filename>
>> + </listitem>
>> + </itemizedlist>
>> + </para>
>> + <para>
>> + Here is how we can make use of the channel's indexing:
>> + <programlisting>
>> + static const struct iio_chan_spec light_channels[] = {
>> + {
>> + .type = IIO_VOLTAGE,
>> + .indexed = 1,
>> + .channel = 0,
>> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
>> + },
>> + {
>> + .type = IIO_VOLTAGE,
>> + .indexed = 1,
>> + .channel = 1,
>> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
>> + },
>> + }
>> + </programlisting>
>> + This will generate two separate attributes files for raw data
>> + retrieval:
>> + <itemizedlist>
>> + <listitem>
>> + <filename>/sys/bus/iio/devices/iio:deviceX/in_voltage0_raw</filename>,
>> + representing voltage measurement for channel 0.
>> + </listitem>
>> + <listitem>
>> + <filename>/sys/bus/iio/devices/iio:deviceX/in_voltage1_raw</filename>,
>> + representing voltage measurement for channel 1.
>> + </listitem>
>> + </itemizedlist>
>> + </para>
>> + </sect2>
>> + </sect1>
>> +
>> + <sect1 id="iiobuffer"> <title> Industrial I/O buffers </title>
>> +!Finclude/linux/iio/buffer.h iio_buffer
>> +!Edrivers/iio/industrialio-buffer.c
>> +
>> + <para>
>> + The Industrial I/O core offers a way for continuous data capture
>> + based on a trigger source. Multiple data channels can be read at once
>> + from <filename>/dev/iio:deviceX</filename> character device node,
>> + thus reducing the CPU load.
>> + </para>
>> +
>> + <sect2 id="iiobuffersysfs">
>> + <title>IIO buffer sysfs interface </title>
>> + <para>
>> + An IIO buffer has an associated attributes directory under <filename>
>> + /sys/bus/iio/iio:deviceX/buffer/</filename>. Here are the existing
>> + attributes:
>> + <itemizedlist>
>> + <listitem>
>> + <emphasis>length</emphasis>, number of data samples contained by the
>> + buffer.
>
> wording is not very clean; length is is the buffer length/capacity, not
> the number of samples currently in the buffer

Oh, I see. The same wording is in the ABI file:

>
>> + </listitem>
>> + <listitem>
>> + <emphasis>enable</emphasis>, activate buffer capture.
>> + </listitem>
>> + </itemizedlist>
>> + </para>
>> + </sect2>
>> + <sect2 id="iiobuffersetup"> <title> IIO buffer setup </title>
>> + <para>The meta information associated with a channel reading
>> + placed in a buffer is called a <emphasis> scan element </emphasis>.
>> + The important bits configuring scan elements are exposed to
>> + userspace applications via the <filename>
>> + /sys/bus/iio/iio:deviceX/scan_elements/</filename> directory. This
>> + file contains attributes of the following form:
>> + <itemizedlist>
>> + <listitem><emphasis>enable</emphasis>, used for enabling a channel.
>> + If and only if its attribute is non zero, then a triggered capture
>> + will contain data samples for this channel.
>> + </listitem>
>> + <listitem><emphasis>type</emphasis>, description of the scan element
>> + data storage within the buffer and hence the form in which it is
>> + read from user space. Format is <emphasis>
>> + [be|le]:[s|u]bits/storagebitsXrepeat[>>shift] </emphasis>.
>> + <itemizedlist>
>> + <listitem> <emphasis>be</emphasis> or <emphasis>le</emphasis> specifies
>> + big or little endian.
>> + </listitem>
>> + <listitem>
>> + <emphasis>s </emphasis>or <emphasis>u</emphasis> specifies if
>> + signed (2's complement) or unsigned.
>> + </listitem>
>> + <listitem><emphasis>bits</emphasis> is the number of bits of data
>
> number of data bits
>
>> + </listitem>
>> + <listitem><emphasis>storagebits</emphasis> is the space (after padding)
>> + that it occupies in the buffer.
>
> is the number of bits (after padding) that...
>
>> + </listitem>
>> + <listitem>
>> + <emphasis>shift</emphasis> if specified, is the shift that needs
>> + to be a applied prior to masking out unused bits
>
> that needs to be applied -- delete a
>
>> + </listitem>
>> + <listitem>
>> + <emphasis>repeat</emphasis>, specifies the number of real/storage bits
>
> what is real? -- undefined at this point;
> "real/storage" doesn't make it clear if the padded or unpadded data bits
> are repeated -- I think the later
> maybe: "specifies the number of unpadded data repetitions"
>
>> + repetitions. When the repeat element is 0 or 1, then the repeat
>> + value is omitted.
>> + </listitem>
>> + </itemizedlist>
>> + </listitem>
>> + </itemizedlist>
>> + For example, a driver for a 3-axis accelerometer with 12 bit
>> + resolution where data is stored in two 8-bits registers as
>> + follows:
>> + <programlisting>
>> + 7 6 5 4 3 2 1 0
>> + +---+---+---+---+---+---+---+---+
>> + |D3 |D2 |D1 |D0 | X | X | X | X | (LOW byte, address 0x06)
>> + +---+---+---+---+---+---+---+---+
>> +
>> + 7 6 5 4 3 2 1 0
>> + +---+---+---+---+---+---+---+---+
>> + |D11|D10|D9 |D8 |D7 |D6 |D5 |D4 | (HIGH byte, address 0x07)
>> + +---+---+---+---+---+---+---+---+
>> + </programlisting>
>> +
>> + will have the following scan element type for each axis:
>> + <programlisting>
>> + $ cat /sys/bus/iio/devices/iio:device0/scan_elements/in_accel_y_type
>> + le:s12/16>>4
>> + </programlisting>
>> + The userspace applications will interpret data samples read from buffer
>
> user space -- inconsistent
> maybe "A user space application will..."
> the buffer -- the
>
>> + as two byte little endian signed data, that needs a 4 bits right
>> + shift before masking out the only 12 valid bits of real data.
>
> masking out the 12 valid bits of data
>
>> + </para>
>> + <para>
>> + For implementing buffer support a driver should initialize the following
>> + fields in <type>iio_chan_spec</type> definition:
>> + <programlisting>
>> + struct iio_chan_spec {
>> + /* other members */
>> + int scan_index
>> + struct {
>> + char sign;
>> + u8 realbits;
>> + u8 storagebits;
>> + u8 shift;
>> + u8 repeat;
>> + enum iio_endian endianness;
>> + } scan_type;
>> + };
>> + </programlisting>
>> + The driver implementing the accelerometer described above will
>> + have the following channel definition:
>> + <programlisting>
>> + struct struct iio_chan_spec accel_channels[] = {
>> + {
>> + .type = IIO_ACCEL,
>> + .modified = 1,
>> + .channel2 = IIO_MOD_X,
>> + /* other stuff here */
>> + .scan_index = 0,
>> + .scan_type = {
>> + .sign = 's',
>> + .realbits = 12,
>> + .storgebits = 16,
>> + .shift = 4,
>> + .endianness = IIO_LE,
>> + },
>> + }
>> + /* similar for Y and Z axis */
>
> two spaces before Z
> maybe: "similar for Y (with channel2 = IIO_MOD_Y, scan_index = 1) and Z
> (with channel2 = IIO_MOD_Z, scan_index=2) axis"
>
>> + }
>> + </programlisting>
>> + </para>
>> + <para>
>> + Here <emphasis> scan_index </emphasis> defines the relative order in which
>
> why relative?
> it is simply the order
>
>> + the enabled channels are placed inside the buffer. Channels with a lower
>> + scan_index will be placed before channels with a higher index. Each
>> + channel needs to have a unique scan_index.
>> + </para>
>> + <para>
>> + It is important to realize that the scan_index does not define the
>> + absolute position in the buffer. E.g. a channel with the scan_index = 3
>> + will not be at offset 3 bytes or 3 words, but rather will be placed in the
>> + buffer after any channel with a scan_index lower than 3 and before
>> + any channel with a scan_index larger than 3.
>
> I'd drop the paragraph above, this is just confusing; better mention that
> there are padding rules (e.g. for the timestamp channel) and it follows
> that the scan_index is not a byte offset into the buffer
>
>> + Furthermore the scan indices do not have to be consecutive. E.g. A
>> + channel spec array that defines 3 channels with the indices 1, 2 and 3 is
>> + just as valid as a channel spec that uses the indices 100, 200, 300. The
>> + relative order of the channels will be the same.
>> + </para>
>> + <para>
>> + Setting scan_index to -1 can be used to indicate that the specific
>> + channel does not support buffered capture. In this case no entries will
>> + be created for the channel in the scan_elements directory.
>> + </para>
>> + </sect2>
>> + </sect1>
>> +
>> + <sect1 id="iiotrigger"> <title> Industrial I/O triggers </title>
>> +!Finclude/linux/iio/trigger.h iio_trigger
>> +!Edrivers/iio/industrialio-trigger.c
>> + <para>
>> + In many situations it is useful for a driver to be able to
>> + capture data based on some external event (trigger) as opposed
>> + to periodically polling for data. An IIO trigger can be provided
>> + by a device driver that also has an IIO device based on hardware
>> + generated events (e.g. data ready or threshold exceeded) or
>> + provided by a separate driver from an independent interrupt
>> + source (e.g. GPIO line connected to some external system, timer
>> + interrupt or user space reading a specific file in sysfs). A
>
> writing a specific file
>
>> + trigger may initialize data capture for a number of sensors and
>
> initiate -- not initialize
>
>> + also it may be completely unrelated to the sensor itself.
>> + </para>
>> +
>> + <sect2 id="iiotrigsysfs"> <title> IIO trigger sysfs interface </title>
>> + There are two locations in sysfs related to triggers:
>> + <itemizedlist>
>> + <listitem><filename>/sys/bus/iio/devices/triggerY</filename>,
>> + this file is created once an IIO triggered is registered with
>
> an IIO trigger
>
>> + the IIO core and corresponds to trigger with index Y. Because
>> + triggers can be very different depending on type there are few
>> + standard attributes that we can describe here:
>> + <itemizedlist>
>> + <listitem>
>> + <emphasis>name</emphasis>, trigger name that can be later
>> + used to for association with a device.
>
> used for association
>
>> + </listitem>
>> + <listitem>
>> + <emphasis>sampling_frequency</emphasis>, some timer based
>> + triggers use this attribute to specify the frequency for
>> + trigger calls.
>> + </listitem>
>> + </itemizedlist>
>> + </listitem>
>> + <listitem>
>> + <filename>/sys/bus/iio/devices/iio:deviceX/trigger/</filename>, this
>> + directory is created once the device supports a triggered
>> + buffer. We can associate a trigger with our device by writing
>> + trigger's name in the<filename>current_trigger</filename> file.
>
> the trigger's name -- the
> the <filename> -- add space before tag
>
>> + </listitem>
>> + </itemizedlist>
>> + </sect2>
>> +
>> + <sect2 id="iiotrigattr"> <title> IIO trigger setup</title>
>> +
>> + <para>
>> + Let's see a simple example of how to setup a trigger to be used
>> + by a driver.
>> +
>> + <programlisting>
>> + struct iio_trigger_ops trigger_ops = {
>> + .set_trigger_state = sample_trigger_state,
>> + .validate_device = sample_validate_device,
>> + }
>> +
>> + struct iio_trigger *trig;
>> +
>> + /* first, allocate memory for our trigger */
>> + trig = iio_trigger_alloc(dev, "trig-%s-%d", name, idx);
>> +
>> + /* setup trigger operations field */
>> + trig->ops = &amp;trigger_ops;
>> +
>> + /* now register the trigger with the IIO core */
>> + iio_trigger_register(trig);
>> + </programlisting>
>> + </para>
>> + </sect2>
>> +
>> + <sect2 id="iiotrigsetup"> <title> IIO trigger ops</title>
>> +!Finclude/linux/iio/trigger.h iio_trigger_ops
>> + <para>
>> + Notice that a trigger has a set of operations attached:
>> + <itemizedlist>
>> + <listitem>
>> + <function>set_trigger_state</function>, switch the trigger on/off
>> + on demand.
>> + </listitem>
>> + <listitem>
>> + <function>validate_device</function>, function to validate the
>> + device when the current trigger gets changed.
>> + </listitem>
>> + </itemizedlist>
>> + </para>
>> + </sect2>
>> + </sect1>
>> + <sect1 id="iiotriggered_buffer">
>> + <title> Industrial I/O triggered buffers </title>
>> + <para>
>> + Now that we know what buffers and triggers are let's see how they
>> + work together.
>> + </para>
>> + <sect2 id="iiotrigbufsetup"> <title> IIO triggered buffer setup</title>
>> +!Edrivers/iio/industrialio-triggered-buffer.c
>> +!Finclude/linux/iio/iio.h iio_buffer_setup_ops
>> +
>> +
>> + <para>
>> + A typical triggered buffer setup looks like this:
>> + <programlisting>
>> + const struct iio_buffer_setup_ops sensor_buffer_setup_ops = {
>> + .preenable = sensor_buffer_preenable,
>> + .postenable = sensor_buffer_postenable,
>> + .postdisable = sensor_buffer_postdisable,
>> + .predisable = sensor_buffer_predisable,
>> + };
>> +
>> + irqreturn_t sensor_iio_pollfunc(int irq, void *p)
>> + {
>> + pf->timestamp = iio_get_time_ns();
>> + return IRQ_WAKE_THREAD;
>> + }
>> +
>> + irqreturn_t sensor_trigger_handler(int irq, void *p)
>> + {
>> + u16 buf[8];
>
> int i = 0;
>
>> +
>> + /* read data for each active channel */
>> + for_each_set_bit(bit, active_scan_mask, masklength)
>> + buf[i++] = sensor_get_data(bit)
>> +
>> + iio_push_to_buffers_with_timestamp(indio_dev, buffer, timestamp);
>
> buf -- not buffer
>
>> +
>> + iio_trigger_notify_done(trigger);
>
> return IRQ_HANDLED;
>
>> + }
>> +
>> + /* setup triggered buffer, usually in probe function */
>> + iio_triggered_buffer_setup(indio_dev, sensor_iio_polfunc,
>> + sensor_trigger_handler,
>> + sensor_buffer_setup_ops);
>> + </programlisting>
>> + </para>
>> + The important things to notice here are:
>> + <itemizedlist>
>> + <listitem><function> iio_buffer_setup_ops</function>, the buffer setup
>> + functions to be called at predefined points in buffer configuration
>
> the buffer configuration -- the
>
>> + sequence (e.g. before enable, after disable). If not specified, the
>> + IIO core uses the default <type>iio_triggered_buffer_setup_ops</type>.
>> + </listitem>
>> + <listitem><function>sensor_iio_pollfunc</function>, the function that
>> + will be used as top half of poll function. It should do as little
>> + processing as possible, because it runs in interrupt context. The most
>> + common operation is recording of the current timestamp and for this reason
>> + one can use the IIO core defined <function>iio_pollfunc_store_time
>> + </function> function.
>> + </listitem>
>> + <listitem><function>sensor_trigger_handler</function>, the function that
>> + will be used as bottom half of the poll function. This runs in the
>> + context of a kernel thread and all the processing takes place here.
>> + It usually reads data from the device and stores it in the internal
>> + buffer together with the timestamp recorded in the top half.
>> + </listitem>
>> + </itemizedlist>
>> + </sect2>
>> + </sect1>
>> + </chapter>
>> + <chapter id='iioresources'>
>> + <title> Resources </title>
>> + IIO core may change during time so the best documentation to read is the
>> + source code. There are several locations where you should look:
>> + <itemizedlist>
>> + <listitem>
>> + <filename>drivers/iio/</filename>, contains the IIO core plus
>> + and directories for each sensor type (e.g. accel, magnetometer,
>> + etc.)
>> + </listitem>
>> + <listitem>
>> + <filename>include/linux/iio/</filename>, contains the header
>> + files, nice to read for the internal kernel interfaces.
>> + </listitem>
>> + <listitem>
>> + <filename>include/uapi/linux/iio/</filename>, contains files to be
>> + used by user space applications.
>> + </listitem>
>> + <listitem>
>> + <filename>tools/iio/</filename>, contains tools for rapidly
>> + testing buffers, events and device creation.
>> + </listitem>
>> + <listitem>
>> + <filename>drivers/staging/iio/</filename>, contains code for some
>> + drivers or experimental features that are not yet mature enough
>> + to be moved out.
>> + </listitem>
>> + </itemizedlist>
>> + <para>
>> + Besides the code, there are some good online documentation sources:
>> + <itemizedlist>
>> + <listitem>
>> + <ulink url="http://marc.info/?l=linux-iio"> Industrial I/O mailing
>> + list </ulink>
>> + </listitem>
>> + <listitem>
>> + <ulink url="http://wiki.analog.com/software/linux/docs/iio/iio">
>> + Analog Device IIO wiki page </ulink>
>> + </listitem>
>> + <listitem>
>> + <ulink url="https://fosdem.org/2015/schedule/event/iiosdr/">
>> + Using the Linux IIO framework for SDR, Lars-Peter Clausen's
>> + presentation at FOSDEM </ulink>
>> + </listitem>
>> + </itemizedlist>
>> + </para>
>> + </chapter>
>> +</book>
>> +
>> +<!--
>> +vim: softtabstop=2:shiftwidth=2:expandtab:textwidth=72
>> +-->
>>
>
> --
>
> Peter Meerwald
> +43-664-2444418 (mobile)
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2015-08-04 09:05:00

by Daniel Baluta

[permalink] [raw]
Subject: Re: [PATCH v4] DocBook: Add initial documentation for IIO

Sorry, hit send by mistake :)


>>> + An IIO buffer has an associated attributes directory under <filename>
>>> + /sys/bus/iio/iio:deviceX/buffer/</filename>. Here are the existing
>>> + attributes:
>>> + <itemizedlist>
>>> + <listitem>
>>> + <emphasis>length</emphasis>, number of data samples contained by the
>>> + buffer.
>>
>> wording is not very clean; length is is the buffer length/capacity, not
>> the number of samples currently in the buffer
>
> Oh, I see. The same wording is in the ABI file:

http://lxr.free-electrons.com/source/Documentation/ABI/testing/sysfs-bus-iio#L975

<snip>

>>> + </listitem>
>>> + <listitem><emphasis>bits</emphasis> is the number of bits of data
>>
>> number of data bits

Ok.

>>
>>> + </listitem>
>>> + <listitem><emphasis>storagebits</emphasis> is the space (after padding)
>>> + that it occupies in the buffer.
>>
>> is the number of bits (after padding) that...

Ok.

>>
>>> + </listitem>
>>> + <listitem>
>>> + <emphasis>shift</emphasis> if specified, is the shift that needs
>>> + to be a applied prior to masking out unused bits
>>
>> that needs to be applied -- delete a

Ok.

>>
>>> + </listitem>
>>> + <listitem>
>>> + <emphasis>repeat</emphasis>, specifies the number of real/storage bits
>>
>> what is real? -- undefined at this point;
>> "real/storage" doesn't make it clear if the padded or unpadded data bits
>> are repeated -- I think the later
>> maybe: "specifies the number of unpadded data repetitions"

Will fix.

>>
>>> + repetitions. When the repeat element is 0 or 1, then the repeat
>>> + value is omitted.
>>> + </listitem>
>>> + </itemizedlist>
>>> + </listitem>
>>> + </itemizedlist>
>>> + For example, a driver for a 3-axis accelerometer with 12 bit
>>> + resolution where data is stored in two 8-bits registers as
>>> + follows:
>>> + <programlisting>
>>> + 7 6 5 4 3 2 1 0
>>> + +---+---+---+---+---+---+---+---+
>>> + |D3 |D2 |D1 |D0 | X | X | X | X | (LOW byte, address 0x06)
>>> + +---+---+---+---+---+---+---+---+
>>> +
>>> + 7 6 5 4 3 2 1 0
>>> + +---+---+---+---+---+---+---+---+
>>> + |D11|D10|D9 |D8 |D7 |D6 |D5 |D4 | (HIGH byte, address 0x07)
>>> + +---+---+---+---+---+---+---+---+
>>> + </programlisting>
>>> +
>>> + will have the following scan element type for each axis:
>>> + <programlisting>
>>> + $ cat /sys/bus/iio/devices/iio:device0/scan_elements/in_accel_y_type
>>> + le:s12/16>>4
>>> + </programlisting>
>>> + The userspace applications will interpret data samples read from buffer
>>
>> user space -- inconsistent
>> maybe "A user space application will..."
>> the buffer -- the
>>
>>> + as two byte little endian signed data, that needs a 4 bits right
>>> + shift before masking out the only 12 valid bits of real data.
>>
>> masking out the 12 valid bits of data

Agree.

>>
>>> + </para>
>>> + <para>
>>> + For implementing buffer support a driver should initialize the following
>>> + fields in <type>iio_chan_spec</type> definition:
>>> + <programlisting>
>>> + struct iio_chan_spec {
>>> + /* other members */
>>> + int scan_index
>>> + struct {
>>> + char sign;
>>> + u8 realbits;
>>> + u8 storagebits;
>>> + u8 shift;
>>> + u8 repeat;
>>> + enum iio_endian endianness;
>>> + } scan_type;
>>> + };
>>> + </programlisting>
>>> + The driver implementing the accelerometer described above will
>>> + have the following channel definition:
>>> + <programlisting>
>>> + struct struct iio_chan_spec accel_channels[] = {
>>> + {
>>> + .type = IIO_ACCEL,
>>> + .modified = 1,
>>> + .channel2 = IIO_MOD_X,
>>> + /* other stuff here */
>>> + .scan_index = 0,
>>> + .scan_type = {
>>> + .sign = 's',
>>> + .realbits = 12,
>>> + .storgebits = 16,
>>> + .shift = 4,
>>> + .endianness = IIO_LE,
>>> + },
>>> + }
>>> + /* similar for Y and Z axis */
>>
>> two spaces before Z
>> maybe: "similar for Y (with channel2 = IIO_MOD_Y, scan_index = 1) and Z
>> (with channel2 = IIO_MOD_Z, scan_index=2) axis"

Ok.

>>
>>> + }
>>> + </programlisting>
>>> + </para>
>>> + <para>
>>> + Here <emphasis> scan_index </emphasis> defines the relative order in which
>>
>> why relative?
>> it is simply the order
>>
>>> + the enabled channels are placed inside the buffer. Channels with a lower
>>> + scan_index will be placed before channels with a higher index. Each
>>> + channel needs to have a unique scan_index.
>>> + </para>
>>> + <para>
>>> + It is important to realize that the scan_index does not define the
>>> + absolute position in the buffer. E.g. a channel with the scan_index = 3
>>> + will not be at offset 3 bytes or 3 words, but rather will be placed in the
>>> + buffer after any channel with a scan_index lower than 3 and before
>>> + any channel with a scan_index larger than 3.
>>
>> I'd drop the paragraph above, this is just confusing; better mention that
>> there are padding rules (e.g. for the timestamp channel) and it follows
>> that the scan_index is not a byte offset into the buffer

Will try to add a better wording for this, although it looks clear enough to me.

>>
>>> + Furthermore the scan indices do not have to be consecutive. E.g. A
>>> + channel spec array that defines 3 channels with the indices 1, 2 and 3 is
>>> + just as valid as a channel spec that uses the indices 100, 200, 300. The
>>> + relative order of the channels will be the same.
>>> + </para>
>>> + <para>
>>> + Setting scan_index to -1 can be used to indicate that the specific
>>> + channel does not support buffered capture. In this case no entries will
>>> + be created for the channel in the scan_elements directory.
>>> + </para>
>>> + </sect2>
>>> + </sect1>
>>> +
>>> + <sect1 id="iiotrigger"> <title> Industrial I/O triggers </title>
>>> +!Finclude/linux/iio/trigger.h iio_trigger
>>> +!Edrivers/iio/industrialio-trigger.c
>>> + <para>
>>> + In many situations it is useful for a driver to be able to
>>> + capture data based on some external event (trigger) as opposed
>>> + to periodically polling for data. An IIO trigger can be provided
>>> + by a device driver that also has an IIO device based on hardware
>>> + generated events (e.g. data ready or threshold exceeded) or
>>> + provided by a separate driver from an independent interrupt
>>> + source (e.g. GPIO line connected to some external system, timer
>>> + interrupt or user space reading a specific file in sysfs). A
>>
>> writing a specific file
Ok.

>>
>>> + trigger may initialize data capture for a number of sensors and
>>
>> initiate -- not initialize

:)

>>
>>> + also it may be completely unrelated to the sensor itself.
>>> + </para>
>>> +
>>> + <sect2 id="iiotrigsysfs"> <title> IIO trigger sysfs interface </title>
>>> + There are two locations in sysfs related to triggers:
>>> + <itemizedlist>
>>> + <listitem><filename>/sys/bus/iio/devices/triggerY</filename>,
>>> + this file is created once an IIO triggered is registered with
>>
>> an IIO trigger

Ok.

>>
>>> + the IIO core and corresponds to trigger with index Y. Because
>>> + triggers can be very different depending on type there are few
>>> + standard attributes that we can describe here:
>>> + <itemizedlist>
>>> + <listitem>
>>> + <emphasis>name</emphasis>, trigger name that can be later
>>> + used to for association with a device.
>>
>> used for association

:), ok.

>>
>>> + </listitem>
>>> + <listitem>
>>> + <emphasis>sampling_frequency</emphasis>, some timer based
>>> + triggers use this attribute to specify the frequency for
>>> + trigger calls.
>>> + </listitem>
>>> + </itemizedlist>
>>> + </listitem>
>>> + <listitem>
>>> + <filename>/sys/bus/iio/devices/iio:deviceX/trigger/</filename>, this
>>> + directory is created once the device supports a triggered
>>> + buffer. We can associate a trigger with our device by writing
>>> + trigger's name in the<filename>current_trigger</filename> file.
>>
>> the trigger's name -- the
>> the <filename> -- add space before tag
>>
>>> + </listitem>
>>> + </itemizedlist>
>>> + </sect2>
>>> +
>>> + <sect2 id="iiotrigattr"> <title> IIO trigger setup</title>
>>> +
>>> + <para>
>>> + Let's see a simple example of how to setup a trigger to be used
>>> + by a driver.
>>> +
>>> + <programlisting>
>>> + struct iio_trigger_ops trigger_ops = {
>>> + .set_trigger_state = sample_trigger_state,
>>> + .validate_device = sample_validate_device,
>>> + }
>>> +
>>> + struct iio_trigger *trig;
>>> +
>>> + /* first, allocate memory for our trigger */
>>> + trig = iio_trigger_alloc(dev, "trig-%s-%d", name, idx);
>>> +
>>> + /* setup trigger operations field */
>>> + trig->ops = &amp;trigger_ops;
>>> +
>>> + /* now register the trigger with the IIO core */
>>> + iio_trigger_register(trig);
>>> + </programlisting>
>>> + </para>
>>> + </sect2>
>>> +
>>> + <sect2 id="iiotrigsetup"> <title> IIO trigger ops</title>
>>> +!Finclude/linux/iio/trigger.h iio_trigger_ops
>>> + <para>
>>> + Notice that a trigger has a set of operations attached:
>>> + <itemizedlist>
>>> + <listitem>
>>> + <function>set_trigger_state</function>, switch the trigger on/off
>>> + on demand.
>>> + </listitem>
>>> + <listitem>
>>> + <function>validate_device</function>, function to validate the
>>> + device when the current trigger gets changed.
>>> + </listitem>
>>> + </itemizedlist>
>>> + </para>
>>> + </sect2>
>>> + </sect1>
>>> + <sect1 id="iiotriggered_buffer">
>>> + <title> Industrial I/O triggered buffers </title>
>>> + <para>
>>> + Now that we know what buffers and triggers are let's see how they
>>> + work together.
>>> + </para>
>>> + <sect2 id="iiotrigbufsetup"> <title> IIO triggered buffer setup</title>
>>> +!Edrivers/iio/industrialio-triggered-buffer.c
>>> +!Finclude/linux/iio/iio.h iio_buffer_setup_ops
>>> +
>>> +
>>> + <para>
>>> + A typical triggered buffer setup looks like this:
>>> + <programlisting>
>>> + const struct iio_buffer_setup_ops sensor_buffer_setup_ops = {
>>> + .preenable = sensor_buffer_preenable,
>>> + .postenable = sensor_buffer_postenable,
>>> + .postdisable = sensor_buffer_postdisable,
>>> + .predisable = sensor_buffer_predisable,
>>> + };
>>> +
>>> + irqreturn_t sensor_iio_pollfunc(int irq, void *p)
>>> + {
>>> + pf->timestamp = iio_get_time_ns();
>>> + return IRQ_WAKE_THREAD;
>>> + }
>>> +
>>> + irqreturn_t sensor_trigger_handler(int irq, void *p)
>>> + {
>>> + u16 buf[8];
>>
>> int i = 0;
>>
>>> +
>>> + /* read data for each active channel */
>>> + for_each_set_bit(bit, active_scan_mask, masklength)
>>> + buf[i++] = sensor_get_data(bit)
>>> +
>>> + iio_push_to_buffers_with_timestamp(indio_dev, buffer, timestamp);
>>
>> buf -- not buffer
ok.

>>
>>> +
>>> + iio_trigger_notify_done(trigger);
>>
>> return IRQ_HANDLED;

ok.

>>
>>> + }
>>> +
>>> + /* setup triggered buffer, usually in probe function */
>>> + iio_triggered_buffer_setup(indio_dev, sensor_iio_polfunc,
>>> + sensor_trigger_handler,
>>> + sensor_buffer_setup_ops);
>>> + </programlisting>
>>> + </para>
>>> + The important things to notice here are:
>>> + <itemizedlist>
>>> + <listitem><function> iio_buffer_setup_ops</function>, the buffer setup
>>> + functions to be called at predefined points in buffer configuration
>>
>> the buffer configuration -- the

ok.