PageRenderTime 40ms CodeModel.GetById 36ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/staging/iio/Documentation/generic_buffer.c

https://github.com/jankeromnes/linux
C | 321 lines | 231 code | 28 blank | 62 comment | 39 complexity | a94270a73aab229ad2209addf7fd14be MD5 | raw 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. #include <unistd.h>
  21. #include <dirent.h>
  22. #include <fcntl.h>
  23. #include <stdio.h>
  24. #include <errno.h>
  25. #include <sys/stat.h>
  26. #include <sys/dir.h>
  27. #include <linux/types.h>
  28. #include <string.h>
  29. #include <poll.h>
  30. #include "iio_utils.h"
  31. /**
  32. * size_from_channelarray() - calculate the storage size of a scan
  33. * @channels: the channel info array
  34. * @num_channels: size of the channel info array
  35. *
  36. * Has the side effect of filling the channels[i].location values used
  37. * in processing the buffer output.
  38. **/
  39. int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
  40. {
  41. int bytes = 0;
  42. int i = 0;
  43. while (i < num_channels) {
  44. if (bytes % channels[i].bytes == 0)
  45. channels[i].location = bytes;
  46. else
  47. channels[i].location = bytes - bytes%channels[i].bytes
  48. + channels[i].bytes;
  49. bytes = channels[i].location + channels[i].bytes;
  50. i++;
  51. }
  52. return bytes;
  53. }
  54. void print2byte(int input, struct iio_channel_info *info)
  55. {
  56. /* shift before conversion to avoid sign extension
  57. of left aligned data */
  58. input = input >> info->shift;
  59. if (info->is_signed) {
  60. int16_t val = input;
  61. val &= (1 << info->bits_used) - 1;
  62. val = (int16_t)(val << (16 - info->bits_used)) >>
  63. (16 - info->bits_used);
  64. printf("%05f ", val,
  65. (float)(val + info->offset)*info->scale);
  66. } else {
  67. uint16_t val = input;
  68. val &= (1 << info->bits_used) - 1;
  69. printf("%05f ", ((float)val + info->offset)*info->scale);
  70. }
  71. }
  72. /**
  73. * process_scan() - print out the values in SI units
  74. * @data: pointer to the start of the scan
  75. * @infoarray: information about the channels. Note
  76. * size_from_channelarray must have been called first to fill the
  77. * location offsets.
  78. * @num_channels: the number of active channels
  79. **/
  80. void process_scan(char *data,
  81. struct iio_channel_info *infoarray,
  82. int num_channels)
  83. {
  84. int k;
  85. for (k = 0; k < num_channels; k++)
  86. switch (infoarray[k].bytes) {
  87. /* only a few cases implemented so far */
  88. case 2:
  89. print2byte(*(uint16_t *)(data + infoarray[k].location),
  90. &infoarray[k]);
  91. break;
  92. case 8:
  93. if (infoarray[k].is_signed) {
  94. int64_t val = *(int64_t *)
  95. (data +
  96. infoarray[k].location);
  97. if ((val >> infoarray[k].bits_used) & 1)
  98. val = (val & infoarray[k].mask) |
  99. ~infoarray[k].mask;
  100. /* special case for timestamp */
  101. if (infoarray[k].scale == 1.0f &&
  102. infoarray[k].offset == 0.0f)
  103. printf(" %lld", val);
  104. else
  105. printf("%05f ", ((float)val +
  106. infoarray[k].offset)*
  107. infoarray[k].scale);
  108. }
  109. break;
  110. default:
  111. break;
  112. }
  113. printf("\n");
  114. }
  115. int main(int argc, char **argv)
  116. {
  117. unsigned long num_loops = 2;
  118. unsigned long timedelay = 1000000;
  119. unsigned long buf_len = 128;
  120. int ret, c, i, j, toread;
  121. FILE *fp_ev;
  122. int fp;
  123. int num_channels;
  124. char *trigger_name = NULL, *device_name = NULL;
  125. char *dev_dir_name, *buf_dir_name;
  126. int datardytrigger = 1;
  127. char *data;
  128. ssize_t read_size;
  129. int dev_num, trig_num;
  130. char *buffer_access;
  131. int scan_size;
  132. int noevents = 0;
  133. char *dummy;
  134. struct iio_channel_info *infoarray;
  135. while ((c = getopt(argc, argv, "l:w:c:et:n:")) != -1) {
  136. switch (c) {
  137. case 'n':
  138. device_name = optarg;
  139. break;
  140. case 't':
  141. trigger_name = optarg;
  142. datardytrigger = 0;
  143. break;
  144. case 'e':
  145. noevents = 1;
  146. break;
  147. case 'c':
  148. num_loops = strtoul(optarg, &dummy, 10);
  149. break;
  150. case 'w':
  151. timedelay = strtoul(optarg, &dummy, 10);
  152. break;
  153. case 'l':
  154. buf_len = strtoul(optarg, &dummy, 10);
  155. break;
  156. case '?':
  157. return -1;
  158. }
  159. }
  160. if (device_name == NULL)
  161. return -1;
  162. /* Find the device requested */
  163. dev_num = find_type_by_name(device_name, "iio:device");
  164. if (dev_num < 0) {
  165. printf("Failed to find the %s\n", device_name);
  166. ret = -ENODEV;
  167. goto error_ret;
  168. }
  169. printf("iio device number being used is %d\n", dev_num);
  170. asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num);
  171. if (trigger_name == NULL) {
  172. /*
  173. * Build the trigger name. If it is device associated it's
  174. * name is <device_name>_dev[n] where n matches the device
  175. * number found above
  176. */
  177. ret = asprintf(&trigger_name,
  178. "%s-dev%d", device_name, dev_num);
  179. if (ret < 0) {
  180. ret = -ENOMEM;
  181. goto error_ret;
  182. }
  183. }
  184. /* Verify the trigger exists */
  185. trig_num = find_type_by_name(trigger_name, "trigger");
  186. if (trig_num < 0) {
  187. printf("Failed to find the trigger %s\n", trigger_name);
  188. ret = -ENODEV;
  189. goto error_free_triggername;
  190. }
  191. printf("iio trigger number being used is %d\n", trig_num);
  192. /*
  193. * Parse the files in scan_elements to identify what channels are
  194. * present
  195. */
  196. ret = build_channel_array(dev_dir_name, &infoarray, &num_channels);
  197. if (ret) {
  198. printf("Problem reading scan element information\n");
  199. printf("diag %s\n", dev_dir_name);
  200. goto error_free_triggername;
  201. }
  202. /*
  203. * Construct the directory name for the associated buffer.
  204. * As we know that the lis3l02dq has only one buffer this may
  205. * be built rather than found.
  206. */
  207. ret = asprintf(&buf_dir_name,
  208. "%siio:device%d/buffer", iio_dir, dev_num);
  209. if (ret < 0) {
  210. ret = -ENOMEM;
  211. goto error_free_triggername;
  212. }
  213. printf("%s %s\n", dev_dir_name, trigger_name);
  214. /* Set the device trigger to be the data rdy trigger found above */
  215. ret = write_sysfs_string_and_verify("trigger/current_trigger",
  216. dev_dir_name,
  217. trigger_name);
  218. if (ret < 0) {
  219. printf("Failed to write current_trigger file\n");
  220. goto error_free_buf_dir_name;
  221. }
  222. /* Setup ring buffer parameters */
  223. ret = write_sysfs_int("length", buf_dir_name, buf_len);
  224. if (ret < 0)
  225. goto error_free_buf_dir_name;
  226. /* Enable the buffer */
  227. ret = write_sysfs_int("enable", buf_dir_name, 1);
  228. if (ret < 0)
  229. goto error_free_buf_dir_name;
  230. scan_size = size_from_channelarray(infoarray, num_channels);
  231. data = malloc(scan_size*buf_len);
  232. if (!data) {
  233. ret = -ENOMEM;
  234. goto error_free_buf_dir_name;
  235. }
  236. ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num);
  237. if (ret < 0) {
  238. ret = -ENOMEM;
  239. goto error_free_data;
  240. }
  241. /* Attempt to open non blocking the access dev */
  242. fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
  243. if (fp == -1) { /*If it isn't there make the node */
  244. printf("Failed to open %s\n", buffer_access);
  245. ret = -errno;
  246. goto error_free_buffer_access;
  247. }
  248. /* Wait for events 10 times */
  249. for (j = 0; j < num_loops; j++) {
  250. if (!noevents) {
  251. struct pollfd pfd = {
  252. .fd = fp,
  253. .events = POLLIN,
  254. };
  255. poll(&pfd, 1, -1);
  256. toread = buf_len;
  257. } else {
  258. usleep(timedelay);
  259. toread = 64;
  260. }
  261. read_size = read(fp,
  262. data,
  263. toread*scan_size);
  264. if (read_size == -EAGAIN) {
  265. printf("nothing available\n");
  266. continue;
  267. }
  268. for (i = 0; i < read_size/scan_size; i++)
  269. process_scan(data + scan_size*i,
  270. infoarray,
  271. num_channels);
  272. }
  273. /* Stop the ring buffer */
  274. ret = write_sysfs_int("enable", buf_dir_name, 0);
  275. if (ret < 0)
  276. goto error_close_buffer_access;
  277. /* Disconnect from the trigger - just write a dummy name.*/
  278. write_sysfs_string("trigger/current_trigger",
  279. dev_dir_name, "NULL");
  280. error_close_buffer_access:
  281. close(fp);
  282. error_free_data:
  283. free(data);
  284. error_free_buffer_access:
  285. free(buffer_access);
  286. error_free_buf_dir_name:
  287. free(buf_dir_name);
  288. error_free_triggername:
  289. if (datardytrigger)
  290. free(trigger_name);
  291. error_ret:
  292. return ret;
  293. }