123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- =============
- Core elements
- =============
- The Industrial I/O core offers a unified framework for writing drivers for
- many different types of embedded sensors. a standard interface to user space
- applications manipulating sensors. The implementation can be found under
- :file:`drivers/iio/industrialio-*`
- Industrial I/O Devices
- ----------------------
- * struct :c:type:`iio_dev` - industrial I/O device
- * :c:func:`iio_device_alloc()` - alocate an :c:type:`iio_dev` from a driver
- * :c:func:`iio_device_free()` - free an :c:type:`iio_dev` from a driver
- * :c:func:`iio_device_register()` - register a device with the IIO subsystem
- * :c:func:`iio_device_unregister()` - unregister a device from the IIO
- subsystem
- 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.
- There are two ways for a user space application to interact with an IIO driver.
- 1. :file:`/sys/bus/iio/iio:device{X}/`, this represents a hardware sensor
- and groups together the data channels of the same chip.
- 2. :file:`/dev/iio:device{X}`, character device node interface used for
- buffered data transfer and for events information retrieval.
- A typical IIO driver will register itself as an :doc:`I2C <../i2c>` or
- :doc:`SPI <../spi>` driver and will create two routines, probe and remove.
- At probe:
- 1. Call :c:func:`iio_device_alloc()`, which allocates memory for an IIO device.
- 2. Initialize IIO device fields with driver specific information (e.g.
- device name, device channels).
- 3. Call :c:func:`iio_device_register()`, this registers the device with the
- IIO core. After this call the device is ready to accept requests from user
- space applications.
- At remove, we free the resources allocated in probe in reverse order:
- 1. :c:func:`iio_device_unregister()`, unregister the device from the IIO core.
- 2. :c:func:`iio_device_free()`, free the memory allocated for the IIO device.
- IIO device sysfs interface
- ==========================
- 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 /sys/bus/iio/iio:deviceX/ directory.
- Common attributes are:
- * :file:`name`, description of the physical chip.
- * :file:`dev`, shows the major:minor pair associated with
- :file:`/dev/iio:deviceX` node.
- * :file:`sampling_frequency_available`, available discrete set of sampling
- frequency values for device.
- * Available standard attributes for IIO devices are described in the
- :file:`Documentation/ABI/testing/sysfs-bus-iio` file in the Linux kernel
- sources.
- IIO device channels
- ===================
- struct :c:type:`iio_chan_spec` - specification of a single channel
- An IIO device channel is a representation of a data channel. An IIO device can
- have one or multiple channels. For example:
- * a thermometer sensor has one channel representing the temperature measurement.
- * a light sensor with two channels indicating the measurements in the visible
- and infrared spectrum.
- * an accelerometer can have up to 3 channels representing acceleration on X, Y
- and Z axes.
- An IIO channel is described by the struct :c:type:`iio_chan_spec`.
- A thermometer driver for the temperature sensor in the example above would
- have to describe its channel as follows::
- static const struct iio_chan_spec temp_channel[] = {
- {
- .type = IIO_TEMP,
- .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
- },
- };
- Channel sysfs attributes exposed to userspace are specified in the form of
- bitmasks. Depending on their shared info, attributes can be set in one of the
- following masks:
- * **info_mask_separate**, attributes will be specific to
- this channel
- * **info_mask_shared_by_type**, attributes are shared by all channels of the
- same type
- * **info_mask_shared_by_dir**, attributes are shared by all channels of the same
- direction
- * **info_mask_shared_by_all**, attributes are shared by all channels
- When there are multiple data channels per channel type we have two ways to
- distinguish between them:
- * set **.modified** field of :c:type:`iio_chan_spec` to 1. Modifiers are
- specified using **.channel2** field of the same :c:type:`iio_chan_spec`
- 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.
- * set **.indexed** field of :c:type:`iio_chan_spec` to 1. In this case the
- channel is simply another instance with an index specified by the **.channel**
- field.
- Here is how we can make use of the channel's modifiers::
- 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),
- },
- }
- This channel's definition will generate two separate sysfs files for raw data
- retrieval:
- * :file:`/sys/bus/iio/iio:device{X}/in_intensity_ir_raw`
- * :file:`/sys/bus/iio/iio:device{X}/in_intensity_both_raw`
- one file for processed data:
- * :file:`/sys/bus/iio/iio:device{X}/in_illuminance_input`
- and one shared sysfs file for sampling frequency:
- * :file:`/sys/bus/iio/iio:device{X}/sampling_frequency`.
- Here is how we can make use of the channel's indexing::
- 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),
- },
- }
- This will generate two separate attributes files for raw data retrieval:
- * :file:`/sys/bus/iio/devices/iio:device{X}/in_voltage0_raw`, representing
- voltage measurement for channel 0.
- * :file:`/sys/bus/iio/devices/iio:device{X}/in_voltage1_raw`, representing
- voltage measurement for channel 1.
- More details
- ============
- .. kernel-doc:: include/linux/iio/iio.h
- .. kernel-doc:: drivers/iio/industrialio-core.c
- :export:
|