Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
generic_buffer.c
Go to the documentation of this file.
1 /* Industrialio buffer test code.
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  * This program is primarily intended as an example application.
10  * Reads the current buffer setup from sysfs and starts a short capture
11  * from the specified device, pretty printing the result after appropriate
12  * conversion.
13  *
14  * Command line parameters
15  * generic_buffer -n <device_name> -t <trigger_name>
16  * If trigger name is not specified the program assumes you want a dataready
17  * trigger associated with the device and goes looking for it.
18  *
19  */
20 
21 #define _GNU_SOURCE
22 
23 #include <unistd.h>
24 #include <dirent.h>
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <errno.h>
28 #include <sys/stat.h>
29 #include <sys/dir.h>
30 #include <linux/types.h>
31 #include <string.h>
32 #include <poll.h>
33 #include <endian.h>
34 #include <getopt.h>
35 #include <inttypes.h>
36 #include "iio_utils.h"
37 
47 {
48  int bytes = 0;
49  int i = 0;
50  while (i < num_channels) {
51  if (bytes % channels[i].bytes == 0)
52  channels[i].location = bytes;
53  else
54  channels[i].location = bytes - bytes%channels[i].bytes
55  + channels[i].bytes;
56  bytes = channels[i].location + channels[i].bytes;
57  i++;
58  }
59  return bytes;
60 }
61 
63 {
64  /* First swap if incorrect endian */
65  if (info->be)
66  input = be16toh((uint16_t)input);
67  else
68  input = le16toh((uint16_t)input);
69 
70  /*
71  * Shift before conversion to avoid sign extension
72  * of left aligned data
73  */
74  input = input >> info->shift;
75  if (info->is_signed) {
76  int16_t val = input;
77  val &= (1 << info->bits_used) - 1;
78  val = (int16_t)(val << (16 - info->bits_used)) >>
79  (16 - info->bits_used);
80  printf("%05f ", ((float)val + info->offset)*info->scale);
81  } else {
82  uint16_t val = input;
83  val &= (1 << info->bits_used) - 1;
84  printf("%05f ", ((float)val + info->offset)*info->scale);
85  }
86 }
95 void process_scan(char *data,
96  struct iio_channel_info *channels,
97  int num_channels)
98 {
99  int k;
100  for (k = 0; k < num_channels; k++)
101  switch (channels[k].bytes) {
102  /* only a few cases implemented so far */
103  case 2:
104  print2byte(*(uint16_t *)(data + channels[k].location),
105  &channels[k]);
106  break;
107  case 4:
108  if (!channels[k].is_signed) {
109  uint32_t val = *(uint32_t *)
110  (data + channels[k].location);
111  printf("%05f ", ((float)val +
112  channels[k].offset)*
113  channels[k].scale);
114 
115  }
116  break;
117  case 8:
118  if (channels[k].is_signed) {
119  int64_t val = *(int64_t *)
120  (data +
121  channels[k].location);
122  if ((val >> channels[k].bits_used) & 1)
123  val = (val & channels[k].mask) |
124  ~channels[k].mask;
125  /* special case for timestamp */
126  if (channels[k].scale == 1.0f &&
127  channels[k].offset == 0.0f)
128  printf("%" PRId64 " ", val);
129  else
130  printf("%05f ", ((float)val +
131  channels[k].offset)*
132  channels[k].scale);
133  }
134  break;
135  default:
136  break;
137  }
138  printf("\n");
139 }
140 
141 int main(int argc, char **argv)
142 {
143  unsigned long num_loops = 2;
144  unsigned long timedelay = 1000000;
145  unsigned long buf_len = 128;
146 
147  int ret, c, i, j, toread;
148  int fp;
149 
150  int num_channels;
151  char *trigger_name = NULL, *device_name = NULL;
152  char *dev_dir_name, *buf_dir_name;
153 
154  int datardytrigger = 1;
155  char *data;
157  int dev_num, trig_num;
158  char *buffer_access;
159  int scan_size;
160  int noevents = 0;
161  char *dummy;
162 
163  struct iio_channel_info *channels;
164 
165  while ((c = getopt(argc, argv, "l:w:c:et:n:")) != -1) {
166  switch (c) {
167  case 'n':
168  device_name = optarg;
169  break;
170  case 't':
171  trigger_name = optarg;
172  datardytrigger = 0;
173  break;
174  case 'e':
175  noevents = 1;
176  break;
177  case 'c':
178  num_loops = strtoul(optarg, &dummy, 10);
179  break;
180  case 'w':
181  timedelay = strtoul(optarg, &dummy, 10);
182  break;
183  case 'l':
184  buf_len = strtoul(optarg, &dummy, 10);
185  break;
186  case '?':
187  return -1;
188  }
189  }
190 
191  if (device_name == NULL)
192  return -1;
193 
194  /* Find the device requested */
195  dev_num = find_type_by_name(device_name, "iio:device");
196  if (dev_num < 0) {
197  printf("Failed to find the %s\n", device_name);
198  ret = -ENODEV;
199  goto error_ret;
200  }
201  printf("iio device number being used is %d\n", dev_num);
202 
203  asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num);
204  if (trigger_name == NULL) {
205  /*
206  * Build the trigger name. If it is device associated its
207  * name is <device_name>_dev[n] where n matches the device
208  * number found above
209  */
210  ret = asprintf(&trigger_name,
211  "%s-dev%d", device_name, dev_num);
212  if (ret < 0) {
213  ret = -ENOMEM;
214  goto error_ret;
215  }
216  }
217 
218  /* Verify the trigger exists */
219  trig_num = find_type_by_name(trigger_name, "trigger");
220  if (trig_num < 0) {
221  printf("Failed to find the trigger %s\n", trigger_name);
222  ret = -ENODEV;
223  goto error_free_triggername;
224  }
225  printf("iio trigger number being used is %d\n", trig_num);
226 
227  /*
228  * Parse the files in scan_elements to identify what channels are
229  * present
230  */
231  ret = build_channel_array(dev_dir_name, &channels, &num_channels);
232  if (ret) {
233  printf("Problem reading scan element information\n");
234  printf("diag %s\n", dev_dir_name);
235  goto error_free_triggername;
236  }
237 
238  /*
239  * Construct the directory name for the associated buffer.
240  * As we know that the lis3l02dq has only one buffer this may
241  * be built rather than found.
242  */
243  ret = asprintf(&buf_dir_name,
244  "%siio:device%d/buffer", iio_dir, dev_num);
245  if (ret < 0) {
246  ret = -ENOMEM;
247  goto error_free_triggername;
248  }
249  printf("%s %s\n", dev_dir_name, trigger_name);
250  /* Set the device trigger to be the data ready trigger found above */
251  ret = write_sysfs_string_and_verify("trigger/current_trigger",
252  dev_dir_name,
253  trigger_name);
254  if (ret < 0) {
255  printf("Failed to write current_trigger file\n");
256  goto error_free_buf_dir_name;
257  }
258 
259  /* Setup ring buffer parameters */
260  ret = write_sysfs_int("length", buf_dir_name, buf_len);
261  if (ret < 0)
262  goto error_free_buf_dir_name;
263 
264  /* Enable the buffer */
265  ret = write_sysfs_int("enable", buf_dir_name, 1);
266  if (ret < 0)
267  goto error_free_buf_dir_name;
268  scan_size = size_from_channelarray(channels, num_channels);
269  data = malloc(scan_size*buf_len);
270  if (!data) {
271  ret = -ENOMEM;
272  goto error_free_buf_dir_name;
273  }
274 
275  ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num);
276  if (ret < 0) {
277  ret = -ENOMEM;
278  goto error_free_data;
279  }
280 
281  /* Attempt to open non blocking the access dev */
282  fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
283  if (fp == -1) { /* If it isn't there make the node */
284  printf("Failed to open %s\n", buffer_access);
285  ret = -errno;
286  goto error_free_buffer_access;
287  }
288 
289  /* Wait for events 10 times */
290  for (j = 0; j < num_loops; j++) {
291  if (!noevents) {
292  struct pollfd pfd = {
293  .fd = fp,
294  .events = POLLIN,
295  };
296 
297  poll(&pfd, 1, -1);
298  toread = buf_len;
299 
300  } else {
301  usleep(timedelay);
302  toread = 64;
303  }
304 
305  read_size = read(fp,
306  data,
307  toread*scan_size);
308  if (read_size == -EAGAIN) {
309  printf("nothing available\n");
310  continue;
311  }
312  for (i = 0; i < read_size/scan_size; i++)
313  process_scan(data + scan_size*i,
314  channels,
315  num_channels);
316  }
317 
318  /* Stop the buffer */
319  ret = write_sysfs_int("enable", buf_dir_name, 0);
320  if (ret < 0)
321  goto error_close_buffer_access;
322 
323  /* Disconnect the trigger - just write a dummy name. */
324  write_sysfs_string("trigger/current_trigger",
325  dev_dir_name, "NULL");
326 
327 error_close_buffer_access:
328  close(fp);
329 error_free_data:
330  free(data);
331 error_free_buffer_access:
332  free(buffer_access);
333 error_free_buf_dir_name:
334  free(buf_dir_name);
335 error_free_triggername:
336  if (datardytrigger)
337  free(trigger_name);
338 error_ret:
339  return ret;
340 }