generic_buffer.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  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. printf("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 == NULL) {
  250. printf("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. printf("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 == NULL) {
  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. printf("Failed to find the trigger %s\n", trigger_name);
  282. ret = trig_num;
  283. goto error_free_triggername;
  284. }
  285. printf("iio trigger number being used is %d\n", trig_num);
  286. } else {
  287. printf("trigger-less mode selected\n");
  288. }
  289. /*
  290. * Parse the files in scan_elements to identify what channels are
  291. * present
  292. */
  293. ret = build_channel_array(dev_dir_name, &channels, &num_channels);
  294. if (ret) {
  295. printf("Problem reading scan element information\n");
  296. printf("diag %s\n", dev_dir_name);
  297. goto error_free_triggername;
  298. }
  299. /*
  300. * Construct the directory name for the associated buffer.
  301. * As we know that the lis3l02dq has only one buffer this may
  302. * be built rather than found.
  303. */
  304. ret = asprintf(&buf_dir_name,
  305. "%siio:device%d/buffer", iio_dir, dev_num);
  306. if (ret < 0) {
  307. ret = -ENOMEM;
  308. goto error_free_channels;
  309. }
  310. if (!notrigger) {
  311. printf("%s %s\n", dev_dir_name, trigger_name);
  312. /*
  313. * Set the device trigger to be the data ready trigger found
  314. * above
  315. */
  316. ret = write_sysfs_string_and_verify("trigger/current_trigger",
  317. dev_dir_name,
  318. trigger_name);
  319. if (ret < 0) {
  320. printf("Failed to write current_trigger file\n");
  321. goto error_free_buf_dir_name;
  322. }
  323. }
  324. /* Setup ring buffer parameters */
  325. ret = write_sysfs_int("length", buf_dir_name, buf_len);
  326. if (ret < 0)
  327. goto error_free_buf_dir_name;
  328. /* Enable the buffer */
  329. ret = write_sysfs_int("enable", buf_dir_name, 1);
  330. if (ret < 0)
  331. goto error_free_buf_dir_name;
  332. scan_size = size_from_channelarray(channels, num_channels);
  333. data = malloc(scan_size * buf_len);
  334. if (!data) {
  335. ret = -ENOMEM;
  336. goto error_free_buf_dir_name;
  337. }
  338. ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num);
  339. if (ret < 0) {
  340. ret = -ENOMEM;
  341. goto error_free_data;
  342. }
  343. /* Attempt to open non blocking the access dev */
  344. fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
  345. if (fp == -1) { /* TODO: If it isn't there make the node */
  346. ret = -errno;
  347. printf("Failed to open %s\n", buffer_access);
  348. goto error_free_buffer_access;
  349. }
  350. for (j = 0; j < num_loops; j++) {
  351. if (!noevents) {
  352. struct pollfd pfd = {
  353. .fd = fp,
  354. .events = POLLIN,
  355. };
  356. ret = poll(&pfd, 1, -1);
  357. if (ret < 0) {
  358. ret = -errno;
  359. goto error_close_buffer_access;
  360. } else if (ret == 0) {
  361. continue;
  362. }
  363. toread = buf_len;
  364. } else {
  365. usleep(timedelay);
  366. toread = 64;
  367. }
  368. read_size = read(fp, data, toread * scan_size);
  369. if (read_size < 0) {
  370. if (errno == EAGAIN) {
  371. printf("nothing available\n");
  372. continue;
  373. } else {
  374. break;
  375. }
  376. }
  377. for (i = 0; i < read_size / scan_size; i++)
  378. process_scan(data + scan_size * i, channels,
  379. num_channels);
  380. }
  381. /* Stop the buffer */
  382. ret = write_sysfs_int("enable", buf_dir_name, 0);
  383. if (ret < 0)
  384. goto error_close_buffer_access;
  385. if (!notrigger)
  386. /* Disconnect the trigger - just write a dummy name. */
  387. ret = write_sysfs_string("trigger/current_trigger",
  388. dev_dir_name, "NULL");
  389. if (ret < 0)
  390. printf("Failed to write to %s\n", dev_dir_name);
  391. error_close_buffer_access:
  392. if (close(fp) == -1)
  393. perror("Failed to close buffer");
  394. error_free_buffer_access:
  395. free(buffer_access);
  396. error_free_data:
  397. free(data);
  398. error_free_buf_dir_name:
  399. free(buf_dir_name);
  400. error_free_channels:
  401. for (i = num_channels - 1; i >= 0; i--) {
  402. free(channels[i].name);
  403. free(channels[i].generic_name);
  404. }
  405. free(channels);
  406. error_free_triggername:
  407. if (datardytrigger)
  408. free(trigger_name);
  409. error_free_dev_dir_name:
  410. free(dev_dir_name);
  411. return ret;
  412. }