generic_buffer.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  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. #include <unistd.h>
  21. #include <stdlib.h>
  22. #include <dirent.h>
  23. #include <fcntl.h>
  24. #include <stdio.h>
  25. #include <errno.h>
  26. #include <sys/stat.h>
  27. #include <sys/dir.h>
  28. #include <linux/types.h>
  29. #include <string.h>
  30. #include <poll.h>
  31. #include <endian.h>
  32. #include <getopt.h>
  33. #include <inttypes.h>
  34. #include "iio_utils.h"
  35. /**
  36. * size_from_channelarray() - calculate the storage size of a scan
  37. * @channels: the channel info array
  38. * @num_channels: number of channels
  39. *
  40. * Has the side effect of filling the channels[i].location values used
  41. * in processing the buffer output.
  42. **/
  43. int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
  44. {
  45. int bytes = 0;
  46. int i = 0;
  47. while (i < num_channels) {
  48. if (bytes % channels[i].bytes == 0)
  49. channels[i].location = bytes;
  50. else
  51. channels[i].location = bytes - bytes%channels[i].bytes
  52. + channels[i].bytes;
  53. bytes = channels[i].location + channels[i].bytes;
  54. i++;
  55. }
  56. return bytes;
  57. }
  58. void print2byte(uint16_t input, struct iio_channel_info *info)
  59. {
  60. /* First swap if incorrect endian */
  61. if (info->be)
  62. input = be16toh(input);
  63. else
  64. input = le16toh(input);
  65. /*
  66. * Shift before conversion to avoid sign extension
  67. * of left aligned data
  68. */
  69. input >>= info->shift;
  70. input &= info->mask;
  71. if (info->is_signed) {
  72. int16_t val = (int16_t)(input << (16 - info->bits_used)) >>
  73. (16 - info->bits_used);
  74. printf("%05f ", ((float)val + info->offset) * info->scale);
  75. } else {
  76. printf("%05f ", ((float)input + info->offset) * info->scale);
  77. }
  78. }
  79. void print4byte(uint32_t input, struct iio_channel_info *info)
  80. {
  81. /* First swap if incorrect endian */
  82. if (info->be)
  83. input = be32toh(input);
  84. else
  85. input = le32toh(input);
  86. /*
  87. * Shift before conversion to avoid sign extension
  88. * of left aligned data
  89. */
  90. input >>= info->shift;
  91. input &= info->mask;
  92. if (info->is_signed) {
  93. int32_t val = (int32_t)(input << (32 - info->bits_used)) >>
  94. (32 - info->bits_used);
  95. printf("%05f ", ((float)val + info->offset) * info->scale);
  96. } else {
  97. printf("%05f ", ((float)input + info->offset) * info->scale);
  98. }
  99. }
  100. void print8byte(uint64_t input, struct iio_channel_info *info)
  101. {
  102. /* First swap if incorrect endian */
  103. if (info->be)
  104. input = be64toh(input);
  105. else
  106. input = le64toh(input);
  107. /*
  108. * Shift before conversion to avoid sign extension
  109. * of left aligned data
  110. */
  111. input >>= info->shift;
  112. input &= info->mask;
  113. if (info->is_signed) {
  114. int64_t val = (int64_t)(input << (64 - info->bits_used)) >>
  115. (64 - info->bits_used);
  116. /* special case for timestamp */
  117. if (info->scale == 1.0f && info->offset == 0.0f)
  118. printf("%" PRId64 " ", val);
  119. else
  120. printf("%05f ",
  121. ((float)val + info->offset) * info->scale);
  122. } else {
  123. printf("%05f ", ((float)input + info->offset) * info->scale);
  124. }
  125. }
  126. /**
  127. * process_scan() - print out the values in SI units
  128. * @data: pointer to the start of the scan
  129. * @channels: information about the channels. Note
  130. * size_from_channelarray must have been called first to fill the
  131. * location offsets.
  132. * @num_channels: number of channels
  133. **/
  134. void process_scan(char *data,
  135. struct iio_channel_info *channels,
  136. int num_channels)
  137. {
  138. int k;
  139. for (k = 0; k < num_channels; k++)
  140. switch (channels[k].bytes) {
  141. /* only a few cases implemented so far */
  142. case 2:
  143. print2byte(*(uint16_t *)(data + channels[k].location),
  144. &channels[k]);
  145. break;
  146. case 4:
  147. print4byte(*(uint32_t *)(data + channels[k].location),
  148. &channels[k]);
  149. break;
  150. case 8:
  151. print8byte(*(uint64_t *)(data + channels[k].location),
  152. &channels[k]);
  153. break;
  154. default:
  155. break;
  156. }
  157. printf("\n");
  158. }
  159. void print_usage(void)
  160. {
  161. printf("Usage: generic_buffer [options]...\n"
  162. "Capture, convert and output data from IIO device buffer\n"
  163. " -c <n> Do n conversions\n"
  164. " -e Disable wait for event (new data)\n"
  165. " -g Use trigger-less mode\n"
  166. " -l <n> Set buffer length to n samples\n"
  167. " -n <name> Set device name (mandatory)\n"
  168. " -t <name> Set trigger name\n"
  169. " -w <n> Set delay between reads in us (event-less mode)\n");
  170. }
  171. int main(int argc, char **argv)
  172. {
  173. unsigned long num_loops = 2;
  174. unsigned long timedelay = 1000000;
  175. unsigned long buf_len = 128;
  176. int ret, c, i, j, toread;
  177. int fp;
  178. int num_channels;
  179. char *trigger_name = NULL, *device_name = NULL;
  180. char *dev_dir_name, *buf_dir_name;
  181. int datardytrigger = 1;
  182. char *data;
  183. ssize_t read_size;
  184. int dev_num, trig_num;
  185. char *buffer_access;
  186. int scan_size;
  187. int noevents = 0;
  188. int notrigger = 0;
  189. char *dummy;
  190. struct iio_channel_info *channels;
  191. while ((c = getopt(argc, argv, "c:egl:n:t:w:")) != -1) {
  192. switch (c) {
  193. case 'c':
  194. errno = 0;
  195. num_loops = strtoul(optarg, &dummy, 10);
  196. if (errno)
  197. return -errno;
  198. break;
  199. case 'e':
  200. noevents = 1;
  201. break;
  202. case 'g':
  203. notrigger = 1;
  204. break;
  205. case 'l':
  206. errno = 0;
  207. buf_len = strtoul(optarg, &dummy, 10);
  208. if (errno)
  209. return -errno;
  210. break;
  211. case 'n':
  212. device_name = optarg;
  213. break;
  214. case 't':
  215. trigger_name = optarg;
  216. datardytrigger = 0;
  217. break;
  218. case 'w':
  219. errno = 0;
  220. timedelay = strtoul(optarg, &dummy, 10);
  221. if (errno)
  222. return -errno;
  223. break;
  224. case '?':
  225. print_usage();
  226. return -1;
  227. }
  228. }
  229. if (device_name == NULL) {
  230. printf("Device name not set\n");
  231. print_usage();
  232. return -1;
  233. }
  234. /* Find the device requested */
  235. dev_num = find_type_by_name(device_name, "iio:device");
  236. if (dev_num < 0) {
  237. printf("Failed to find the %s\n", device_name);
  238. return dev_num;
  239. }
  240. printf("iio device number being used is %d\n", dev_num);
  241. ret = asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num);
  242. if (ret < 0)
  243. return -ENOMEM;
  244. if (!notrigger) {
  245. if (trigger_name == NULL) {
  246. /*
  247. * Build the trigger name. If it is device associated
  248. * its name is <device_name>_dev[n] where n matches
  249. * the device number found above.
  250. */
  251. ret = asprintf(&trigger_name,
  252. "%s-dev%d", device_name, dev_num);
  253. if (ret < 0) {
  254. ret = -ENOMEM;
  255. goto error_free_dev_dir_name;
  256. }
  257. }
  258. /* Verify the trigger exists */
  259. trig_num = find_type_by_name(trigger_name, "trigger");
  260. if (trig_num < 0) {
  261. printf("Failed to find the trigger %s\n", trigger_name);
  262. ret = trig_num;
  263. goto error_free_triggername;
  264. }
  265. printf("iio trigger number being used is %d\n", trig_num);
  266. } else
  267. printf("trigger-less mode selected\n");
  268. /*
  269. * Parse the files in scan_elements to identify what channels are
  270. * present
  271. */
  272. ret = build_channel_array(dev_dir_name, &channels, &num_channels);
  273. if (ret) {
  274. printf("Problem reading scan element information\n");
  275. printf("diag %s\n", dev_dir_name);
  276. goto error_free_triggername;
  277. }
  278. /*
  279. * Construct the directory name for the associated buffer.
  280. * As we know that the lis3l02dq has only one buffer this may
  281. * be built rather than found.
  282. */
  283. ret = asprintf(&buf_dir_name,
  284. "%siio:device%d/buffer", iio_dir, dev_num);
  285. if (ret < 0) {
  286. ret = -ENOMEM;
  287. goto error_free_channels;
  288. }
  289. if (!notrigger) {
  290. printf("%s %s\n", dev_dir_name, trigger_name);
  291. /* Set the device trigger to be the data ready trigger found
  292. * above */
  293. ret = write_sysfs_string_and_verify("trigger/current_trigger",
  294. dev_dir_name,
  295. trigger_name);
  296. if (ret < 0) {
  297. printf("Failed to write current_trigger file\n");
  298. goto error_free_buf_dir_name;
  299. }
  300. }
  301. /* Setup ring buffer parameters */
  302. ret = write_sysfs_int("length", buf_dir_name, buf_len);
  303. if (ret < 0)
  304. goto error_free_buf_dir_name;
  305. /* Enable the buffer */
  306. ret = write_sysfs_int("enable", buf_dir_name, 1);
  307. if (ret < 0)
  308. goto error_free_buf_dir_name;
  309. scan_size = size_from_channelarray(channels, num_channels);
  310. data = malloc(scan_size*buf_len);
  311. if (!data) {
  312. ret = -ENOMEM;
  313. goto error_free_buf_dir_name;
  314. }
  315. ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num);
  316. if (ret < 0) {
  317. ret = -ENOMEM;
  318. goto error_free_data;
  319. }
  320. /* Attempt to open non blocking the access dev */
  321. fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
  322. if (fp == -1) { /* If it isn't there make the node */
  323. ret = -errno;
  324. printf("Failed to open %s\n", buffer_access);
  325. goto error_free_buffer_access;
  326. }
  327. /* Wait for events 10 times */
  328. for (j = 0; j < num_loops; j++) {
  329. if (!noevents) {
  330. struct pollfd pfd = {
  331. .fd = fp,
  332. .events = POLLIN,
  333. };
  334. ret = poll(&pfd, 1, -1);
  335. if (ret < 0) {
  336. ret = -errno;
  337. goto error_close_buffer_access;
  338. } else if (ret == 0) {
  339. continue;
  340. }
  341. toread = buf_len;
  342. } else {
  343. usleep(timedelay);
  344. toread = 64;
  345. }
  346. read_size = read(fp,
  347. data,
  348. toread*scan_size);
  349. if (read_size < 0) {
  350. if (errno == EAGAIN) {
  351. printf("nothing available\n");
  352. continue;
  353. } else
  354. break;
  355. }
  356. for (i = 0; i < read_size/scan_size; i++)
  357. process_scan(data + scan_size*i,
  358. channels,
  359. num_channels);
  360. }
  361. /* Stop the buffer */
  362. ret = write_sysfs_int("enable", buf_dir_name, 0);
  363. if (ret < 0)
  364. goto error_close_buffer_access;
  365. if (!notrigger)
  366. /* Disconnect the trigger - just write a dummy name. */
  367. ret = write_sysfs_string("trigger/current_trigger",
  368. dev_dir_name, "NULL");
  369. if (ret < 0)
  370. printf("Failed to write to %s\n", dev_dir_name);
  371. error_close_buffer_access:
  372. if (close(fp) == -1)
  373. perror("Failed to close buffer");
  374. error_free_buffer_access:
  375. free(buffer_access);
  376. error_free_data:
  377. free(data);
  378. error_free_buf_dir_name:
  379. free(buf_dir_name);
  380. error_free_channels:
  381. for (i = num_channels - 1; i >= 0; i--) {
  382. free(channels[i].name);
  383. free(channels[i].generic_name);
  384. }
  385. free(channels);
  386. error_free_triggername:
  387. if (datardytrigger)
  388. free(trigger_name);
  389. error_free_dev_dir_name:
  390. free(dev_dir_name);
  391. return ret;
  392. }