iio_utils.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985
  1. /* IIO - useful set of util functionality
  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. #ifndef _IIO_UTILS_H
  10. #define _IIO_UTILS_H
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14. #include <stdint.h>
  15. #include <dirent.h>
  16. #include <errno.h>
  17. #include <ctype.h>
  18. #include "iio_utils.h"
  19. const char *iio_dir = "/sys/bus/iio/devices/";
  20. static char * const iio_direction[] = {
  21. "in",
  22. "out",
  23. };
  24. /**
  25. * iioutils_break_up_name() - extract generic name from full channel name
  26. * @full_name: the full channel name
  27. * @generic_name: the output generic channel name
  28. *
  29. * Returns 0 on success, or a negative error code if string extraction failed.
  30. **/
  31. int iioutils_break_up_name(const char *full_name, char **generic_name)
  32. {
  33. char *current;
  34. char *w, *r;
  35. char *working, *prefix = "";
  36. int i, ret;
  37. for (i = 0; i < sizeof(iio_direction) / sizeof(iio_direction[0]); i++)
  38. if (!strncmp(full_name, iio_direction[i],
  39. strlen(iio_direction[i]))) {
  40. prefix = iio_direction[i];
  41. break;
  42. }
  43. current = strdup(full_name + strlen(prefix) + 1);
  44. if (!current)
  45. return -ENOMEM;
  46. working = strtok(current, "_\0");
  47. if (!working) {
  48. free(current);
  49. return -EINVAL;
  50. }
  51. w = working;
  52. r = working;
  53. while (*r != '\0') {
  54. if (!isdigit(*r)) {
  55. *w = *r;
  56. w++;
  57. }
  58. r++;
  59. }
  60. *w = '\0';
  61. ret = asprintf(generic_name, "%s_%s", prefix, working);
  62. free(current);
  63. return (ret == -1) ? -ENOMEM : 0;
  64. }
  65. /**
  66. * iioutils_get_type() - find and process _type attribute data
  67. * @is_signed: output whether channel is signed
  68. * @bytes: output how many bytes the channel storage occupies
  69. * @bits_used: output number of valid bits of data
  70. * @shift: output amount of bits to shift right data before applying bit mask
  71. * @mask: output a bit mask for the raw data
  72. * @be: output if data in big endian
  73. * @device_dir: the IIO device directory
  74. * @name: the channel name
  75. * @generic_name: the channel type name
  76. *
  77. * Returns a value >= 0 on success, otherwise a negative error code.
  78. **/
  79. int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
  80. unsigned *shift, uint64_t *mask, unsigned *be,
  81. const char *device_dir, const char *name,
  82. const char *generic_name)
  83. {
  84. FILE *sysfsfp;
  85. int ret;
  86. DIR *dp;
  87. char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
  88. char signchar, endianchar;
  89. unsigned padint;
  90. const struct dirent *ent;
  91. ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
  92. if (ret < 0)
  93. return -ENOMEM;
  94. ret = asprintf(&builtname, FORMAT_TYPE_FILE, name);
  95. if (ret < 0) {
  96. ret = -ENOMEM;
  97. goto error_free_scan_el_dir;
  98. }
  99. ret = asprintf(&builtname_generic, FORMAT_TYPE_FILE, generic_name);
  100. if (ret < 0) {
  101. ret = -ENOMEM;
  102. goto error_free_builtname;
  103. }
  104. dp = opendir(scan_el_dir);
  105. if (dp == NULL) {
  106. ret = -errno;
  107. goto error_free_builtname_generic;
  108. }
  109. ret = -ENOENT;
  110. while (ent = readdir(dp), ent != NULL)
  111. /*
  112. * Do we allow devices to override a generic name with
  113. * a specific one?
  114. */
  115. if ((strcmp(builtname, ent->d_name) == 0) ||
  116. (strcmp(builtname_generic, ent->d_name) == 0)) {
  117. ret = asprintf(&filename,
  118. "%s/%s", scan_el_dir, ent->d_name);
  119. if (ret < 0) {
  120. ret = -ENOMEM;
  121. goto error_closedir;
  122. }
  123. sysfsfp = fopen(filename, "r");
  124. if (sysfsfp == NULL) {
  125. ret = -errno;
  126. printf("failed to open %s\n", filename);
  127. goto error_free_filename;
  128. }
  129. ret = fscanf(sysfsfp,
  130. "%ce:%c%u/%u>>%u",
  131. &endianchar,
  132. &signchar,
  133. bits_used,
  134. &padint, shift);
  135. if (ret < 0) {
  136. ret = -errno;
  137. printf("failed to pass scan type description\n");
  138. goto error_close_sysfsfp;
  139. } else if (ret != 5) {
  140. ret = -EIO;
  141. printf("scan type description didn't match\n");
  142. goto error_close_sysfsfp;
  143. }
  144. *be = (endianchar == 'b');
  145. *bytes = padint / 8;
  146. if (*bits_used == 64)
  147. *mask = ~0;
  148. else
  149. *mask = (1 << *bits_used) - 1;
  150. *is_signed = (signchar == 's');
  151. if (fclose(sysfsfp)) {
  152. ret = -errno;
  153. printf("Failed to close %s\n", filename);
  154. goto error_free_filename;
  155. }
  156. sysfsfp = 0;
  157. free(filename);
  158. filename = 0;
  159. }
  160. error_close_sysfsfp:
  161. if (sysfsfp)
  162. if (fclose(sysfsfp))
  163. perror("iioutils_get_type(): Failed to close file");
  164. error_free_filename:
  165. if (filename)
  166. free(filename);
  167. error_closedir:
  168. if (closedir(dp) == -1)
  169. perror("iioutils_get_type(): Failed to close directory");
  170. error_free_builtname_generic:
  171. free(builtname_generic);
  172. error_free_builtname:
  173. free(builtname);
  174. error_free_scan_el_dir:
  175. free(scan_el_dir);
  176. return ret;
  177. }
  178. /**
  179. * iioutils_get_param_float() - read a float value from a channel parameter
  180. * @output: output the float value
  181. * @param_name: the parameter name to read
  182. * @device_dir: the IIO device directory in sysfs
  183. * @name: the channel name
  184. * @generic_name: the channel type name
  185. *
  186. * Returns a value >= 0 on success, otherwise a negative error code.
  187. **/
  188. int iioutils_get_param_float(float *output, const char *param_name,
  189. const char *device_dir, const char *name,
  190. const char *generic_name)
  191. {
  192. FILE *sysfsfp;
  193. int ret;
  194. DIR *dp;
  195. char *builtname, *builtname_generic;
  196. char *filename = NULL;
  197. const struct dirent *ent;
  198. ret = asprintf(&builtname, "%s_%s", name, param_name);
  199. if (ret < 0)
  200. return -ENOMEM;
  201. ret = asprintf(&builtname_generic,
  202. "%s_%s", generic_name, param_name);
  203. if (ret < 0) {
  204. ret = -ENOMEM;
  205. goto error_free_builtname;
  206. }
  207. dp = opendir(device_dir);
  208. if (dp == NULL) {
  209. ret = -errno;
  210. goto error_free_builtname_generic;
  211. }
  212. ret = -ENOENT;
  213. while (ent = readdir(dp), ent != NULL)
  214. if ((strcmp(builtname, ent->d_name) == 0) ||
  215. (strcmp(builtname_generic, ent->d_name) == 0)) {
  216. ret = asprintf(&filename,
  217. "%s/%s", device_dir, ent->d_name);
  218. if (ret < 0) {
  219. ret = -ENOMEM;
  220. goto error_closedir;
  221. }
  222. sysfsfp = fopen(filename, "r");
  223. if (!sysfsfp) {
  224. ret = -errno;
  225. goto error_free_filename;
  226. }
  227. errno = 0;
  228. if (fscanf(sysfsfp, "%f", output) != 1)
  229. ret = errno ? -errno : -ENODATA;
  230. break;
  231. }
  232. error_free_filename:
  233. if (filename)
  234. free(filename);
  235. error_closedir:
  236. if (closedir(dp) == -1)
  237. perror("iioutils_get_param_float(): Failed to close directory");
  238. error_free_builtname_generic:
  239. free(builtname_generic);
  240. error_free_builtname:
  241. free(builtname);
  242. return ret;
  243. }
  244. /**
  245. * bsort_channel_array_by_index() - sort the array in index order
  246. * @ci_array: the iio_channel_info array to be sorted
  247. * @cnt: the amount of array elements
  248. **/
  249. void bsort_channel_array_by_index(struct iio_channel_info **ci_array, int cnt)
  250. {
  251. struct iio_channel_info temp;
  252. int x, y;
  253. for (x = 0; x < cnt; x++)
  254. for (y = 0; y < (cnt - 1); y++)
  255. if ((*ci_array)[y].index > (*ci_array)[y + 1].index) {
  256. temp = (*ci_array)[y + 1];
  257. (*ci_array)[y + 1] = (*ci_array)[y];
  258. (*ci_array)[y] = temp;
  259. }
  260. }
  261. /**
  262. * build_channel_array() - function to figure out what channels are present
  263. * @device_dir: the IIO device directory in sysfs
  264. * @ci_array: output the resulting array of iio_channel_info
  265. * @counter: output the amount of array elements
  266. *
  267. * Returns 0 on success, otherwise a negative error code.
  268. **/
  269. int build_channel_array(const char *device_dir,
  270. struct iio_channel_info **ci_array, int *counter)
  271. {
  272. DIR *dp;
  273. FILE *sysfsfp;
  274. int count = 0, i;
  275. struct iio_channel_info *current;
  276. int ret;
  277. const struct dirent *ent;
  278. char *scan_el_dir;
  279. char *filename;
  280. *counter = 0;
  281. ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
  282. if (ret < 0)
  283. return -ENOMEM;
  284. dp = opendir(scan_el_dir);
  285. if (dp == NULL) {
  286. ret = -errno;
  287. goto error_free_name;
  288. }
  289. while (ent = readdir(dp), ent != NULL)
  290. if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
  291. "_en") == 0) {
  292. ret = asprintf(&filename,
  293. "%s/%s", scan_el_dir, ent->d_name);
  294. if (ret < 0) {
  295. ret = -ENOMEM;
  296. goto error_close_dir;
  297. }
  298. sysfsfp = fopen(filename, "r");
  299. if (sysfsfp == NULL) {
  300. ret = -errno;
  301. free(filename);
  302. goto error_close_dir;
  303. }
  304. errno = 0;
  305. if (fscanf(sysfsfp, "%i", &ret) != 1) {
  306. ret = errno ? -errno : -ENODATA;
  307. if (fclose(sysfsfp))
  308. perror("build_channel_array(): Failed to close file");
  309. free(filename);
  310. goto error_close_dir;
  311. }
  312. if (ret == 1)
  313. (*counter)++;
  314. if (fclose(sysfsfp)) {
  315. ret = -errno;
  316. free(filename);
  317. goto error_close_dir;
  318. }
  319. free(filename);
  320. }
  321. *ci_array = malloc(sizeof(**ci_array) * (*counter));
  322. if (*ci_array == NULL) {
  323. ret = -ENOMEM;
  324. goto error_close_dir;
  325. }
  326. seekdir(dp, 0);
  327. while (ent = readdir(dp), ent != NULL) {
  328. if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
  329. "_en") == 0) {
  330. int current_enabled = 0;
  331. current = &(*ci_array)[count++];
  332. ret = asprintf(&filename,
  333. "%s/%s", scan_el_dir, ent->d_name);
  334. if (ret < 0) {
  335. ret = -ENOMEM;
  336. /* decrement count to avoid freeing name */
  337. count--;
  338. goto error_cleanup_array;
  339. }
  340. sysfsfp = fopen(filename, "r");
  341. if (sysfsfp == NULL) {
  342. ret = -errno;
  343. free(filename);
  344. count--;
  345. goto error_cleanup_array;
  346. }
  347. errno = 0;
  348. if (fscanf(sysfsfp, "%i", &current_enabled) != 1) {
  349. ret = errno ? -errno : -ENODATA;
  350. free(filename);
  351. count--;
  352. goto error_cleanup_array;
  353. }
  354. if (fclose(sysfsfp)) {
  355. ret = -errno;
  356. free(filename);
  357. count--;
  358. goto error_cleanup_array;
  359. }
  360. if (!current_enabled) {
  361. free(filename);
  362. count--;
  363. continue;
  364. }
  365. current->scale = 1.0;
  366. current->offset = 0;
  367. current->name = strndup(ent->d_name,
  368. strlen(ent->d_name) -
  369. strlen("_en"));
  370. if (current->name == NULL) {
  371. free(filename);
  372. ret = -ENOMEM;
  373. count--;
  374. goto error_cleanup_array;
  375. }
  376. /* Get the generic and specific name elements */
  377. ret = iioutils_break_up_name(current->name,
  378. &current->generic_name);
  379. if (ret) {
  380. free(filename);
  381. free(current->name);
  382. count--;
  383. goto error_cleanup_array;
  384. }
  385. ret = asprintf(&filename,
  386. "%s/%s_index",
  387. scan_el_dir,
  388. current->name);
  389. if (ret < 0) {
  390. free(filename);
  391. ret = -ENOMEM;
  392. goto error_cleanup_array;
  393. }
  394. sysfsfp = fopen(filename, "r");
  395. if (sysfsfp == NULL) {
  396. ret = -errno;
  397. printf("failed to open %s\n", filename);
  398. free(filename);
  399. goto error_cleanup_array;
  400. }
  401. errno = 0;
  402. if (fscanf(sysfsfp, "%u", &current->index) != 1) {
  403. ret = errno ? -errno : -ENODATA;
  404. if (fclose(sysfsfp))
  405. perror("build_channel_array(): Failed to close file");
  406. free(filename);
  407. goto error_cleanup_array;
  408. }
  409. if (fclose(sysfsfp)) {
  410. ret = -errno;
  411. free(filename);
  412. goto error_cleanup_array;
  413. }
  414. free(filename);
  415. /* Find the scale */
  416. ret = iioutils_get_param_float(&current->scale,
  417. "scale",
  418. device_dir,
  419. current->name,
  420. current->generic_name);
  421. if (ret < 0)
  422. goto error_cleanup_array;
  423. ret = iioutils_get_param_float(&current->offset,
  424. "offset",
  425. device_dir,
  426. current->name,
  427. current->generic_name);
  428. if (ret < 0)
  429. goto error_cleanup_array;
  430. ret = iioutils_get_type(&current->is_signed,
  431. &current->bytes,
  432. &current->bits_used,
  433. &current->shift,
  434. &current->mask,
  435. &current->be,
  436. device_dir,
  437. current->name,
  438. current->generic_name);
  439. if (ret < 0)
  440. goto error_cleanup_array;
  441. }
  442. }
  443. if (closedir(dp) == -1) {
  444. ret = -errno;
  445. goto error_cleanup_array;
  446. }
  447. free(scan_el_dir);
  448. /* reorder so that the array is in index order */
  449. bsort_channel_array_by_index(ci_array, *counter);
  450. return 0;
  451. error_cleanup_array:
  452. for (i = count - 1; i >= 0; i--) {
  453. free((*ci_array)[i].name);
  454. free((*ci_array)[i].generic_name);
  455. }
  456. free(*ci_array);
  457. error_close_dir:
  458. if (dp)
  459. if (closedir(dp) == -1)
  460. perror("build_channel_array(): Failed to close dir");
  461. error_free_name:
  462. free(scan_el_dir);
  463. return ret;
  464. }
  465. int calc_digits(int num)
  466. {
  467. int count = 0;
  468. while (num != 0) {
  469. num /= 10;
  470. count++;
  471. }
  472. return count;
  473. }
  474. /**
  475. * find_type_by_name() - function to match top level types by name
  476. * @name: top level type instance name
  477. * @type: the type of top level instance being searched
  478. *
  479. * Returns the device number of a matched IIO device on success, otherwise a
  480. * negative error code.
  481. * Typical types this is used for are device and trigger.
  482. **/
  483. int find_type_by_name(const char *name, const char *type)
  484. {
  485. const struct dirent *ent;
  486. int number, numstrlen, ret;
  487. FILE *nameFile;
  488. DIR *dp;
  489. char thisname[IIO_MAX_NAME_LENGTH];
  490. char *filename;
  491. dp = opendir(iio_dir);
  492. if (dp == NULL) {
  493. printf("No industrialio devices available\n");
  494. return -ENODEV;
  495. }
  496. while (ent = readdir(dp), ent != NULL) {
  497. if (strcmp(ent->d_name, ".") != 0 &&
  498. strcmp(ent->d_name, "..") != 0 &&
  499. strlen(ent->d_name) > strlen(type) &&
  500. strncmp(ent->d_name, type, strlen(type)) == 0) {
  501. errno = 0;
  502. ret = sscanf(ent->d_name + strlen(type), "%d", &number);
  503. if (ret < 0) {
  504. ret = -errno;
  505. printf("failed to read element number\n");
  506. goto error_close_dir;
  507. } else if (ret != 1) {
  508. ret = -EIO;
  509. printf("failed to match element number\n");
  510. goto error_close_dir;
  511. }
  512. numstrlen = calc_digits(number);
  513. /* verify the next character is not a colon */
  514. if (strncmp(ent->d_name + strlen(type) + numstrlen,
  515. ":", 1) != 0) {
  516. filename = malloc(strlen(iio_dir) + strlen(type)
  517. + numstrlen + 6);
  518. if (filename == NULL) {
  519. ret = -ENOMEM;
  520. goto error_close_dir;
  521. }
  522. ret = sprintf(filename, "%s%s%d/name", iio_dir,
  523. type, number);
  524. if (ret < 0) {
  525. free(filename);
  526. goto error_close_dir;
  527. }
  528. nameFile = fopen(filename, "r");
  529. if (!nameFile) {
  530. free(filename);
  531. continue;
  532. }
  533. free(filename);
  534. errno = 0;
  535. if (fscanf(nameFile, "%s", thisname) != 1) {
  536. ret = errno ? -errno : -ENODATA;
  537. goto error_close_dir;
  538. }
  539. if (fclose(nameFile)) {
  540. ret = -errno;
  541. goto error_close_dir;
  542. }
  543. if (strcmp(name, thisname) == 0) {
  544. if (closedir(dp) == -1)
  545. return -errno;
  546. return number;
  547. }
  548. }
  549. }
  550. }
  551. if (closedir(dp) == -1)
  552. return -errno;
  553. return -ENODEV;
  554. error_close_dir:
  555. if (closedir(dp) == -1)
  556. perror("find_type_by_name(): Failed to close directory");
  557. return ret;
  558. }
  559. static int _write_sysfs_int(const char *filename, const char *basedir, int val,
  560. int verify)
  561. {
  562. int ret = 0;
  563. FILE *sysfsfp;
  564. int test;
  565. char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
  566. if (temp == NULL)
  567. return -ENOMEM;
  568. ret = sprintf(temp, "%s/%s", basedir, filename);
  569. if (ret < 0)
  570. goto error_free;
  571. sysfsfp = fopen(temp, "w");
  572. if (sysfsfp == NULL) {
  573. ret = -errno;
  574. printf("failed to open %s\n", temp);
  575. goto error_free;
  576. }
  577. ret = fprintf(sysfsfp, "%d", val);
  578. if (ret < 0) {
  579. if (fclose(sysfsfp))
  580. perror("_write_sysfs_int(): Failed to close dir");
  581. goto error_free;
  582. }
  583. if (fclose(sysfsfp)) {
  584. ret = -errno;
  585. goto error_free;
  586. }
  587. if (verify) {
  588. sysfsfp = fopen(temp, "r");
  589. if (sysfsfp == NULL) {
  590. ret = -errno;
  591. printf("failed to open %s\n", temp);
  592. goto error_free;
  593. }
  594. if (fscanf(sysfsfp, "%d", &test) != 1) {
  595. ret = errno ? -errno : -ENODATA;
  596. if (fclose(sysfsfp))
  597. perror("_write_sysfs_int(): Failed to close dir");
  598. goto error_free;
  599. }
  600. if (fclose(sysfsfp)) {
  601. ret = -errno;
  602. goto error_free;
  603. }
  604. if (test != val) {
  605. printf("Possible failure in int write %d to %s/%s\n",
  606. val, basedir, filename);
  607. ret = -1;
  608. }
  609. }
  610. error_free:
  611. free(temp);
  612. return ret;
  613. }
  614. /**
  615. * write_sysfs_int() - write an integer value to a sysfs file
  616. * @filename: name of the file to write to
  617. * @basedir: the sysfs directory in which the file is to be found
  618. * @val: integer value to write to file
  619. *
  620. * Returns a value >= 0 on success, otherwise a negative error code.
  621. **/
  622. int write_sysfs_int(const char *filename, const char *basedir, int val)
  623. {
  624. return _write_sysfs_int(filename, basedir, val, 0);
  625. }
  626. /**
  627. * write_sysfs_int_and_verify() - write an integer value to a sysfs file
  628. * and verify
  629. * @filename: name of the file to write to
  630. * @basedir: the sysfs directory in which the file is to be found
  631. * @val: integer value to write to file
  632. *
  633. * Returns a value >= 0 on success, otherwise a negative error code.
  634. **/
  635. int write_sysfs_int_and_verify(const char *filename, const char *basedir,
  636. int val)
  637. {
  638. return _write_sysfs_int(filename, basedir, val, 1);
  639. }
  640. static int _write_sysfs_string(const char *filename, const char *basedir,
  641. const char *val, int verify)
  642. {
  643. int ret = 0;
  644. FILE *sysfsfp;
  645. char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
  646. if (temp == NULL) {
  647. printf("Memory allocation failed\n");
  648. return -ENOMEM;
  649. }
  650. ret = sprintf(temp, "%s/%s", basedir, filename);
  651. if (ret < 0)
  652. goto error_free;
  653. sysfsfp = fopen(temp, "w");
  654. if (sysfsfp == NULL) {
  655. ret = -errno;
  656. printf("Could not open %s\n", temp);
  657. goto error_free;
  658. }
  659. ret = fprintf(sysfsfp, "%s", val);
  660. if (ret < 0) {
  661. if (fclose(sysfsfp))
  662. perror("_write_sysfs_string(): Failed to close dir");
  663. goto error_free;
  664. }
  665. if (fclose(sysfsfp)) {
  666. ret = -errno;
  667. goto error_free;
  668. }
  669. if (verify) {
  670. sysfsfp = fopen(temp, "r");
  671. if (sysfsfp == NULL) {
  672. ret = -errno;
  673. printf("Could not open file to verify\n");
  674. goto error_free;
  675. }
  676. if (fscanf(sysfsfp, "%s", temp) != 1) {
  677. ret = errno ? -errno : -ENODATA;
  678. if (fclose(sysfsfp))
  679. perror("_write_sysfs_string(): Failed to close dir");
  680. goto error_free;
  681. }
  682. if (fclose(sysfsfp)) {
  683. ret = -errno;
  684. goto error_free;
  685. }
  686. if (strcmp(temp, val) != 0) {
  687. printf("Possible failure in string write of %s "
  688. "Should be %s written to %s/%s\n", temp, val,
  689. basedir, filename);
  690. ret = -1;
  691. }
  692. }
  693. error_free:
  694. free(temp);
  695. return ret;
  696. }
  697. /**
  698. * write_sysfs_string_and_verify() - string write, readback and verify
  699. * @filename: name of file to write to
  700. * @basedir: the sysfs directory in which the file is to be found
  701. * @val: the string to write
  702. *
  703. * Returns a value >= 0 on success, otherwise a negative error code.
  704. **/
  705. int write_sysfs_string_and_verify(const char *filename, const char *basedir,
  706. const char *val)
  707. {
  708. return _write_sysfs_string(filename, basedir, val, 1);
  709. }
  710. /**
  711. * write_sysfs_string() - write string to a sysfs file
  712. * @filename: name of file to write to
  713. * @basedir: the sysfs directory in which the file is to be found
  714. * @val: the string to write
  715. *
  716. * Returns a value >= 0 on success, otherwise a negative error code.
  717. **/
  718. int write_sysfs_string(const char *filename, const char *basedir,
  719. const char *val)
  720. {
  721. return _write_sysfs_string(filename, basedir, val, 0);
  722. }
  723. /**
  724. * read_sysfs_posint() - read an integer value from file
  725. * @filename: name of file to read from
  726. * @basedir: the sysfs directory in which the file is to be found
  727. *
  728. * Returns the read integer value >= 0 on success, otherwise a negative error
  729. * code.
  730. **/
  731. int read_sysfs_posint(const char *filename, const char *basedir)
  732. {
  733. int ret;
  734. FILE *sysfsfp;
  735. char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
  736. if (temp == NULL) {
  737. printf("Memory allocation failed");
  738. return -ENOMEM;
  739. }
  740. ret = sprintf(temp, "%s/%s", basedir, filename);
  741. if (ret < 0)
  742. goto error_free;
  743. sysfsfp = fopen(temp, "r");
  744. if (sysfsfp == NULL) {
  745. ret = -errno;
  746. goto error_free;
  747. }
  748. errno = 0;
  749. if (fscanf(sysfsfp, "%d\n", &ret) != 1) {
  750. ret = errno ? -errno : -ENODATA;
  751. if (fclose(sysfsfp))
  752. perror("read_sysfs_posint(): Failed to close dir");
  753. goto error_free;
  754. }
  755. if (fclose(sysfsfp))
  756. ret = -errno;
  757. error_free:
  758. free(temp);
  759. return ret;
  760. }
  761. /**
  762. * read_sysfs_float() - read a float value from file
  763. * @filename: name of file to read from
  764. * @basedir: the sysfs directory in which the file is to be found
  765. * @val: output the read float value
  766. *
  767. * Returns a value >= 0 on success, otherwise a negative error code.
  768. **/
  769. int read_sysfs_float(const char *filename, const char *basedir, float *val)
  770. {
  771. int ret = 0;
  772. FILE *sysfsfp;
  773. char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
  774. if (temp == NULL) {
  775. printf("Memory allocation failed");
  776. return -ENOMEM;
  777. }
  778. ret = sprintf(temp, "%s/%s", basedir, filename);
  779. if (ret < 0)
  780. goto error_free;
  781. sysfsfp = fopen(temp, "r");
  782. if (sysfsfp == NULL) {
  783. ret = -errno;
  784. goto error_free;
  785. }
  786. errno = 0;
  787. if (fscanf(sysfsfp, "%f\n", val) != 1) {
  788. ret = errno ? -errno : -ENODATA;
  789. if (fclose(sysfsfp))
  790. perror("read_sysfs_float(): Failed to close dir");
  791. goto error_free;
  792. }
  793. if (fclose(sysfsfp))
  794. ret = -errno;
  795. error_free:
  796. free(temp);
  797. return ret;
  798. }
  799. /**
  800. * read_sysfs_string() - read a string from file
  801. * @filename: name of file to read from
  802. * @basedir: the sysfs directory in which the file is to be found
  803. * @str: output the read string
  804. *
  805. * Returns a value >= 0 on success, otherwise a negative error code.
  806. **/
  807. int read_sysfs_string(const char *filename, const char *basedir, char *str)
  808. {
  809. int ret = 0;
  810. FILE *sysfsfp;
  811. char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
  812. if (temp == NULL) {
  813. printf("Memory allocation failed");
  814. return -ENOMEM;
  815. }
  816. ret = sprintf(temp, "%s/%s", basedir, filename);
  817. if (ret < 0)
  818. goto error_free;
  819. sysfsfp = fopen(temp, "r");
  820. if (sysfsfp == NULL) {
  821. ret = -errno;
  822. goto error_free;
  823. }
  824. errno = 0;
  825. if (fscanf(sysfsfp, "%s\n", str) != 1) {
  826. ret = errno ? -errno : -ENODATA;
  827. if (fclose(sysfsfp))
  828. perror("read_sysfs_string(): Failed to close dir");
  829. goto error_free;
  830. }
  831. if (fclose(sysfsfp))
  832. ret = -errno;
  833. error_free:
  834. free(temp);
  835. return ret;
  836. }
  837. #endif /* _IIO_UTILS_H */