~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/iio/iio_utils.c

Version: ~ [ linux-5.4 ] ~ [ linux-5.3.13 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.86 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.156 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.203 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.202 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.78 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp