aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Cameron <jic23@cam.ac.uk>2009-08-18 13:06:32 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-15 15:02:25 -0400
commitc57f1ba7326100fd90c35259a588a8484bf569b4 (patch)
tree57bf331086ac7dbb916e79753702bafeaa0713f6
parent930bae8667c100d727360c0fa0df0378af9097ea (diff)
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>
-rw-r--r--drivers/staging/iio/Documentation/device.txt49
-rw-r--r--drivers/staging/iio/Documentation/iio_utils.h159
-rw-r--r--drivers/staging/iio/Documentation/lis3l02dqbuffersimple.c171
-rw-r--r--drivers/staging/iio/Documentation/overview.txt62
-rw-r--r--drivers/staging/iio/Documentation/ring.txt61
-rw-r--r--drivers/staging/iio/Documentation/trigger.txt38
-rw-r--r--drivers/staging/iio/Documentation/userspace.txt60
7 files changed, 600 insertions, 0 deletions
diff --git a/drivers/staging/iio/Documentation/device.txt b/drivers/staging/iio/Documentation/device.txt
new file mode 100644
index 00000000000..6916cd33335
--- /dev/null
+++ b/drivers/staging/iio/Documentation/device.txt
@@ -0,0 +1,49 @@
1IIO Device drivers
2
3This is not intended to provide a comprehensive guide to writing an
4IIO device driver. For further information see the drivers within the
5subsystem.
6
7The crucial structure for device drivers in iio is iio_dev.
8
9First allocate one using:
10
11struct iio_dev *indio_dev = iio_allocate_device();
12
13The fill in the following.
14
15indio_dev->dev.parent
16 the struct device associated with the underlying hardware.
17
18indio_dev->num_interrupt_lines
19 number of event triggering hardware lines the device has.
20
21indio_dev->event_attrs
22 attributes used to enable / disable hardware events - note the
23 attributes are embedded in iio_event_attr structures with an
24 associated iio_event_handler which may or may note be shared.
25 If num_interrupt_lines = 0, then no need to fill this in.
26
27indio_dev->attrs
28 general attributes such as polled access to device channels.
29
30indio_dev->dev_data
31 private device specific data.
32
33indio_dev->driver_module
34 typically set to THIS_MODULE. Used to specify ownership of some
35 iio created resources.
36
37indio_dev->modes
38 whether direct access and / or ring buffer access is supported.
39
40Once these are set up, a call to iio_device_register(indio_dev),
41will register the device with the iio core.
42
43Worth noting here is that, if a ring buffer is to be used, it can be
44allocated prior to registering the device with the iio-core, but must
45be registered afterwards (otherwise the whole parentage of devices
46gets confused)
47
48On remove iio_device_unregister(indio_dev) will remove the device from
49the core, and iio_free_device will clean up.
diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h
new file mode 100644
index 00000000000..74d31247337
--- /dev/null
+++ b/drivers/staging/iio/Documentation/iio_utils.h
@@ -0,0 +1,159 @@
1/* IIO - useful set of util functionality
2 *
3 * Copyright (c) 2008 Jonathan Cameron
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 */
9
10#define IIO_EVENT_CODE_RING_50_FULL 200
11#define IIO_EVENT_CODE_RING_75_FULL 201
12#define IIO_EVENT_CODE_RING_100_FULL 202
13
14struct iio_event_data {
15 int id;
16 __s64 timestamp;
17};
18
19
20inline char *find_ring_subelement(const char *directory, const char *subelement)
21{
22 DIR *dp;
23 const struct dirent *ent;
24 int pos;
25 char temp[100];
26 char *returnstring;
27 dp = opendir(directory);
28 if (dp == NULL) {
29 printf("could not directory: %s\n", directory);
30 return NULL;
31 }
32 while (ent = readdir(dp), ent != NULL) {
33 if (strcmp(ent->d_name, ".") != 0 &&
34 strcmp(ent->d_name, "..") != 0) {
35 if (strncmp(ent->d_name, subelement, strlen(subelement)) == 0) {
36 int length = sprintf(temp, "%s%s%s", directory, ent->d_name, "/");
37 returnstring = malloc(length+1);
38 strncpy(returnstring, temp, length+1);
39 return returnstring;
40
41 }
42 }
43 }
44 return 0;
45}
46
47
48char *find_type_by_name(const char *name, const char *type)
49{
50 const char *iio_dir = "/sys/class/iio/";
51 const struct dirent *ent;
52 int cnt, pos, pos2;
53
54 FILE *nameFile;
55 DIR *dp;
56 char thisname[100];
57 char temp[100];
58
59 char *returnstring = NULL;
60 struct stat Stat;
61 pos = sprintf(temp, "%s", iio_dir);
62 dp = opendir(iio_dir);
63 if (dp == NULL) {
64 printf("No industrialio devices available");
65 return NULL;
66 }
67 while (ent = readdir(dp), ent != NULL) {
68 cnt++;
69 /*reject . and .. */
70 if (strcmp(ent->d_name, ".") != 0 &&
71 strcmp(ent->d_name, "..") != 0) {
72 /*make sure it isn't a trigger!*/
73 if (strncmp(ent->d_name, type, strlen(type)) == 0) {
74 /* build full path to new file */
75 pos2 = pos + sprintf(temp + pos, "%s/", ent->d_name);
76 sprintf(temp + pos2, "name");
77 printf("search location %s\n", temp);
78 nameFile = fopen(temp, "r");
79 if (!nameFile) {
80 sprintf(temp + pos2, "modalias", ent->d_name);
81 nameFile = fopen(temp, "r");
82 if (!nameFile) {
83 printf("Failed to find a name for device\n");
84 return NULL;
85 }
86 }
87 fscanf(nameFile, "%s", thisname);
88 if (strcmp(name, thisname) == 0) {
89 returnstring = malloc(strlen(temp) + 1);
90 sprintf(temp + pos2, "");
91 strcpy(returnstring, temp);
92 return returnstring;
93 }
94 fclose(nameFile);
95
96 }
97 }
98 }
99}
100
101int write_sysfs_int(char *filename, char *basedir, int val)
102{
103 int ret;
104 FILE *sysfsfp;
105 char temp[100];
106 sprintf(temp, "%s%s", basedir, filename);
107 sysfsfp = fopen(temp, "w");
108 if (sysfsfp == NULL)
109 return -1;
110 fprintf(sysfsfp, "%d", val);
111 fclose(sysfsfp);
112 return 0;
113}
114
115/**
116 * write_sysfs_string_and_verify() - string write, readback and verify
117 * @filename: name of file to write to
118 * @basedir: the sysfs directory in which the file is to be found
119 * @val: the string to write
120 **/
121int write_sysfs_string_and_verify(char *filename, char *basedir, char *val)
122{
123 int ret;
124 FILE *sysfsfp;
125 char temp[100];
126 sprintf(temp, "%s%s", basedir, filename);
127 sysfsfp = fopen(temp, "w");
128 if (sysfsfp == NULL)
129 return -1;
130 fprintf(sysfsfp, "%s", val);
131 fclose(sysfsfp);
132
133 sysfsfp = fopen(temp, "r");
134 if (sysfsfp == NULL)
135 return -1;
136 fscanf(sysfsfp, "%s", temp);
137 if (strcmp(temp, val) != 0) {
138 printf("Possible failure in string write %s to %s%s \n",
139 val,
140 basedir,
141 filename);
142 return -1;
143 }
144 return 0;
145}
146
147int read_sysfs_posint(char *filename, char *basedir)
148{
149 int ret;
150 FILE *sysfsfp;
151 char temp[100];
152 sprintf(temp, "%s%s", basedir, filename);
153 sysfsfp = fopen(temp, "r");
154 if (sysfsfp == NULL)
155 return -1;
156 fscanf(sysfsfp, "%d\n", &ret);
157 fclose(sysfsfp);
158 return ret;
159}
diff --git a/drivers/staging/iio/Documentation/lis3l02dqbuffersimple.c b/drivers/staging/iio/Documentation/lis3l02dqbuffersimple.c
new file mode 100644
index 00000000000..2b5cfc58d78
--- /dev/null
+++ b/drivers/staging/iio/Documentation/lis3l02dqbuffersimple.c
@@ -0,0 +1,171 @@
1/* Industrialio test ring buffer with a lis3l02dq acceleromter
2 *
3 * Copyright (c) 2008 Jonathan Cameron
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * Assumes suitable udev rules are used to create the dev nodes as named here.
10 */
11
12#include <dirent.h>
13#include <fcntl.h>
14#include <stdio.h>
15#include <errno.h>
16#include <stdint.h>
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <sys/dir.h>
20
21#include <linux/types.h>
22#include <dirent.h>
23#include "iio_util.h"
24
25static const char *ring_access = "/dev/iio/lis3l02dq_ring_access";
26static const char *ring_event = "/dev/iio/lis3l02dq_ring_event";
27static const char *device_name = "lis3l02dq";
28static const char *trigger_name = "lis3l02dq-dev0";
29static int NumVals = 3;
30static int scan_ts = 1;
31static int RingLength = 128;
32
33/*
34 * Could get this from ring bps, but only after starting the ring
35 * which is a bit late for it to be useful
36 */
37int size_from_scanmode(int numVals, int timestamp)
38{
39 if (numVals && timestamp)
40 return 16;
41 else if (timestamp)
42 return 8;
43 else
44 return numVals*2;
45}
46
47int main(int argc, char **argv)
48{
49 int i, j, k, toread;
50 FILE *fp_ev;
51 int fp;
52 char *data;
53 size_t read_size;
54 struct iio_event_data dat;
55
56 char *BaseDirectoryName,
57 *TriggerDirectoryName,
58 *RingBufferDirectoryName;
59
60 BaseDirectoryName = find_type_by_name(device_name, "device");
61 if (BaseDirectoryName == NULL) {
62 printf("Failed to find the %s \n", device_name);
63 return -1;
64 }
65 TriggerDirectoryName = find_type_by_name(trigger_name, "trigger");
66 if (TriggerDirectoryName == NULL) {
67 printf("Failed to find the %s\n", trigger_name);
68 return -1;
69 }
70 RingBufferDirectoryName = find_ring_subelement(BaseDirectoryName,
71 "ring_buffer");
72 if (RingBufferDirectoryName == NULL) {
73 printf("Failed to find ring buffer\n");
74 return -1;
75 }
76
77 if (write_sysfs_string_and_verify("trigger/current_trigger",
78 BaseDirectoryName,
79 (char *)trigger_name) < 0) {
80 printf("Failed to write current_trigger file \n");
81 return -1;
82 }
83
84 /* Setup ring buffer parameters */
85 if (write_sysfs_int("length", RingBufferDirectoryName,
86 RingLength) < 0) {
87 printf("Failed to open the ring buffer length file \n");
88 return -1;
89 }
90
91 /* Enable the ring buffer */
92 if (write_sysfs_int("ring_enable", RingBufferDirectoryName, 1) < 0) {
93 printf("Failed to open the ring buffer control file \n");
94 return -1;
95 };
96
97 data = malloc(size_from_scanmode(NumVals, scan_ts)*RingLength);
98 if (!data) {
99 printf("Could not allocate space for usespace data store\n");
100 return -1;
101 }
102
103 /* Attempt to open non blocking the access dev */
104 fp = open(ring_access, O_RDONLY | O_NONBLOCK);
105 if (fp == -1) { /*If it isn't there make the node */
106 printf("Failed to open %s\n", ring_access);
107 return -1;
108 }
109 /* Attempt to open the event access dev (blocking this time) */
110 fp_ev = fopen(ring_event, "rb");
111 if (fp_ev == NULL) {
112 printf("Failed to open %s\n", ring_event);
113 return -1;
114 }
115
116 /* Wait for events 10 times */
117 for (j = 0; j < 10; j++) {
118 read_size = fread(&dat, 1, sizeof(struct iio_event_data),
119 fp_ev);
120 switch (dat.id) {
121 case IIO_EVENT_CODE_RING_100_FULL:
122 toread = RingLength;
123 break;
124 case IIO_EVENT_CODE_RING_75_FULL:
125 toread = RingLength*3/4;
126 break;
127 case IIO_EVENT_CODE_RING_50_FULL:
128 toread = RingLength/2;
129 break;
130 default:
131 printf("Unexpecteded event code\n");
132 continue;
133 }
134 read_size = read(fp,
135 data,
136 toread*size_from_scanmode(NumVals, scan_ts));
137 if (read_size == -EAGAIN) {
138 printf("nothing available \n");
139 continue;
140 }
141
142 for (i = 0;
143 i < read_size/size_from_scanmode(NumVals, scan_ts);
144 i++) {
145 for (k = 0; k < NumVals; k++) {
146 __s16 val = *(__s16 *)(&data[i*size_from_scanmode(NumVals, scan_ts)
147 + (k)*2]);
148 printf("%05d ", val);
149 }
150 printf(" %lld\n",
151 *(__s64 *)(&data[(i+1)*size_from_scanmode(NumVals, scan_ts)
152 - sizeof(__s64)]));
153 }
154 }
155
156 /* Stop the ring buffer */
157 if (write_sysfs_int("ring_enable", RingBufferDirectoryName, 0) < 0) {
158 printf("Failed to open the ring buffer control file \n");
159 return -1;
160 };
161
162 /* Disconnect from the trigger - writing something that doesn't exist.*/
163 write_sysfs_string_and_verify("trigger/current_trigger",
164 BaseDirectoryName, "NULL");
165 free(BaseDirectoryName);
166 free(TriggerDirectoryName);
167 free(RingBufferDirectoryName);
168 free(data);
169
170 return 0;
171}
diff --git a/drivers/staging/iio/Documentation/overview.txt b/drivers/staging/iio/Documentation/overview.txt
new file mode 100644
index 00000000000..64584ad4024
--- /dev/null
+++ b/drivers/staging/iio/Documentation/overview.txt
@@ -0,0 +1,62 @@
1Overview of IIO
2
3The Industrial I/O subsytem is intended to provide support for devices
4that in some sense are analog to digital convertors (ADCs). As many
5actual devices combine some ADCs with digital to analog convertors
6(DACs) the intention is to add that functionality at a future date
7(hence the name).
8
9The aim is to fill the gap between the somewhat similar hwmon and
10input subsystems. Hwmon is very much directed at low sample rate
11sensors used in applications such as fan speed control and temperature
12measurement. Input is, as it's name suggests focused on input
13devices. In some cases there is considerable overlap between these and
14IIO.
15
16A typical device falling into this category would be connected via SPI
17or I2C.
18
19Functionality of IIO
20
21* Basic device registration and handling. This is very similar to
22hwmon with simple polled access to device channels via sysfs.
23
24* Event chrdevs. These are similar to input in that they provide a
25route to user space for hardware triggered events. Such events include
26threshold detectors, free-fall detectors and more complex action
27detection. They events themselves are currently very simple with
28merely an event code and a timestamp. Any data associated with the
29event must be accessed via polling. Note a given device may have one
30or more event channel. These events are turned on or off (if possible)
31via sysfs interfaces.
32
33* Hardware ring buffer support. Some recent sensors have included
34fifo / ring buffers on the sensor chip. These greatly reduce the load
35on the host CPU by buffering relatively large numbers of data samples
36based on an internal sampling clock. Examples include VTI SCA3000
37series and Analog Device ADXL345 accelerometers. Each ring buffer
38typically has an event chrdev (similar to the more general ones above)
39to pass on events such as buffer 50% full and an access chrdev via
40which the raw data it self may be read back.
41
42* Trigger and software ring buffer support. In many data analysis
43applications it it useful to be able to capture data based on some
44external signal (trigger). These triggers might be a data ready
45signal, a gpio line connected to some external system or an on
46processor periodic interrupt. A single trigger many initialize data
47capture or reading from a number of sensors. These triggers are
48used in iio to fill software ring buffers acting in a very similar
49fashion to the hardware buffers described above.
50
51Other documentation:
52
53userspace.txt - overview of ring buffer reading from userspace
54
55device.txt - elemennts of a typical device driver.
56
57trigger.txt - elements of a typical trigger driver.
58
59ring.txt - additional elements required for ring buffer support
60
61
62
diff --git a/drivers/staging/iio/Documentation/ring.txt b/drivers/staging/iio/Documentation/ring.txt
new file mode 100644
index 00000000000..d2ca6834c16
--- /dev/null
+++ b/drivers/staging/iio/Documentation/ring.txt
@@ -0,0 +1,61 @@
1Ring buffer support within IIO
2
3This document is intended as a general overview of the functionality
4a ring buffer may supply and how it is specified within IIO. For more
5specific information on a given ring buffer implementation, see the
6comments in the source code. Note that the intention is to allow
7some drivers to specify ring buffers choice at probe or runtime, but
8for now the selection is hard coded within a given driver.
9
10A given ring buffer implementation typically embedded a struct
11iio_ring_buffer and it is a pointer to this that is provided to the
12IIO core. Access to the embedding structure is typically done via
13container_of functions.
14
15struct iio_ring_buffer contains 4 function pointers
16(preenable, postenable, predisable, postdisable).
17These are used to perform implementation specific steps on either side
18of the core changing it's current mode to indicate that the ring buffer
19is enabled or disabled (along with enabling triggering etc as appropriate).
20
21Also in struct iio_ring_buffer is a struct iio_ring_access_funcs.
22The function pointers within here are used to allow the core to handle
23as much ring buffer functionality as possible. Note almost all of these
24are optional.
25
26mark_in_use, unmark_in_use
27 Basically indicate that not changes should be made to the ring
28 buffer state that will effect the form of the data being captures
29 (e.g. scan elements or length)
30
31store_to
32 If possible, push data to ring buffer.
33
34read_last
35 If possible get the most recent entry from the buffer (without removal).
36 This provides polling like functionality whilst the ring buffering is in
37 use without a separate read from the device.
38
39rip_lots
40 The primary ring buffer reading function. Note that it may well not return
41 as much data as requested. The deadoffset is used to indicate that some
42 initial data in the data array is not guaranteed to be valid.
43
44mark_param_changed
45 Used to indicate that something has changed. Used in conjunction with
46request_update
47 If parameters have changed that require reinitialization or configuration of
48 the ring buffer this will trigger it.
49
50get_bpd, set_bpd
51 Get/set the number of bytes for a given reading (single element, not sample set)
52 The value of bps (bytes per set) is created from a combination of this and the
53 enabled scan elements.
54
55get_length / set_length
56 Get/set the number of sample sets that may be held by the buffer.
57
58is_enabled
59 Query if ring buffer is in use
60enable
61 Start the ring buffer.
diff --git a/drivers/staging/iio/Documentation/trigger.txt b/drivers/staging/iio/Documentation/trigger.txt
new file mode 100644
index 00000000000..650157f5c9d
--- /dev/null
+++ b/drivers/staging/iio/Documentation/trigger.txt
@@ -0,0 +1,38 @@
1IIO trigger drivers.
2
3Many triggers are provided by hardware that will also be registered as
4an IIO device. Whilst this can create device specific complexities
5such triggers are registered with the core in the same way as
6stand-alone triggers.
7
8struct iio_trig *trig = iio_allocate_trigger();
9
10allocates a trigger structure. The key elements to then fill in within
11a driver are:
12
13trig->control_attrs
14 Any sysfs attributes needed to control parameters of the trigger
15
16trig->private_data
17 Device specific private data.
18
19trig->owner
20 Typically set to THIS_MODULE. Used to ensure correct
21 ownership of core allocated resources.
22
23trig->name
24 A unique name for the trigger.
25
26When these have been set call:
27
28iio_trigger_register(trig);
29
30to register the trigger with the core, making it available to trigger
31consumers.
32
33
34Trigger Consumers
35
36Currently triggers are only used for the filling of software ring
37buffers and as such any device supporting INDIO_RING_TRIGGERED has the
38consumer interface automatically created.
diff --git a/drivers/staging/iio/Documentation/userspace.txt b/drivers/staging/iio/Documentation/userspace.txt
new file mode 100644
index 00000000000..661015a0b86
--- /dev/null
+++ b/drivers/staging/iio/Documentation/userspace.txt
@@ -0,0 +1,60 @@
1Userspace access to IIO
2
3Example, ST Microelectronics LIS3L02DQ accelerometer.
4
5Typical sysfs entries (pruned for clarity)
6
7/sys/class/iio
8 device0 - iio_dev related elements
9 name - driver specific identifier (here lis3l02dq)
10 accel_x - polled (or from ring) raw readout of acceleration
11 accel_x_gain - hardware gain (calibration)
12 accel_x_offset - hardware offset (calibration)
13 available_sampling_frequency
14
15 available_sampling_frequency - what options are there
16 sampling_frequency - control of internal sampling frequency
17 scan_elements - controls which channels will be stored in the ring buffer
18 scan_en_accel_x
19 scan_en_accel_y
20 scan_en_timestamp
21 device - link to underlying hardware device
22 uevent - udev related element
23
24 thresh - unified threshold used for detection on all axis
25 event_line0_sources - which events are enabled
26 accel_x_high - enable x axis high threshold event
27 accel_x_low - enable x axis low threshold event
28
29 event_line0 - event interface
30 dev - major:minor for the chrdev (note major allocation dynamic)
31 trigger - consumer attachement
32 current_trigger - name based association with a trigger
33 ring_buffer0 - ring buffer interface
34 bps - byptes per sample (read only), dependant on scan element selection
35 length - (rw) specificy length fo software ring buffer (typically ro in hw case)
36 ring_enable - turn the ring on. If its the first to be enabled attached to this
37 trigger will also enable the trigger.
38 ring_access0
39 dev - major:minor for ring buffer access chrdev
40 ring_event_line0
41 dev - major:minor for ring buffer event chrdev
42
43 trigger0 - data ready trigger elements
44 name - unqiue name of trigger
45
46Udev will create the following entries under /dev by default:
47
48ring_access0 - ring access chrdev
49ring_event0 - ring event chrdev
50event_line0 - general event chrdev.
51
52For the example code we assume the following rules have been used to ensure
53unique and consistent naming of these for the lis3l02dq in question:
54
55KERNEL="ring_event_line*", ID="spi1.0", DRIVER="lis3l02dq", NAME="iio/lis3l02dq_ring_event"
56KERNEL="event_line*", ID="spi1.0", DRIVER="lis3l02dq", NAME="iio/lis3l02dq_event"
57KERNEL="ring_access*", ID="spi1.0", DRIVER="lis3l02dq", NAME="iio/lis3l02dq_ring_access"
58
59The files, lis3l02dqbuffersimple.c and iio_util.h in this directory provide an example
60of how to use the ring buffer and event interfaces.