iio_utils.c 21 KB

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