generic_buffer.c 11 KB

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