* [PATCH v4] DocBook documentation for IIO @ 2015-07-31 14:04 Daniel Baluta 2015-07-31 14:04 ` [PATCH v4] DocBook: Add initial " Daniel Baluta 0 siblings, 1 reply; 7+ messages in thread From: Daniel Baluta @ 2015-07-31 14:04 UTC (permalink / raw) To: jic23, corbet, rdunlap, cmo Cc: pmeerw, knaack.h, lars, linux-kernel, linux-iio, herbert, smueller, mmarek, daniel.baluta, linux-doc, cristina.opriceana 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 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v4] DocBook: Add initial documentation for IIO 2015-07-31 14:04 [PATCH v4] DocBook documentation for IIO Daniel Baluta @ 2015-07-31 14:04 ` Daniel Baluta 2015-08-03 8:14 ` Lars-Peter Clausen 2015-08-03 9:24 ` Peter Meerwald 0 siblings, 2 replies; 7+ messages in thread From: Daniel Baluta @ 2015-07-31 14:04 UTC (permalink / raw) To: jic23, corbet, rdunlap, cmo Cc: pmeerw, knaack.h, lars, linux-kernel, linux-iio, herbert, smueller, mmarek, daniel.baluta, linux-doc, cristina.opriceana 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 <daniel.baluta@intel.com> --- 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>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 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 = &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 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v4] DocBook: Add initial documentation for IIO 2015-07-31 14:04 ` [PATCH v4] DocBook: Add initial " Daniel Baluta @ 2015-08-03 8:14 ` Lars-Peter Clausen 2015-08-03 8:29 ` Crt Mori 2015-08-03 9:24 ` Peter Meerwald 1 sibling, 1 reply; 7+ messages in thread From: Lars-Peter Clausen @ 2015-08-03 8:14 UTC (permalink / raw) To: Daniel Baluta, jic23, corbet, rdunlap, cmo Cc: pmeerw, knaack.h, linux-kernel, linux-iio, herbert, smueller, mmarek, linux-doc, cristina.opriceana 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 <daniel.baluta@intel.com> Looks good to me. Thanks again. Reviewed-by: Lars-Peter Clausen <lars@metafoo.de> ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v4] DocBook: Add initial documentation for IIO 2015-08-03 8:14 ` Lars-Peter Clausen @ 2015-08-03 8:29 ` Crt Mori 0 siblings, 0 replies; 7+ messages in thread From: Crt Mori @ 2015-08-03 8:29 UTC (permalink / raw) To: Lars-Peter Clausen Cc: Daniel Baluta, Johnathan Iain Cameron, Jonathan Corbet, rdunlap, Peter Meerwald, Hartmut Knaack, linux-kernel, linux-iio, Herbert Xu, smueller, mmarek, linux-doc, Cristina Georgiana Opriceana On 3 August 2015 at 10:14, Lars-Peter Clausen <lars@metafoo.de> 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 <daniel.baluta@intel.com> > > Looks good to me. Thanks again. > > Reviewed-by: Lars-Peter Clausen <lars@metafoo.de> Acked-by: Crt Mori <cmo@melexis.com> ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v4] DocBook: Add initial documentation for IIO 2015-07-31 14:04 ` [PATCH v4] DocBook: Add initial " Daniel Baluta 2015-08-03 8:14 ` Lars-Peter Clausen @ 2015-08-03 9:24 ` Peter Meerwald 2015-08-04 8:59 ` Daniel Baluta 1 sibling, 1 reply; 7+ messages in thread From: Peter Meerwald @ 2015-08-03 9:24 UTC (permalink / raw) To: Daniel Baluta Cc: jic23, corbet, knaack.h, lars, linux-kernel, linux-iio, linux-doc 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 <daniel.baluta@intel.com> > --- > 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>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 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 = &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) ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v4] DocBook: Add initial documentation for IIO 2015-08-03 9:24 ` Peter Meerwald @ 2015-08-04 8:59 ` Daniel Baluta 2015-08-04 9:04 ` Daniel Baluta 0 siblings, 1 reply; 7+ messages in thread From: Daniel Baluta @ 2015-08-04 8:59 UTC (permalink / raw) To: Peter Meerwald Cc: Daniel Baluta, Jonathan Cameron, Jonathan Corbet, Hartmut Knaack, Lars-Peter Clausen, Linux Kernel Mailing List, linux-iio@vger.kernel.org, linux-doc On Mon, Aug 3, 2015 at 12:24 PM, Peter Meerwald <pmeerw@pmeerw.net> 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 <daniel.baluta@intel.com> >> --- >> 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>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 > > 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 = &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 majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v4] DocBook: Add initial documentation for IIO 2015-08-04 8:59 ` Daniel Baluta @ 2015-08-04 9:04 ` Daniel Baluta 0 siblings, 0 replies; 7+ messages in thread From: Daniel Baluta @ 2015-08-04 9:04 UTC (permalink / raw) To: Daniel Baluta Cc: Peter Meerwald, Jonathan Cameron, Jonathan Corbet, Hartmut Knaack, Lars-Peter Clausen, Linux Kernel Mailing List, linux-iio@vger.kernel.org, linux-doc 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 = &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. ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2015-08-04 9:04 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-07-31 14:04 [PATCH v4] DocBook documentation for IIO Daniel Baluta 2015-07-31 14:04 ` [PATCH v4] DocBook: Add initial " Daniel Baluta 2015-08-03 8:14 ` Lars-Peter Clausen 2015-08-03 8:29 ` Crt Mori 2015-08-03 9:24 ` Peter Meerwald 2015-08-04 8:59 ` Daniel Baluta 2015-08-04 9:04 ` Daniel Baluta
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).