Staging: IIO: Initial documentation
This needs considerably more work, all comments / suggestions welcomed. Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
930bae8667
commit
c57f1ba732
|
@ -0,0 +1,49 @@
|
|||
IIO Device drivers
|
||||
|
||||
This is not intended to provide a comprehensive guide to writing an
|
||||
IIO device driver. For further information see the drivers within the
|
||||
subsystem.
|
||||
|
||||
The crucial structure for device drivers in iio is iio_dev.
|
||||
|
||||
First allocate one using:
|
||||
|
||||
struct iio_dev *indio_dev = iio_allocate_device();
|
||||
|
||||
The fill in the following.
|
||||
|
||||
indio_dev->dev.parent
|
||||
the struct device associated with the underlying hardware.
|
||||
|
||||
indio_dev->num_interrupt_lines
|
||||
number of event triggering hardware lines the device has.
|
||||
|
||||
indio_dev->event_attrs
|
||||
attributes used to enable / disable hardware events - note the
|
||||
attributes are embedded in iio_event_attr structures with an
|
||||
associated iio_event_handler which may or may note be shared.
|
||||
If num_interrupt_lines = 0, then no need to fill this in.
|
||||
|
||||
indio_dev->attrs
|
||||
general attributes such as polled access to device channels.
|
||||
|
||||
indio_dev->dev_data
|
||||
private device specific data.
|
||||
|
||||
indio_dev->driver_module
|
||||
typically set to THIS_MODULE. Used to specify ownership of some
|
||||
iio created resources.
|
||||
|
||||
indio_dev->modes
|
||||
whether direct access and / or ring buffer access is supported.
|
||||
|
||||
Once these are set up, a call to iio_device_register(indio_dev),
|
||||
will register the device with the iio core.
|
||||
|
||||
Worth noting here is that, if a ring buffer is to be used, it can be
|
||||
allocated prior to registering the device with the iio-core, but must
|
||||
be registered afterwards (otherwise the whole parentage of devices
|
||||
gets confused)
|
||||
|
||||
On remove iio_device_unregister(indio_dev) will remove the device from
|
||||
the core, and iio_free_device will clean up.
|
|
@ -0,0 +1,159 @@
|
|||
/* IIO - useful set of util functionality
|
||||
*
|
||||
* Copyright (c) 2008 Jonathan Cameron
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#define IIO_EVENT_CODE_RING_50_FULL 200
|
||||
#define IIO_EVENT_CODE_RING_75_FULL 201
|
||||
#define IIO_EVENT_CODE_RING_100_FULL 202
|
||||
|
||||
struct iio_event_data {
|
||||
int id;
|
||||
__s64 timestamp;
|
||||
};
|
||||
|
||||
|
||||
inline char *find_ring_subelement(const char *directory, const char *subelement)
|
||||
{
|
||||
DIR *dp;
|
||||
const struct dirent *ent;
|
||||
int pos;
|
||||
char temp[100];
|
||||
char *returnstring;
|
||||
dp = opendir(directory);
|
||||
if (dp == NULL) {
|
||||
printf("could not directory: %s\n", directory);
|
||||
return NULL;
|
||||
}
|
||||
while (ent = readdir(dp), ent != NULL) {
|
||||
if (strcmp(ent->d_name, ".") != 0 &&
|
||||
strcmp(ent->d_name, "..") != 0) {
|
||||
if (strncmp(ent->d_name, subelement, strlen(subelement)) == 0) {
|
||||
int length = sprintf(temp, "%s%s%s", directory, ent->d_name, "/");
|
||||
returnstring = malloc(length+1);
|
||||
strncpy(returnstring, temp, length+1);
|
||||
return returnstring;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char *find_type_by_name(const char *name, const char *type)
|
||||
{
|
||||
const char *iio_dir = "/sys/class/iio/";
|
||||
const struct dirent *ent;
|
||||
int cnt, pos, pos2;
|
||||
|
||||
FILE *nameFile;
|
||||
DIR *dp;
|
||||
char thisname[100];
|
||||
char temp[100];
|
||||
|
||||
char *returnstring = NULL;
|
||||
struct stat Stat;
|
||||
pos = sprintf(temp, "%s", iio_dir);
|
||||
dp = opendir(iio_dir);
|
||||
if (dp == NULL) {
|
||||
printf("No industrialio devices available");
|
||||
return NULL;
|
||||
}
|
||||
while (ent = readdir(dp), ent != NULL) {
|
||||
cnt++;
|
||||
/*reject . and .. */
|
||||
if (strcmp(ent->d_name, ".") != 0 &&
|
||||
strcmp(ent->d_name, "..") != 0) {
|
||||
/*make sure it isn't a trigger!*/
|
||||
if (strncmp(ent->d_name, type, strlen(type)) == 0) {
|
||||
/* build full path to new file */
|
||||
pos2 = pos + sprintf(temp + pos, "%s/", ent->d_name);
|
||||
sprintf(temp + pos2, "name");
|
||||
printf("search location %s\n", temp);
|
||||
nameFile = fopen(temp, "r");
|
||||
if (!nameFile) {
|
||||
sprintf(temp + pos2, "modalias", ent->d_name);
|
||||
nameFile = fopen(temp, "r");
|
||||
if (!nameFile) {
|
||||
printf("Failed to find a name for device\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
fscanf(nameFile, "%s", thisname);
|
||||
if (strcmp(name, thisname) == 0) {
|
||||
returnstring = malloc(strlen(temp) + 1);
|
||||
sprintf(temp + pos2, "");
|
||||
strcpy(returnstring, temp);
|
||||
return returnstring;
|
||||
}
|
||||
fclose(nameFile);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int write_sysfs_int(char *filename, char *basedir, int val)
|
||||
{
|
||||
int ret;
|
||||
FILE *sysfsfp;
|
||||
char temp[100];
|
||||
sprintf(temp, "%s%s", basedir, filename);
|
||||
sysfsfp = fopen(temp, "w");
|
||||
if (sysfsfp == NULL)
|
||||
return -1;
|
||||
fprintf(sysfsfp, "%d", val);
|
||||
fclose(sysfsfp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* write_sysfs_string_and_verify() - string write, readback and verify
|
||||
* @filename: name of file to write to
|
||||
* @basedir: the sysfs directory in which the file is to be found
|
||||
* @val: the string to write
|
||||
**/
|
||||
int write_sysfs_string_and_verify(char *filename, char *basedir, char *val)
|
||||
{
|
||||
int ret;
|
||||
FILE *sysfsfp;
|
||||
char temp[100];
|
||||
sprintf(temp, "%s%s", basedir, filename);
|
||||
sysfsfp = fopen(temp, "w");
|
||||
if (sysfsfp == NULL)
|
||||
return -1;
|
||||
fprintf(sysfsfp, "%s", val);
|
||||
fclose(sysfsfp);
|
||||
|
||||
sysfsfp = fopen(temp, "r");
|
||||
if (sysfsfp == NULL)
|
||||
return -1;
|
||||
fscanf(sysfsfp, "%s", temp);
|
||||
if (strcmp(temp, val) != 0) {
|
||||
printf("Possible failure in string write %s to %s%s \n",
|
||||
val,
|
||||
basedir,
|
||||
filename);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_sysfs_posint(char *filename, char *basedir)
|
||||
{
|
||||
int ret;
|
||||
FILE *sysfsfp;
|
||||
char temp[100];
|
||||
sprintf(temp, "%s%s", basedir, filename);
|
||||
sysfsfp = fopen(temp, "r");
|
||||
if (sysfsfp == NULL)
|
||||
return -1;
|
||||
fscanf(sysfsfp, "%d\n", &ret);
|
||||
fclose(sysfsfp);
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
/* Industrialio test ring buffer with a lis3l02dq acceleromter
|
||||
*
|
||||
* Copyright (c) 2008 Jonathan Cameron
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* Assumes suitable udev rules are used to create the dev nodes as named here.
|
||||
*/
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/dir.h>
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <dirent.h>
|
||||
#include "iio_util.h"
|
||||
|
||||
static const char *ring_access = "/dev/iio/lis3l02dq_ring_access";
|
||||
static const char *ring_event = "/dev/iio/lis3l02dq_ring_event";
|
||||
static const char *device_name = "lis3l02dq";
|
||||
static const char *trigger_name = "lis3l02dq-dev0";
|
||||
static int NumVals = 3;
|
||||
static int scan_ts = 1;
|
||||
static int RingLength = 128;
|
||||
|
||||
/*
|
||||
* Could get this from ring bps, but only after starting the ring
|
||||
* which is a bit late for it to be useful
|
||||
*/
|
||||
int size_from_scanmode(int numVals, int timestamp)
|
||||
{
|
||||
if (numVals && timestamp)
|
||||
return 16;
|
||||
else if (timestamp)
|
||||
return 8;
|
||||
else
|
||||
return numVals*2;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, j, k, toread;
|
||||
FILE *fp_ev;
|
||||
int fp;
|
||||
char *data;
|
||||
size_t read_size;
|
||||
struct iio_event_data dat;
|
||||
|
||||
char *BaseDirectoryName,
|
||||
*TriggerDirectoryName,
|
||||
*RingBufferDirectoryName;
|
||||
|
||||
BaseDirectoryName = find_type_by_name(device_name, "device");
|
||||
if (BaseDirectoryName == NULL) {
|
||||
printf("Failed to find the %s \n", device_name);
|
||||
return -1;
|
||||
}
|
||||
TriggerDirectoryName = find_type_by_name(trigger_name, "trigger");
|
||||
if (TriggerDirectoryName == NULL) {
|
||||
printf("Failed to find the %s\n", trigger_name);
|
||||
return -1;
|
||||
}
|
||||
RingBufferDirectoryName = find_ring_subelement(BaseDirectoryName,
|
||||
"ring_buffer");
|
||||
if (RingBufferDirectoryName == NULL) {
|
||||
printf("Failed to find ring buffer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (write_sysfs_string_and_verify("trigger/current_trigger",
|
||||
BaseDirectoryName,
|
||||
(char *)trigger_name) < 0) {
|
||||
printf("Failed to write current_trigger file \n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Setup ring buffer parameters */
|
||||
if (write_sysfs_int("length", RingBufferDirectoryName,
|
||||
RingLength) < 0) {
|
||||
printf("Failed to open the ring buffer length file \n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Enable the ring buffer */
|
||||
if (write_sysfs_int("ring_enable", RingBufferDirectoryName, 1) < 0) {
|
||||
printf("Failed to open the ring buffer control file \n");
|
||||
return -1;
|
||||
};
|
||||
|
||||
data = malloc(size_from_scanmode(NumVals, scan_ts)*RingLength);
|
||||
if (!data) {
|
||||
printf("Could not allocate space for usespace data store\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Attempt to open non blocking the access dev */
|
||||
fp = open(ring_access, O_RDONLY | O_NONBLOCK);
|
||||
if (fp == -1) { /*If it isn't there make the node */
|
||||
printf("Failed to open %s\n", ring_access);
|
||||
return -1;
|
||||
}
|
||||
/* Attempt to open the event access dev (blocking this time) */
|
||||
fp_ev = fopen(ring_event, "rb");
|
||||
if (fp_ev == NULL) {
|
||||
printf("Failed to open %s\n", ring_event);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Wait for events 10 times */
|
||||
for (j = 0; j < 10; j++) {
|
||||
read_size = fread(&dat, 1, sizeof(struct iio_event_data),
|
||||
fp_ev);
|
||||
switch (dat.id) {
|
||||
case IIO_EVENT_CODE_RING_100_FULL:
|
||||
toread = RingLength;
|
||||
break;
|
||||
case IIO_EVENT_CODE_RING_75_FULL:
|
||||
toread = RingLength*3/4;
|
||||
break;
|
||||
case IIO_EVENT_CODE_RING_50_FULL:
|
||||
toread = RingLength/2;
|
||||
break;
|
||||
default:
|
||||
printf("Unexpecteded event code\n");
|
||||
continue;
|
||||
}
|
||||
read_size = read(fp,
|
||||
data,
|
||||
toread*size_from_scanmode(NumVals, scan_ts));
|
||||
if (read_size == -EAGAIN) {
|
||||
printf("nothing available \n");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0;
|
||||
i < read_size/size_from_scanmode(NumVals, scan_ts);
|
||||
i++) {
|
||||
for (k = 0; k < NumVals; k++) {
|
||||
__s16 val = *(__s16 *)(&data[i*size_from_scanmode(NumVals, scan_ts)
|
||||
+ (k)*2]);
|
||||
printf("%05d ", val);
|
||||
}
|
||||
printf(" %lld\n",
|
||||
*(__s64 *)(&data[(i+1)*size_from_scanmode(NumVals, scan_ts)
|
||||
- sizeof(__s64)]));
|
||||
}
|
||||
}
|
||||
|
||||
/* Stop the ring buffer */
|
||||
if (write_sysfs_int("ring_enable", RingBufferDirectoryName, 0) < 0) {
|
||||
printf("Failed to open the ring buffer control file \n");
|
||||
return -1;
|
||||
};
|
||||
|
||||
/* Disconnect from the trigger - writing something that doesn't exist.*/
|
||||
write_sysfs_string_and_verify("trigger/current_trigger",
|
||||
BaseDirectoryName, "NULL");
|
||||
free(BaseDirectoryName);
|
||||
free(TriggerDirectoryName);
|
||||
free(RingBufferDirectoryName);
|
||||
free(data);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
Overview of IIO
|
||||
|
||||
The Industrial I/O subsytem is intended to provide support for devices
|
||||
that in some sense are analog to digital convertors (ADCs). As many
|
||||
actual devices combine some ADCs with digital to analog convertors
|
||||
(DACs) the intention is to add that functionality at a future date
|
||||
(hence the name).
|
||||
|
||||
The aim is to fill the gap between the somewhat similar hwmon and
|
||||
input subsystems. Hwmon is very much directed at low sample rate
|
||||
sensors used in applications such as fan speed control and temperature
|
||||
measurement. Input is, as it's name suggests focused on input
|
||||
devices. In some cases there is considerable overlap between these and
|
||||
IIO.
|
||||
|
||||
A typical device falling into this category would be connected via SPI
|
||||
or I2C.
|
||||
|
||||
Functionality of IIO
|
||||
|
||||
* Basic device registration and handling. This is very similar to
|
||||
hwmon with simple polled access to device channels via sysfs.
|
||||
|
||||
* Event chrdevs. These are similar to input in that they provide a
|
||||
route to user space for hardware triggered events. Such events include
|
||||
threshold detectors, free-fall detectors and more complex action
|
||||
detection. They events themselves are currently very simple with
|
||||
merely an event code and a timestamp. Any data associated with the
|
||||
event must be accessed via polling. Note a given device may have one
|
||||
or more event channel. These events are turned on or off (if possible)
|
||||
via sysfs interfaces.
|
||||
|
||||
* Hardware ring buffer support. Some recent sensors have included
|
||||
fifo / ring buffers on the sensor chip. These greatly reduce the load
|
||||
on the host CPU by buffering relatively large numbers of data samples
|
||||
based on an internal sampling clock. Examples include VTI SCA3000
|
||||
series and Analog Device ADXL345 accelerometers. Each ring buffer
|
||||
typically has an event chrdev (similar to the more general ones above)
|
||||
to pass on events such as buffer 50% full and an access chrdev via
|
||||
which the raw data it self may be read back.
|
||||
|
||||
* Trigger and software ring buffer support. In many data analysis
|
||||
applications it it useful to be able to capture data based on some
|
||||
external signal (trigger). These triggers might be a data ready
|
||||
signal, a gpio line connected to some external system or an on
|
||||
processor periodic interrupt. A single trigger many initialize data
|
||||
capture or reading from a number of sensors. These triggers are
|
||||
used in iio to fill software ring buffers acting in a very similar
|
||||
fashion to the hardware buffers described above.
|
||||
|
||||
Other documentation:
|
||||
|
||||
userspace.txt - overview of ring buffer reading from userspace
|
||||
|
||||
device.txt - elemennts of a typical device driver.
|
||||
|
||||
trigger.txt - elements of a typical trigger driver.
|
||||
|
||||
ring.txt - additional elements required for ring buffer support
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
Ring buffer support within IIO
|
||||
|
||||
This document is intended as a general overview of the functionality
|
||||
a ring buffer may supply and how it is specified within IIO. For more
|
||||
specific information on a given ring buffer implementation, see the
|
||||
comments in the source code. Note that the intention is to allow
|
||||
some drivers to specify ring buffers choice at probe or runtime, but
|
||||
for now the selection is hard coded within a given driver.
|
||||
|
||||
A given ring buffer implementation typically embedded a struct
|
||||
iio_ring_buffer and it is a pointer to this that is provided to the
|
||||
IIO core. Access to the embedding structure is typically done via
|
||||
container_of functions.
|
||||
|
||||
struct iio_ring_buffer contains 4 function pointers
|
||||
(preenable, postenable, predisable, postdisable).
|
||||
These are used to perform implementation specific steps on either side
|
||||
of the core changing it's current mode to indicate that the ring buffer
|
||||
is enabled or disabled (along with enabling triggering etc as appropriate).
|
||||
|
||||
Also in struct iio_ring_buffer is a struct iio_ring_access_funcs.
|
||||
The function pointers within here are used to allow the core to handle
|
||||
as much ring buffer functionality as possible. Note almost all of these
|
||||
are optional.
|
||||
|
||||
mark_in_use, unmark_in_use
|
||||
Basically indicate that not changes should be made to the ring
|
||||
buffer state that will effect the form of the data being captures
|
||||
(e.g. scan elements or length)
|
||||
|
||||
store_to
|
||||
If possible, push data to ring buffer.
|
||||
|
||||
read_last
|
||||
If possible get the most recent entry from the buffer (without removal).
|
||||
This provides polling like functionality whilst the ring buffering is in
|
||||
use without a separate read from the device.
|
||||
|
||||
rip_lots
|
||||
The primary ring buffer reading function. Note that it may well not return
|
||||
as much data as requested. The deadoffset is used to indicate that some
|
||||
initial data in the data array is not guaranteed to be valid.
|
||||
|
||||
mark_param_changed
|
||||
Used to indicate that something has changed. Used in conjunction with
|
||||
request_update
|
||||
If parameters have changed that require reinitialization or configuration of
|
||||
the ring buffer this will trigger it.
|
||||
|
||||
get_bpd, set_bpd
|
||||
Get/set the number of bytes for a given reading (single element, not sample set)
|
||||
The value of bps (bytes per set) is created from a combination of this and the
|
||||
enabled scan elements.
|
||||
|
||||
get_length / set_length
|
||||
Get/set the number of sample sets that may be held by the buffer.
|
||||
|
||||
is_enabled
|
||||
Query if ring buffer is in use
|
||||
enable
|
||||
Start the ring buffer.
|
|
@ -0,0 +1,38 @@
|
|||
IIO trigger drivers.
|
||||
|
||||
Many triggers are provided by hardware that will also be registered as
|
||||
an IIO device. Whilst this can create device specific complexities
|
||||
such triggers are registered with the core in the same way as
|
||||
stand-alone triggers.
|
||||
|
||||
struct iio_trig *trig = iio_allocate_trigger();
|
||||
|
||||
allocates a trigger structure. The key elements to then fill in within
|
||||
a driver are:
|
||||
|
||||
trig->control_attrs
|
||||
Any sysfs attributes needed to control parameters of the trigger
|
||||
|
||||
trig->private_data
|
||||
Device specific private data.
|
||||
|
||||
trig->owner
|
||||
Typically set to THIS_MODULE. Used to ensure correct
|
||||
ownership of core allocated resources.
|
||||
|
||||
trig->name
|
||||
A unique name for the trigger.
|
||||
|
||||
When these have been set call:
|
||||
|
||||
iio_trigger_register(trig);
|
||||
|
||||
to register the trigger with the core, making it available to trigger
|
||||
consumers.
|
||||
|
||||
|
||||
Trigger Consumers
|
||||
|
||||
Currently triggers are only used for the filling of software ring
|
||||
buffers and as such any device supporting INDIO_RING_TRIGGERED has the
|
||||
consumer interface automatically created.
|
|
@ -0,0 +1,60 @@
|
|||
Userspace access to IIO
|
||||
|
||||
Example, ST Microelectronics LIS3L02DQ accelerometer.
|
||||
|
||||
Typical sysfs entries (pruned for clarity)
|
||||
|
||||
/sys/class/iio
|
||||
device0 - iio_dev related elements
|
||||
name - driver specific identifier (here lis3l02dq)
|
||||
accel_x - polled (or from ring) raw readout of acceleration
|
||||
accel_x_gain - hardware gain (calibration)
|
||||
accel_x_offset - hardware offset (calibration)
|
||||
available_sampling_frequency
|
||||
|
||||
available_sampling_frequency - what options are there
|
||||
sampling_frequency - control of internal sampling frequency
|
||||
scan_elements - controls which channels will be stored in the ring buffer
|
||||
scan_en_accel_x
|
||||
scan_en_accel_y
|
||||
scan_en_timestamp
|
||||
device - link to underlying hardware device
|
||||
uevent - udev related element
|
||||
|
||||
thresh - unified threshold used for detection on all axis
|
||||
event_line0_sources - which events are enabled
|
||||
accel_x_high - enable x axis high threshold event
|
||||
accel_x_low - enable x axis low threshold event
|
||||
|
||||
event_line0 - event interface
|
||||
dev - major:minor for the chrdev (note major allocation dynamic)
|
||||
trigger - consumer attachement
|
||||
current_trigger - name based association with a trigger
|
||||
ring_buffer0 - ring buffer interface
|
||||
bps - byptes per sample (read only), dependant on scan element selection
|
||||
length - (rw) specificy length fo software ring buffer (typically ro in hw case)
|
||||
ring_enable - turn the ring on. If its the first to be enabled attached to this
|
||||
trigger will also enable the trigger.
|
||||
ring_access0
|
||||
dev - major:minor for ring buffer access chrdev
|
||||
ring_event_line0
|
||||
dev - major:minor for ring buffer event chrdev
|
||||
|
||||
trigger0 - data ready trigger elements
|
||||
name - unqiue name of trigger
|
||||
|
||||
Udev will create the following entries under /dev by default:
|
||||
|
||||
ring_access0 - ring access chrdev
|
||||
ring_event0 - ring event chrdev
|
||||
event_line0 - general event chrdev.
|
||||
|
||||
For the example code we assume the following rules have been used to ensure
|
||||
unique and consistent naming of these for the lis3l02dq in question:
|
||||
|
||||
KERNEL="ring_event_line*", ID="spi1.0", DRIVER="lis3l02dq", NAME="iio/lis3l02dq_ring_event"
|
||||
KERNEL="event_line*", ID="spi1.0", DRIVER="lis3l02dq", NAME="iio/lis3l02dq_event"
|
||||
KERNEL="ring_access*", ID="spi1.0", DRIVER="lis3l02dq", NAME="iio/lis3l02dq_ring_access"
|
||||
|
||||
The files, lis3l02dqbuffersimple.c and iio_util.h in this directory provide an example
|
||||
of how to use the ring buffer and event interfaces.
|
Loading…
Reference in New Issue