iio_utils.c 21 KB

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