iio_utils.c 21 KB

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