iio_generic_buffer.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Industrialio buffer test code.
  3. *
  4. * Copyright (c) 2008 Jonathan Cameron
  5. *
  6. * This program is primarily intended as an example application.
  7. * Reads the current buffer setup from sysfs and starts a short capture
  8. * from the specified device, pretty printing the result after appropriate
  9. * conversion.
  10. *
  11. * Command line parameters
  12. * generic_buffer -n <device_name> -t <trigger_name>
  13. * If trigger name is not specified the program assumes you want a dataready
  14. * trigger associated with the device and goes looking for it.
  15. */
  16. #include <unistd.h>
  17. #include <stdlib.h>
  18. #include <dirent.h>
  19. #include <fcntl.h>
  20. #include <stdio.h>
  21. #include <errno.h>
  22. #include <sys/stat.h>
  23. #include <sys/dir.h>
  24. #include <linux/types.h>
  25. #include <string.h>
  26. #include <poll.h>
  27. #include <endian.h>
  28. #include <getopt.h>
  29. #include <inttypes.h>
  30. #include <stdbool.h>
  31. #include <signal.h>
  32. #include "iio_utils.h"
  33. /**
  34. * enum autochan - state for the automatic channel enabling mechanism
  35. */
  36. enum autochan {
  37. AUTOCHANNELS_DISABLED,
  38. AUTOCHANNELS_ENABLED,
  39. AUTOCHANNELS_ACTIVE,
  40. };
  41. /**
  42. * size_from_channelarray() - calculate the storage size of a scan
  43. * @channels: the channel info array
  44. * @num_channels: number of channels
  45. *
  46. * Has the side effect of filling the channels[i].location values used
  47. * in processing the buffer output.
  48. **/
  49. int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
  50. {
  51. int bytes = 0;
  52. int i = 0;
  53. while (i < num_channels) {
  54. if (bytes % channels[i].bytes == 0)
  55. channels[i].location = bytes;
  56. else
  57. channels[i].location = bytes - bytes % channels[i].bytes
  58. + channels[i].bytes;
  59. bytes = channels[i].location + channels[i].bytes;
  60. i++;
  61. }
  62. return bytes;
  63. }
  64. void print1byte(uint8_t input, struct iio_channel_info *info)
  65. {
  66. /*
  67. * Shift before conversion to avoid sign extension
  68. * of left aligned data
  69. */
  70. input >>= info->shift;
  71. input &= info->mask;
  72. if (info->is_signed) {
  73. int8_t val = (int8_t)(input << (8 - info->bits_used)) >>
  74. (8 - info->bits_used);
  75. printf("%05f ", ((float)val + info->offset) * info->scale);
  76. } else {
  77. printf("%05f ", ((float)input + info->offset) * info->scale);
  78. }
  79. }
  80. void print2byte(uint16_t input, struct iio_channel_info *info)
  81. {
  82. /* First swap if incorrect endian */
  83. if (info->be)
  84. input = be16toh(input);
  85. else
  86. input = le16toh(input);
  87. /*
  88. * Shift before conversion to avoid sign extension
  89. * of left aligned data
  90. */
  91. input >>= info->shift;
  92. input &= info->mask;
  93. if (info->is_signed) {
  94. int16_t val = (int16_t)(input << (16 - info->bits_used)) >>
  95. (16 - info->bits_used);
  96. printf("%05f ", ((float)val + info->offset) * info->scale);
  97. } else {
  98. printf("%05f ", ((float)input + info->offset) * info->scale);
  99. }
  100. }
  101. void print4byte(uint32_t input, struct iio_channel_info *info)
  102. {
  103. /* First swap if incorrect endian */
  104. if (info->be)
  105. input = be32toh(input);
  106. else
  107. input = le32toh(input);
  108. /*
  109. * Shift before conversion to avoid sign extension
  110. * of left aligned data
  111. */
  112. input >>= info->shift;
  113. input &= info->mask;
  114. if (info->is_signed) {
  115. int32_t val = (int32_t)(input << (32 - info->bits_used)) >>
  116. (32 - info->bits_used);
  117. printf("%05f ", ((float)val + info->offset) * info->scale);
  118. } else {
  119. printf("%05f ", ((float)input + info->offset) * info->scale);
  120. }
  121. }
  122. void print8byte(uint64_t input, struct iio_channel_info *info)
  123. {
  124. /* First swap if incorrect endian */
  125. if (info->be)
  126. input = be64toh(input);
  127. else
  128. input = le64toh(input);
  129. /*
  130. * Shift before conversion to avoid sign extension
  131. * of left aligned data
  132. */
  133. input >>= info->shift;
  134. input &= info->mask;
  135. if (info->is_signed) {
  136. int64_t val = (int64_t)(input << (64 - info->bits_used)) >>
  137. (64 - info->bits_used);
  138. /* special case for timestamp */
  139. if (info->scale == 1.0f && info->offset == 0.0f)
  140. printf("%" PRId64 " ", val);
  141. else
  142. printf("%05f ",
  143. ((float)val + info->offset) * info->scale);
  144. } else {
  145. printf("%05f ", ((float)input + info->offset) * info->scale);
  146. }
  147. }
  148. /**
  149. * process_scan() - print out the values in SI units
  150. * @data: pointer to the start of the scan
  151. * @channels: information about the channels.
  152. * Note: size_from_channelarray must have been called first
  153. * to fill the location offsets.
  154. * @num_channels: number of channels
  155. **/
  156. void process_scan(char *data,
  157. struct iio_channel_info *channels,
  158. int num_channels)
  159. {
  160. int k;
  161. for (k = 0; k < num_channels; k++)
  162. switch (channels[k].bytes) {
  163. /* only a few cases implemented so far */
  164. case 1:
  165. print1byte(*(uint8_t *)(data + channels[k].location),
  166. &channels[k]);
  167. break;
  168. case 2:
  169. print2byte(*(uint16_t *)(data + channels[k].location),
  170. &channels[k]);
  171. break;
  172. case 4:
  173. print4byte(*(uint32_t *)(data + channels[k].location),
  174. &channels[k]);
  175. break;
  176. case 8:
  177. print8byte(*(uint64_t *)(data + channels[k].location),
  178. &channels[k]);
  179. break;
  180. default:
  181. break;
  182. }
  183. printf("\n");
  184. }
  185. static int enable_disable_all_channels(char *dev_dir_name, int enable)
  186. {
  187. const struct dirent *ent;
  188. char scanelemdir[256];
  189. DIR *dp;
  190. int ret;
  191. snprintf(scanelemdir, sizeof(scanelemdir),
  192. FORMAT_SCAN_ELEMENTS_DIR, dev_dir_name);
  193. scanelemdir[sizeof(scanelemdir)-1] = '\0';
  194. dp = opendir(scanelemdir);
  195. if (!dp) {
  196. fprintf(stderr, "Enabling/disabling channels: can't open %s\n",
  197. scanelemdir);
  198. return -EIO;
  199. }
  200. ret = -ENOENT;
  201. while (ent = readdir(dp), ent) {
  202. if (iioutils_check_suffix(ent->d_name, "_en")) {
  203. printf("%sabling: %s\n",
  204. enable ? "En" : "Dis",
  205. ent->d_name);
  206. ret = write_sysfs_int(ent->d_name, scanelemdir,
  207. enable);
  208. if (ret < 0)
  209. fprintf(stderr, "Failed to enable/disable %s\n",
  210. ent->d_name);
  211. }
  212. }
  213. if (closedir(dp) == -1) {
  214. perror("Enabling/disabling channels: "
  215. "Failed to close directory");
  216. return -errno;
  217. }
  218. return 0;
  219. }
  220. void print_usage(void)
  221. {
  222. fprintf(stderr, "Usage: generic_buffer [options]...\n"
  223. "Capture, convert and output data from IIO device buffer\n"
  224. " -a Auto-activate all available channels\n"
  225. " -A Force-activate ALL channels\n"
  226. " -c <n> Do n conversions, or loop forever if n < 0\n"
  227. " -e Disable wait for event (new data)\n"
  228. " -g Use trigger-less mode\n"
  229. " -l <n> Set buffer length to n samples\n"
  230. " --device-name -n <name>\n"
  231. " --device-num -N <num>\n"
  232. " Set device by name or number (mandatory)\n"
  233. " --trigger-name -t <name>\n"
  234. " --trigger-num -T <num>\n"
  235. " Set trigger by name or number\n"
  236. " -w <n> Set delay between reads in us (event-less mode)\n");
  237. }
  238. enum autochan autochannels = AUTOCHANNELS_DISABLED;
  239. char *dev_dir_name = NULL;
  240. char *buf_dir_name = NULL;
  241. bool current_trigger_set = false;
  242. void cleanup(void)
  243. {
  244. int ret;
  245. /* Disable trigger */
  246. if (dev_dir_name && current_trigger_set) {
  247. /* Disconnect the trigger - just write a dummy name. */
  248. ret = write_sysfs_string("trigger/current_trigger",
  249. dev_dir_name, "NULL");
  250. if (ret < 0)
  251. fprintf(stderr, "Failed to disable trigger: %s\n",
  252. strerror(-ret));
  253. current_trigger_set = false;
  254. }
  255. /* Disable buffer */
  256. if (buf_dir_name) {
  257. ret = write_sysfs_int("enable", buf_dir_name, 0);
  258. if (ret < 0)
  259. fprintf(stderr, "Failed to disable buffer: %s\n",
  260. strerror(-ret));
  261. }
  262. /* Disable channels if auto-enabled */
  263. if (dev_dir_name && autochannels == AUTOCHANNELS_ACTIVE) {
  264. ret = enable_disable_all_channels(dev_dir_name, 0);
  265. if (ret)
  266. fprintf(stderr, "Failed to disable all channels\n");
  267. autochannels = AUTOCHANNELS_DISABLED;
  268. }
  269. }
  270. void sig_handler(int signum)
  271. {
  272. fprintf(stderr, "Caught signal %d\n", signum);
  273. cleanup();
  274. exit(-signum);
  275. }
  276. void register_cleanup(void)
  277. {
  278. struct sigaction sa = { .sa_handler = sig_handler };
  279. const int signums[] = { SIGINT, SIGTERM, SIGABRT };
  280. int ret, i;
  281. for (i = 0; i < ARRAY_SIZE(signums); ++i) {
  282. ret = sigaction(signums[i], &sa, NULL);
  283. if (ret) {
  284. perror("Failed to register signal handler");
  285. exit(-1);
  286. }
  287. }
  288. }
  289. static const struct option longopts[] = {
  290. { "device-name", 1, 0, 'n' },
  291. { "device-num", 1, 0, 'N' },
  292. { "trigger-name", 1, 0, 't' },
  293. { "trigger-num", 1, 0, 'T' },
  294. { },
  295. };
  296. int main(int argc, char **argv)
  297. {
  298. long long num_loops = 2;
  299. unsigned long timedelay = 1000000;
  300. unsigned long buf_len = 128;
  301. ssize_t i;
  302. unsigned long long j;
  303. unsigned long toread;
  304. int ret, c;
  305. int fp = -1;
  306. int num_channels = 0;
  307. char *trigger_name = NULL, *device_name = NULL;
  308. char *data = NULL;
  309. ssize_t read_size;
  310. int dev_num = -1, trig_num = -1;
  311. char *buffer_access = NULL;
  312. int scan_size;
  313. int noevents = 0;
  314. int notrigger = 0;
  315. char *dummy;
  316. bool force_autochannels = false;
  317. struct iio_channel_info *channels = NULL;
  318. register_cleanup();
  319. while ((c = getopt_long(argc, argv, "aAc:egl:n:N:t:T:w:?", longopts,
  320. NULL)) != -1) {
  321. switch (c) {
  322. case 'a':
  323. autochannels = AUTOCHANNELS_ENABLED;
  324. break;
  325. case 'A':
  326. autochannels = AUTOCHANNELS_ENABLED;
  327. force_autochannels = true;
  328. break;
  329. case 'c':
  330. errno = 0;
  331. num_loops = strtoll(optarg, &dummy, 10);
  332. if (errno) {
  333. ret = -errno;
  334. goto error;
  335. }
  336. break;
  337. case 'e':
  338. noevents = 1;
  339. break;
  340. case 'g':
  341. notrigger = 1;
  342. break;
  343. case 'l':
  344. errno = 0;
  345. buf_len = strtoul(optarg, &dummy, 10);
  346. if (errno) {
  347. ret = -errno;
  348. goto error;
  349. }
  350. break;
  351. case 'n':
  352. device_name = strdup(optarg);
  353. break;
  354. case 'N':
  355. errno = 0;
  356. dev_num = strtoul(optarg, &dummy, 10);
  357. if (errno) {
  358. ret = -errno;
  359. goto error;
  360. }
  361. break;
  362. case 't':
  363. trigger_name = strdup(optarg);
  364. break;
  365. case 'T':
  366. errno = 0;
  367. trig_num = strtoul(optarg, &dummy, 10);
  368. if (errno)
  369. return -errno;
  370. break;
  371. case 'w':
  372. errno = 0;
  373. timedelay = strtoul(optarg, &dummy, 10);
  374. if (errno) {
  375. ret = -errno;
  376. goto error;
  377. }
  378. break;
  379. case '?':
  380. print_usage();
  381. ret = -1;
  382. goto error;
  383. }
  384. }
  385. /* Find the device requested */
  386. if (dev_num < 0 && !device_name) {
  387. fprintf(stderr, "Device not set\n");
  388. print_usage();
  389. ret = -1;
  390. goto error;
  391. } else if (dev_num >= 0 && device_name) {
  392. fprintf(stderr, "Only one of --device-num or --device-name needs to be set\n");
  393. print_usage();
  394. ret = -1;
  395. goto error;
  396. } else if (dev_num < 0) {
  397. dev_num = find_type_by_name(device_name, "iio:device");
  398. if (dev_num < 0) {
  399. fprintf(stderr, "Failed to find the %s\n", device_name);
  400. ret = dev_num;
  401. goto error;
  402. }
  403. }
  404. printf("iio device number being used is %d\n", dev_num);
  405. ret = asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num);
  406. if (ret < 0)
  407. return -ENOMEM;
  408. /* Fetch device_name if specified by number */
  409. if (!device_name) {
  410. device_name = malloc(IIO_MAX_NAME_LENGTH);
  411. if (!device_name) {
  412. ret = -ENOMEM;
  413. goto error;
  414. }
  415. ret = read_sysfs_string("name", dev_dir_name, device_name);
  416. if (ret < 0) {
  417. fprintf(stderr, "Failed to read name of device %d\n", dev_num);
  418. goto error;
  419. }
  420. }
  421. if (notrigger) {
  422. printf("trigger-less mode selected\n");
  423. } else if (trig_num >= 0) {
  424. char *trig_dev_name;
  425. ret = asprintf(&trig_dev_name, "%strigger%d", iio_dir, trig_num);
  426. if (ret < 0) {
  427. return -ENOMEM;
  428. }
  429. trigger_name = malloc(IIO_MAX_NAME_LENGTH);
  430. ret = read_sysfs_string("name", trig_dev_name, trigger_name);
  431. free(trig_dev_name);
  432. if (ret < 0) {
  433. fprintf(stderr, "Failed to read trigger%d name from\n", trig_num);
  434. return ret;
  435. }
  436. printf("iio trigger number being used is %d\n", trig_num);
  437. } else {
  438. if (!trigger_name) {
  439. /*
  440. * Build the trigger name. If it is device associated
  441. * its name is <device_name>_dev[n] where n matches
  442. * the device number found above.
  443. */
  444. ret = asprintf(&trigger_name,
  445. "%s-dev%d", device_name, dev_num);
  446. if (ret < 0) {
  447. ret = -ENOMEM;
  448. goto error;
  449. }
  450. }
  451. /* Look for this "-devN" trigger */
  452. trig_num = find_type_by_name(trigger_name, "trigger");
  453. if (trig_num < 0) {
  454. /* OK try the simpler "-trigger" suffix instead */
  455. free(trigger_name);
  456. ret = asprintf(&trigger_name,
  457. "%s-trigger", device_name);
  458. if (ret < 0) {
  459. ret = -ENOMEM;
  460. goto error;
  461. }
  462. }
  463. trig_num = find_type_by_name(trigger_name, "trigger");
  464. if (trig_num < 0) {
  465. fprintf(stderr, "Failed to find the trigger %s\n",
  466. trigger_name);
  467. ret = trig_num;
  468. goto error;
  469. }
  470. printf("iio trigger number being used is %d\n", trig_num);
  471. }
  472. /*
  473. * Parse the files in scan_elements to identify what channels are
  474. * present
  475. */
  476. ret = build_channel_array(dev_dir_name, &channels, &num_channels);
  477. if (ret) {
  478. fprintf(stderr, "Problem reading scan element information\n"
  479. "diag %s\n", dev_dir_name);
  480. goto error;
  481. }
  482. if (num_channels && autochannels == AUTOCHANNELS_ENABLED &&
  483. !force_autochannels) {
  484. fprintf(stderr, "Auto-channels selected but some channels "
  485. "are already activated in sysfs\n");
  486. fprintf(stderr, "Proceeding without activating any channels\n");
  487. }
  488. if ((!num_channels && autochannels == AUTOCHANNELS_ENABLED) ||
  489. (autochannels == AUTOCHANNELS_ENABLED && force_autochannels)) {
  490. fprintf(stderr, "Enabling all channels\n");
  491. ret = enable_disable_all_channels(dev_dir_name, 1);
  492. if (ret) {
  493. fprintf(stderr, "Failed to enable all channels\n");
  494. goto error;
  495. }
  496. /* This flags that we need to disable the channels again */
  497. autochannels = AUTOCHANNELS_ACTIVE;
  498. ret = build_channel_array(dev_dir_name, &channels,
  499. &num_channels);
  500. if (ret) {
  501. fprintf(stderr, "Problem reading scan element "
  502. "information\n"
  503. "diag %s\n", dev_dir_name);
  504. goto error;
  505. }
  506. if (!num_channels) {
  507. fprintf(stderr, "Still no channels after "
  508. "auto-enabling, giving up\n");
  509. goto error;
  510. }
  511. }
  512. if (!num_channels && autochannels == AUTOCHANNELS_DISABLED) {
  513. fprintf(stderr,
  514. "No channels are enabled, we have nothing to scan.\n");
  515. fprintf(stderr, "Enable channels manually in "
  516. FORMAT_SCAN_ELEMENTS_DIR
  517. "/*_en or pass -a to autoenable channels and "
  518. "try again.\n", dev_dir_name);
  519. ret = -ENOENT;
  520. goto error;
  521. }
  522. /*
  523. * Construct the directory name for the associated buffer.
  524. * As we know that the lis3l02dq has only one buffer this may
  525. * be built rather than found.
  526. */
  527. ret = asprintf(&buf_dir_name,
  528. "%siio:device%d/buffer", iio_dir, dev_num);
  529. if (ret < 0) {
  530. ret = -ENOMEM;
  531. goto error;
  532. }
  533. if (!notrigger) {
  534. printf("%s %s\n", dev_dir_name, trigger_name);
  535. /*
  536. * Set the device trigger to be the data ready trigger found
  537. * above
  538. */
  539. ret = write_sysfs_string_and_verify("trigger/current_trigger",
  540. dev_dir_name,
  541. trigger_name);
  542. if (ret < 0) {
  543. fprintf(stderr,
  544. "Failed to write current_trigger file\n");
  545. goto error;
  546. }
  547. }
  548. /* Setup ring buffer parameters */
  549. ret = write_sysfs_int("length", buf_dir_name, buf_len);
  550. if (ret < 0)
  551. goto error;
  552. /* Enable the buffer */
  553. ret = write_sysfs_int("enable", buf_dir_name, 1);
  554. if (ret < 0) {
  555. fprintf(stderr,
  556. "Failed to enable buffer: %s\n", strerror(-ret));
  557. goto error;
  558. }
  559. scan_size = size_from_channelarray(channels, num_channels);
  560. data = malloc(scan_size * buf_len);
  561. if (!data) {
  562. ret = -ENOMEM;
  563. goto error;
  564. }
  565. ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num);
  566. if (ret < 0) {
  567. ret = -ENOMEM;
  568. goto error;
  569. }
  570. /* Attempt to open non blocking the access dev */
  571. fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
  572. if (fp == -1) { /* TODO: If it isn't there make the node */
  573. ret = -errno;
  574. fprintf(stderr, "Failed to open %s\n", buffer_access);
  575. goto error;
  576. }
  577. for (j = 0; j < num_loops || num_loops < 0; j++) {
  578. if (!noevents) {
  579. struct pollfd pfd = {
  580. .fd = fp,
  581. .events = POLLIN,
  582. };
  583. ret = poll(&pfd, 1, -1);
  584. if (ret < 0) {
  585. ret = -errno;
  586. goto error;
  587. } else if (ret == 0) {
  588. continue;
  589. }
  590. toread = buf_len;
  591. } else {
  592. usleep(timedelay);
  593. toread = 64;
  594. }
  595. read_size = read(fp, data, toread * scan_size);
  596. if (read_size < 0) {
  597. if (errno == EAGAIN) {
  598. fprintf(stderr, "nothing available\n");
  599. continue;
  600. } else {
  601. break;
  602. }
  603. }
  604. for (i = 0; i < read_size / scan_size; i++)
  605. process_scan(data + scan_size * i, channels,
  606. num_channels);
  607. }
  608. error:
  609. cleanup();
  610. if (fp >= 0 && close(fp) == -1)
  611. perror("Failed to close buffer");
  612. free(buffer_access);
  613. free(data);
  614. free(buf_dir_name);
  615. for (i = num_channels - 1; i >= 0; i--) {
  616. free(channels[i].name);
  617. free(channels[i].generic_name);
  618. }
  619. free(channels);
  620. free(trigger_name);
  621. free(device_name);
  622. free(dev_dir_name);
  623. return ret;
  624. }