|  | <?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>daniel.baluta@intel.com</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 buffered 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 channel type we have 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/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>, the total number of data samples | 
|  | (capacity) that can be stored 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 valid data | 
|  | bits. | 
|  | </listitem> | 
|  | <listitem><emphasis>storagebits</emphasis>, is the number of bits | 
|  | (after padding) that it occupies in the buffer. | 
|  | </listitem> | 
|  | <listitem> | 
|  | <emphasis>shift</emphasis>, if specified, is the shift that needs | 
|  | to be applied prior to masking out unused bits. | 
|  | </listitem> | 
|  | <listitem> | 
|  | <emphasis>repeat</emphasis>, specifies the number of bits/storagebits | 
|  | 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> | 
|  | A user space application will interpret data samples read from the | 
|  | buffer as two byte little endian signed data, that needs a 4 bits | 
|  | right shift before 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 (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 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> | 
|  | 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 writing a specific file in sysfs). A | 
|  | trigger may initiate 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 trigger 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 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 | 
|  | the 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 = &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, buf, timestamp); | 
|  |  | 
|  | 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 the 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 | 
|  | --> |