]>
Commit | Line | Data |
---|---|---|
9d8ae6c8 | 1 | /* Industrialio ring buffer with a lis3l02dq accelerometer |
c57f1ba7 JC |
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 | * | |
9d8ae6c8 | 9 | * This program is primarily intended as an example application. |
c57f1ba7 JC |
10 | */ |
11 | ||
12 | #include <dirent.h> | |
13 | #include <fcntl.h> | |
14 | #include <stdio.h> | |
15 | #include <errno.h> | |
c57f1ba7 JC |
16 | #include <sys/stat.h> |
17 | #include <sys/dir.h> | |
c57f1ba7 | 18 | #include <linux/types.h> |
ceb0525c | 19 | #include "iio_utils.h" |
c57f1ba7 | 20 | |
9d8ae6c8 JC |
21 | const char *device_name = "lis3l02dq"; |
22 | const char *trigger_name_base = "lis3l02dq-dev"; | |
23 | const int num_vals = 3; | |
24 | const int scan_ts = 1; | |
25 | const int buf_len = 128; | |
26 | const int num_loops = 10; | |
c57f1ba7 JC |
27 | |
28 | /* | |
29 | * Could get this from ring bps, but only after starting the ring | |
9d8ae6c8 JC |
30 | * which is a bit late for it to be useful. |
31 | * | |
32 | * Todo: replace with much more generic version based on scan_elements | |
33 | * directory. | |
c57f1ba7 | 34 | */ |
9d8ae6c8 | 35 | int size_from_scanmode(int num_vals, int timestamp) |
c57f1ba7 | 36 | { |
9d8ae6c8 | 37 | if (num_vals && timestamp) |
c57f1ba7 JC |
38 | return 16; |
39 | else if (timestamp) | |
40 | return 8; | |
41 | else | |
9d8ae6c8 | 42 | return num_vals*2; |
c57f1ba7 JC |
43 | } |
44 | ||
45 | int main(int argc, char **argv) | |
46 | { | |
9d8ae6c8 | 47 | int ret; |
c57f1ba7 JC |
48 | int i, j, k, toread; |
49 | FILE *fp_ev; | |
50 | int fp; | |
9d8ae6c8 JC |
51 | |
52 | char *trigger_name, *dev_dir_name, *buf_dir_name; | |
c57f1ba7 JC |
53 | char *data; |
54 | size_t read_size; | |
55 | struct iio_event_data dat; | |
9d8ae6c8 JC |
56 | int dev_num, trig_num; |
57 | ||
58 | char *buffer_access, *buffer_event; | |
59 | const char *iio_dir = "/sys/bus/iio/devices/"; | |
60 | int scan_size; | |
61 | float gain = 1; | |
c57f1ba7 | 62 | |
c57f1ba7 | 63 | |
9d8ae6c8 JC |
64 | /* Find out which iio device is the accelerometer. */ |
65 | dev_num = find_type_by_name(device_name, "device"); | |
66 | if (dev_num < 0) { | |
67 | printf("Failed to find the %s\n", device_name); | |
68 | ret = -ENODEV; | |
69 | goto error_ret; | |
c57f1ba7 | 70 | } |
9d8ae6c8 JC |
71 | printf("iio device number being used is %d\n", dev_num); |
72 | asprintf(&dev_dir_name, "%sdevice%d", iio_dir, dev_num); | |
73 | ||
74 | /* | |
75 | * Build the trigger name. | |
76 | * In this case we want the lis3l02dq's data ready trigger | |
77 | * for this lis3l02dq. The naming is lis3l02dq_dev[n], where | |
78 | * n matches the device number found above. | |
79 | */ | |
80 | ret = asprintf(&trigger_name, "%s%d", trigger_name_base, dev_num); | |
81 | if (ret < 0) { | |
82 | ret = -ENOMEM; | |
83 | goto error_free_dev_dir_name; | |
84 | } | |
85 | ||
86 | /* | |
87 | * Find the trigger by name. | |
88 | * This is techically unecessary here as we only need to | |
89 | * refer to the trigger by name and that name is already | |
90 | * known. | |
91 | */ | |
92 | trig_num = find_type_by_name(trigger_name, "trigger"); | |
93 | if (trig_num < 0) { | |
c57f1ba7 | 94 | printf("Failed to find the %s\n", trigger_name); |
9d8ae6c8 JC |
95 | ret = -ENODEV; |
96 | goto error_free_triggername; | |
c57f1ba7 | 97 | } |
9d8ae6c8 JC |
98 | printf("iio trigger number being used is %d\n", trig_num); |
99 | ||
100 | /* | |
101 | * Read in the scale value - in a more generic case, first | |
102 | * check for accel_scale, then the indivual channel scales | |
103 | */ | |
104 | ret = read_sysfs_float("accel_scale", dev_dir_name, &gain); | |
105 | if (ret) | |
106 | goto error_free_triggername;; | |
107 | ||
108 | /* | |
109 | * Construct the directory name for the associated buffer. | |
110 | * As we know that the lis3l02dq has only one buffer this may | |
111 | * be built rather than found. | |
112 | */ | |
113 | ret = asprintf(&buf_dir_name, "%sdevice%d:buffer0", iio_dir, dev_num); | |
114 | if (ret < 0) { | |
115 | ret = -ENOMEM; | |
116 | goto error_free_triggername; | |
c57f1ba7 | 117 | } |
9d8ae6c8 JC |
118 | /* Set the device trigger to be the data rdy trigger found above */ |
119 | ret = write_sysfs_string_and_verify("trigger/current_trigger", | |
120 | dev_dir_name, | |
121 | trigger_name); | |
122 | if (ret < 0) { | |
123 | printf("Failed to write current_trigger file\n"); | |
124 | goto error_free_buf_dir_name; | |
c57f1ba7 JC |
125 | } |
126 | ||
127 | /* Setup ring buffer parameters */ | |
9d8ae6c8 JC |
128 | ret = write_sysfs_int("length", buf_dir_name, buf_len); |
129 | if (ret < 0) | |
130 | goto error_free_buf_dir_name; | |
c57f1ba7 | 131 | |
9d8ae6c8 | 132 | /* Enable the buffer */ |
04b70812 | 133 | ret = write_sysfs_int("enable", buf_dir_name, 1); |
9d8ae6c8 JC |
134 | if (ret < 0) |
135 | goto error_free_buf_dir_name; | |
c57f1ba7 | 136 | |
9d8ae6c8 | 137 | data = malloc(size_from_scanmode(num_vals, scan_ts)*buf_len); |
c57f1ba7 | 138 | if (!data) { |
9d8ae6c8 JC |
139 | ret = -ENOMEM; |
140 | goto error_free_buf_dir_name; | |
141 | } | |
142 | ||
143 | ret = asprintf(&buffer_access, | |
144 | "/dev/device%d:buffer0:access0", | |
145 | dev_num); | |
146 | if (ret < 0) { | |
147 | ret = -ENOMEM; | |
148 | goto error_free_data; | |
c57f1ba7 JC |
149 | } |
150 | ||
9d8ae6c8 JC |
151 | ret = asprintf(&buffer_event, "/dev/device%d:buffer0:event0", dev_num); |
152 | if (ret < 0) { | |
153 | ret = -ENOMEM; | |
154 | goto error_free_data; | |
155 | } | |
c57f1ba7 | 156 | /* Attempt to open non blocking the access dev */ |
9d8ae6c8 | 157 | fp = open(buffer_access, O_RDONLY | O_NONBLOCK); |
c57f1ba7 | 158 | if (fp == -1) { /*If it isn't there make the node */ |
9d8ae6c8 JC |
159 | printf("Failed to open %s\n", buffer_access); |
160 | ret = -errno; | |
161 | goto error_free_buffer_event; | |
c57f1ba7 JC |
162 | } |
163 | /* Attempt to open the event access dev (blocking this time) */ | |
9d8ae6c8 | 164 | fp_ev = fopen(buffer_event, "rb"); |
c57f1ba7 | 165 | if (fp_ev == NULL) { |
9d8ae6c8 JC |
166 | printf("Failed to open %s\n", buffer_event); |
167 | ret = -errno; | |
168 | goto error_close_buffer_access; | |
c57f1ba7 JC |
169 | } |
170 | ||
171 | /* Wait for events 10 times */ | |
9d8ae6c8 | 172 | for (j = 0; j < num_loops; j++) { |
c57f1ba7 JC |
173 | read_size = fread(&dat, 1, sizeof(struct iio_event_data), |
174 | fp_ev); | |
175 | switch (dat.id) { | |
176 | case IIO_EVENT_CODE_RING_100_FULL: | |
9d8ae6c8 | 177 | toread = buf_len; |
c57f1ba7 JC |
178 | break; |
179 | case IIO_EVENT_CODE_RING_75_FULL: | |
9d8ae6c8 | 180 | toread = buf_len*3/4; |
c57f1ba7 JC |
181 | break; |
182 | case IIO_EVENT_CODE_RING_50_FULL: | |
9d8ae6c8 | 183 | toread = buf_len/2; |
c57f1ba7 JC |
184 | break; |
185 | default: | |
186 | printf("Unexpecteded event code\n"); | |
187 | continue; | |
188 | } | |
189 | read_size = read(fp, | |
190 | data, | |
9d8ae6c8 | 191 | toread*size_from_scanmode(num_vals, scan_ts)); |
c57f1ba7 | 192 | if (read_size == -EAGAIN) { |
9d8ae6c8 | 193 | printf("nothing available\n"); |
c57f1ba7 JC |
194 | continue; |
195 | } | |
9d8ae6c8 JC |
196 | scan_size = size_from_scanmode(num_vals, scan_ts); |
197 | for (i = 0; i < read_size/scan_size; i++) { | |
198 | for (k = 0; k < num_vals; k++) { | |
199 | __s16 val = *(__s16 *)(&data[i*scan_size | |
c57f1ba7 | 200 | + (k)*2]); |
9d8ae6c8 | 201 | printf("%05f ", (float)val*gain); |
c57f1ba7 JC |
202 | } |
203 | printf(" %lld\n", | |
9d8ae6c8 JC |
204 | *(__s64 *)(&data[(i + 1) |
205 | *size_from_scanmode(num_vals, | |
206 | scan_ts) | |
c57f1ba7 JC |
207 | - sizeof(__s64)])); |
208 | } | |
209 | } | |
210 | ||
211 | /* Stop the ring buffer */ | |
04b70812 | 212 | ret = write_sysfs_int("enable", buf_dir_name, 0); |
9d8ae6c8 JC |
213 | if (ret < 0) |
214 | goto error_close_buffer_event; | |
215 | ||
216 | /* Disconnect from the trigger - just write a dummy name.*/ | |
217 | write_sysfs_string("trigger/current_trigger", | |
218 | dev_dir_name, "NULL"); | |
219 | ||
220 | error_close_buffer_event: | |
221 | fclose(fp_ev); | |
222 | error_close_buffer_access: | |
223 | close(fp); | |
224 | error_free_data: | |
c57f1ba7 | 225 | free(data); |
9d8ae6c8 JC |
226 | error_free_buffer_access: |
227 | free(buffer_access); | |
228 | error_free_buffer_event: | |
229 | free(buffer_event); | |
230 | error_free_buf_dir_name: | |
231 | free(buf_dir_name); | |
232 | error_free_triggername: | |
233 | free(trigger_name); | |
234 | error_free_dev_dir_name: | |
235 | free(dev_dir_name); | |
236 | error_ret: | |
237 | return ret; | |
c57f1ba7 | 238 | } |