Merge tag 'v3.10.72' into linux-linaro-lsk
[firefly-linux-kernel-4.4.55.git] / tools / gator / daemon / libsensors / sysfs.c
1 /*
2     sysfs.c - Part of libsensors, a library for reading Linux sensor data
3     Copyright (c) 2005 Mark M. Hoffman <mhoffman@lightlink.com>
4     Copyright (C) 2007-2010 Jean Delvare <khali@linux-fr.org>
5
6     This library is free software; you can redistribute it and/or
7     modify it under the terms of the GNU Lesser General Public
8     License as published by the Free Software Foundation; either
9     version 2.1 of the License, or (at your option) any later version.
10
11     This library is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU Lesser General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19     MA 02110-1301 USA.
20 */
21
22 /*** This file modified by ARM on Jan 23, 2013 to improve performance by substituting calls to fread() with calls to read() and to read non-scaled values. ***/
23
24 /* this define needed for strndup() */
25 #define _GNU_SOURCE
26
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <sys/vfs.h>
30 #include <unistd.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <limits.h>
34 #include <errno.h>
35 #include <dirent.h>
36 #include <fcntl.h>
37 #include "data.h"
38 #include "error.h"
39 #include "access.h"
40 #include "general.h"
41 #include "sysfs.h"
42
43
44 /****************************************************************************/
45
46 #define ATTR_MAX        128
47 #define SYSFS_MAGIC     0x62656572
48
49 int sensors_sysfs_no_scaling;
50
51 /*
52  * Read an attribute from sysfs
53  * Returns a pointer to a freshly allocated string; free it yourself.
54  * If the file doesn't exist or can't be read, NULL is returned.
55  */
56 static char *sysfs_read_attr(const char *device, const char *attr)
57 {
58         char path[NAME_MAX];
59         char buf[ATTR_MAX], *p;
60         FILE *f;
61
62         snprintf(path, NAME_MAX, "%s/%s", device, attr);
63
64         if (!(f = fopen(path, "r")))
65                 return NULL;
66         p = fgets(buf, ATTR_MAX, f);
67         fclose(f);
68         if (!p)
69                 return NULL;
70
71         /* Last byte is a '\n'; chop that off */
72         p = strndup(buf, strlen(buf) - 1);
73         if (!p)
74                 sensors_fatal_error(__func__, "Out of memory");
75         return p;
76 }
77
78 /*
79  * Call an arbitrary function for each class device of the given class
80  * Returns 0 on success (all calls returned 0), a positive errno for
81  * local errors, or a negative error value if any call fails.
82  */
83 static int sysfs_foreach_classdev(const char *class_name,
84                                    int (*func)(const char *, const char *))
85 {
86         char path[NAME_MAX];
87         int path_off, ret;
88         DIR *dir;
89         struct dirent *ent;
90
91         path_off = snprintf(path, NAME_MAX, "%s/class/%s",
92                             sensors_sysfs_mount, class_name);
93         if (!(dir = opendir(path)))
94                 return errno;
95
96         ret = 0;
97         while (!ret && (ent = readdir(dir))) {
98                 if (ent->d_name[0] == '.')      /* skip hidden entries */
99                         continue;
100
101                 snprintf(path + path_off, NAME_MAX - path_off, "/%s",
102                          ent->d_name);
103                 ret = func(path, ent->d_name);
104         }
105
106         closedir(dir);
107         return ret;
108 }
109
110 /*
111  * Call an arbitrary function for each device of the given bus type
112  * Returns 0 on success (all calls returned 0), a positive errno for
113  * local errors, or a negative error value if any call fails.
114  */
115 static int sysfs_foreach_busdev(const char *bus_type,
116                                  int (*func)(const char *, const char *))
117 {
118         char path[NAME_MAX];
119         int path_off, ret;
120         DIR *dir;
121         struct dirent *ent;
122
123         path_off = snprintf(path, NAME_MAX, "%s/bus/%s/devices",
124                             sensors_sysfs_mount, bus_type);
125         if (!(dir = opendir(path)))
126                 return errno;
127
128         ret = 0;
129         while (!ret && (ent = readdir(dir))) {
130                 if (ent->d_name[0] == '.')      /* skip hidden entries */
131                         continue;
132
133                 snprintf(path + path_off, NAME_MAX - path_off, "/%s",
134                          ent->d_name);
135                 ret = func(path, ent->d_name);
136         }
137
138         closedir(dir);
139         return ret;
140 }
141
142 /****************************************************************************/
143
144 char sensors_sysfs_mount[NAME_MAX];
145
146 #define MAX_MAIN_SENSOR_TYPES   (SENSORS_FEATURE_MAX_MAIN - SENSORS_FEATURE_IN)
147 #define MAX_OTHER_SENSOR_TYPES  (SENSORS_FEATURE_MAX_OTHER - SENSORS_FEATURE_VID)
148 #define MAX_SENSORS_PER_TYPE    24
149 /* max_subfeatures is now computed dynamically */
150 #define FEATURE_SIZE            (max_subfeatures * 2)
151 #define FEATURE_TYPE_SIZE       (MAX_SENSORS_PER_TYPE * FEATURE_SIZE)
152
153 /*
154  * Room for all 7 main types (in, fan, temp, power, energy, current, humidity)
155  * and 2 other types (VID, intrusion) with all their subfeatures + misc features
156  */
157 #define SUB_OFFSET_OTHER        (MAX_MAIN_SENSOR_TYPES * FEATURE_TYPE_SIZE)
158 #define SUB_OFFSET_MISC         (SUB_OFFSET_OTHER + \
159                                  MAX_OTHER_SENSOR_TYPES * FEATURE_TYPE_SIZE)
160 #define ALL_POSSIBLE_SUBFEATURES        (SUB_OFFSET_MISC + 1)
161
162 static
163 int get_type_scaling(sensors_subfeature_type type)
164 {
165         /* Multipliers for subfeatures */
166         switch (type & 0xFF80) {
167         case SENSORS_SUBFEATURE_IN_INPUT:
168         case SENSORS_SUBFEATURE_TEMP_INPUT:
169         case SENSORS_SUBFEATURE_CURR_INPUT:
170         case SENSORS_SUBFEATURE_HUMIDITY_INPUT:
171                 return 1000;
172         case SENSORS_SUBFEATURE_FAN_INPUT:
173                 return 1;
174         case SENSORS_SUBFEATURE_POWER_AVERAGE:
175         case SENSORS_SUBFEATURE_ENERGY_INPUT:
176                 return 1000000;
177         }
178
179         /* Multipliers for second class subfeatures
180            that need their own multiplier */
181         switch (type) {
182         case SENSORS_SUBFEATURE_POWER_AVERAGE_INTERVAL:
183         case SENSORS_SUBFEATURE_VID:
184         case SENSORS_SUBFEATURE_TEMP_OFFSET:
185                 return 1000;
186         default:
187                 return 1;
188         }
189 }
190
191 static
192 char *get_feature_name(sensors_feature_type ftype, char *sfname)
193 {
194         char *name, *underscore;
195
196         switch (ftype) {
197         case SENSORS_FEATURE_IN:
198         case SENSORS_FEATURE_FAN:
199         case SENSORS_FEATURE_TEMP:
200         case SENSORS_FEATURE_POWER:
201         case SENSORS_FEATURE_ENERGY:
202         case SENSORS_FEATURE_CURR:
203         case SENSORS_FEATURE_HUMIDITY:
204         case SENSORS_FEATURE_INTRUSION:
205                 underscore = strchr(sfname, '_');
206                 name = strndup(sfname, underscore - sfname);
207                 if (!name)
208                         sensors_fatal_error(__func__, "Out of memory");
209
210                 break;
211         default:
212                 name = strdup(sfname);
213                 if (!name)
214                         sensors_fatal_error(__func__, "Out of memory");
215         }
216
217         return name;
218 }
219
220 /* Static mappings for use by sensors_subfeature_get_type() */
221 struct subfeature_type_match
222 {
223         const char *name;
224         sensors_subfeature_type type;
225 };
226
227 struct feature_type_match
228 {
229         const char *name;
230         const struct subfeature_type_match *submatches;
231 };
232
233 static const struct subfeature_type_match temp_matches[] = {
234         { "input", SENSORS_SUBFEATURE_TEMP_INPUT },
235         { "max", SENSORS_SUBFEATURE_TEMP_MAX },
236         { "max_hyst", SENSORS_SUBFEATURE_TEMP_MAX_HYST },
237         { "min", SENSORS_SUBFEATURE_TEMP_MIN },
238         { "crit", SENSORS_SUBFEATURE_TEMP_CRIT },
239         { "crit_hyst", SENSORS_SUBFEATURE_TEMP_CRIT_HYST },
240         { "lcrit", SENSORS_SUBFEATURE_TEMP_LCRIT },
241         { "emergency", SENSORS_SUBFEATURE_TEMP_EMERGENCY },
242         { "emergency_hyst", SENSORS_SUBFEATURE_TEMP_EMERGENCY_HYST },
243         { "lowest", SENSORS_SUBFEATURE_TEMP_LOWEST },
244         { "highest", SENSORS_SUBFEATURE_TEMP_HIGHEST },
245         { "alarm", SENSORS_SUBFEATURE_TEMP_ALARM },
246         { "min_alarm", SENSORS_SUBFEATURE_TEMP_MIN_ALARM },
247         { "max_alarm", SENSORS_SUBFEATURE_TEMP_MAX_ALARM },
248         { "crit_alarm", SENSORS_SUBFEATURE_TEMP_CRIT_ALARM },
249         { "emergency_alarm", SENSORS_SUBFEATURE_TEMP_EMERGENCY_ALARM },
250         { "lcrit_alarm", SENSORS_SUBFEATURE_TEMP_LCRIT_ALARM },
251         { "fault", SENSORS_SUBFEATURE_TEMP_FAULT },
252         { "type", SENSORS_SUBFEATURE_TEMP_TYPE },
253         { "offset", SENSORS_SUBFEATURE_TEMP_OFFSET },
254         { "beep", SENSORS_SUBFEATURE_TEMP_BEEP },
255         { NULL, 0 }
256 };
257
258 static const struct subfeature_type_match in_matches[] = {
259         { "input", SENSORS_SUBFEATURE_IN_INPUT },
260         { "min", SENSORS_SUBFEATURE_IN_MIN },
261         { "max", SENSORS_SUBFEATURE_IN_MAX },
262         { "lcrit", SENSORS_SUBFEATURE_IN_LCRIT },
263         { "crit", SENSORS_SUBFEATURE_IN_CRIT },
264         { "average", SENSORS_SUBFEATURE_IN_AVERAGE },
265         { "lowest", SENSORS_SUBFEATURE_IN_LOWEST },
266         { "highest", SENSORS_SUBFEATURE_IN_HIGHEST },
267         { "alarm", SENSORS_SUBFEATURE_IN_ALARM },
268         { "min_alarm", SENSORS_SUBFEATURE_IN_MIN_ALARM },
269         { "max_alarm", SENSORS_SUBFEATURE_IN_MAX_ALARM },
270         { "lcrit_alarm", SENSORS_SUBFEATURE_IN_LCRIT_ALARM },
271         { "crit_alarm", SENSORS_SUBFEATURE_IN_CRIT_ALARM },
272         { "beep", SENSORS_SUBFEATURE_IN_BEEP },
273         { NULL, 0 }
274 };
275
276 static const struct subfeature_type_match fan_matches[] = {
277         { "input", SENSORS_SUBFEATURE_FAN_INPUT },
278         { "min", SENSORS_SUBFEATURE_FAN_MIN },
279         { "max", SENSORS_SUBFEATURE_FAN_MAX },
280         { "div", SENSORS_SUBFEATURE_FAN_DIV },
281         { "pulses", SENSORS_SUBFEATURE_FAN_PULSES },
282         { "alarm", SENSORS_SUBFEATURE_FAN_ALARM },
283         { "min_alarm", SENSORS_SUBFEATURE_FAN_MIN_ALARM },
284         { "max_alarm", SENSORS_SUBFEATURE_FAN_MAX_ALARM },
285         { "fault", SENSORS_SUBFEATURE_FAN_FAULT },
286         { "beep", SENSORS_SUBFEATURE_FAN_BEEP },
287         { NULL, 0 }
288 };
289
290 static const struct subfeature_type_match power_matches[] = {
291         { "average", SENSORS_SUBFEATURE_POWER_AVERAGE },
292         { "average_highest", SENSORS_SUBFEATURE_POWER_AVERAGE_HIGHEST },
293         { "average_lowest", SENSORS_SUBFEATURE_POWER_AVERAGE_LOWEST },
294         { "input", SENSORS_SUBFEATURE_POWER_INPUT },
295         { "input_highest", SENSORS_SUBFEATURE_POWER_INPUT_HIGHEST },
296         { "input_lowest", SENSORS_SUBFEATURE_POWER_INPUT_LOWEST },
297         { "cap", SENSORS_SUBFEATURE_POWER_CAP },
298         { "cap_hyst", SENSORS_SUBFEATURE_POWER_CAP_HYST },
299         { "cap_alarm", SENSORS_SUBFEATURE_POWER_CAP_ALARM },
300         { "alarm", SENSORS_SUBFEATURE_POWER_ALARM },
301         { "max", SENSORS_SUBFEATURE_POWER_MAX },
302         { "max_alarm", SENSORS_SUBFEATURE_POWER_MAX_ALARM },
303         { "crit", SENSORS_SUBFEATURE_POWER_CRIT },
304         { "crit_alarm", SENSORS_SUBFEATURE_POWER_CRIT_ALARM },
305         { "average_interval", SENSORS_SUBFEATURE_POWER_AVERAGE_INTERVAL },
306         { NULL, 0 }
307 };
308
309 static const struct subfeature_type_match energy_matches[] = {
310         { "input", SENSORS_SUBFEATURE_ENERGY_INPUT },
311         { NULL, 0 }
312 };
313
314 static const struct subfeature_type_match curr_matches[] = {
315         { "input", SENSORS_SUBFEATURE_CURR_INPUT },
316         { "min", SENSORS_SUBFEATURE_CURR_MIN },
317         { "max", SENSORS_SUBFEATURE_CURR_MAX },
318         { "lcrit", SENSORS_SUBFEATURE_CURR_LCRIT },
319         { "crit", SENSORS_SUBFEATURE_CURR_CRIT },
320         { "average", SENSORS_SUBFEATURE_CURR_AVERAGE },
321         { "lowest", SENSORS_SUBFEATURE_CURR_LOWEST },
322         { "highest", SENSORS_SUBFEATURE_CURR_HIGHEST },
323         { "alarm", SENSORS_SUBFEATURE_CURR_ALARM },
324         { "min_alarm", SENSORS_SUBFEATURE_CURR_MIN_ALARM },
325         { "max_alarm", SENSORS_SUBFEATURE_CURR_MAX_ALARM },
326         { "lcrit_alarm", SENSORS_SUBFEATURE_CURR_LCRIT_ALARM },
327         { "crit_alarm", SENSORS_SUBFEATURE_CURR_CRIT_ALARM },
328         { "beep", SENSORS_SUBFEATURE_CURR_BEEP },
329         { NULL, 0 }
330 };
331
332 static const struct subfeature_type_match humidity_matches[] = {
333         { "input", SENSORS_SUBFEATURE_HUMIDITY_INPUT },
334         { NULL, 0 }
335 };
336
337 static const struct subfeature_type_match cpu_matches[] = {
338         { "vid", SENSORS_SUBFEATURE_VID },
339         { NULL, 0 }
340 };
341
342 static const struct subfeature_type_match intrusion_matches[] = {
343         { "alarm", SENSORS_SUBFEATURE_INTRUSION_ALARM },
344         { "beep", SENSORS_SUBFEATURE_INTRUSION_BEEP },
345         { NULL, 0 }
346 };
347 static struct feature_type_match matches[] = {
348         { "temp%d%c", temp_matches },
349         { "in%d%c", in_matches },
350         { "fan%d%c", fan_matches },
351         { "cpu%d%c", cpu_matches },
352         { "power%d%c", power_matches },
353         { "curr%d%c", curr_matches },
354         { "energy%d%c", energy_matches },
355         { "intrusion%d%c", intrusion_matches },
356         { "humidity%d%c", humidity_matches },
357 };
358
359 /* Return the subfeature type and channel number based on the subfeature
360    name */
361 static
362 sensors_subfeature_type sensors_subfeature_get_type(const char *name, int *nr)
363 {
364         char c;
365         int i, count;
366         const struct subfeature_type_match *submatches;
367
368         /* Special case */
369         if (!strcmp(name, "beep_enable")) {
370                 *nr = 0;
371                 return SENSORS_SUBFEATURE_BEEP_ENABLE;
372         }
373
374         for (i = 0; i < ARRAY_SIZE(matches); i++)
375                 if ((count = sscanf(name, matches[i].name, nr, &c)))
376                         break;
377
378         if (i == ARRAY_SIZE(matches) || count != 2 || c != '_')
379                 return SENSORS_SUBFEATURE_UNKNOWN;  /* no match */
380
381         submatches = matches[i].submatches;
382         name = strchr(name + 3, '_') + 1;
383         for (i = 0; submatches[i].name != NULL; i++)
384                 if (!strcmp(name, submatches[i].name))
385                         return submatches[i].type;
386
387         return SENSORS_SUBFEATURE_UNKNOWN;
388 }
389
390 static int sensors_compute_max(void)
391 {
392         int i, j, max, offset;
393         const struct subfeature_type_match *submatches;
394         sensors_feature_type ftype;
395
396         max = 0;
397         for (i = 0; i < ARRAY_SIZE(matches); i++) {
398                 submatches = matches[i].submatches;
399                 for (j = 0; submatches[j].name != NULL; j++) {
400                         ftype = submatches[j].type >> 8;
401
402                         if (ftype < SENSORS_FEATURE_VID) {
403                                 offset = submatches[j].type & 0x7F;
404                                 if (offset >= max)
405                                         max = offset + 1;
406                         } else {
407                                 offset = submatches[j].type & 0xFF;
408                                 if (offset >= max * 2)
409                                         max = ((offset + 1) + 1) / 2;
410                         }
411                 }
412         }
413
414         return max;
415 }
416
417 static int sensors_get_attr_mode(const char *device, const char *attr)
418 {
419         char path[NAME_MAX];
420         struct stat st;
421         int mode = 0;
422
423         snprintf(path, NAME_MAX, "%s/%s", device, attr);
424         if (!stat(path, &st)) {
425                 if (st.st_mode & S_IRUSR)
426                         mode |= SENSORS_MODE_R;
427                 if (st.st_mode & S_IWUSR)
428                         mode |= SENSORS_MODE_W;
429         }
430         return mode;
431 }
432
433 static int sensors_read_dynamic_chip(sensors_chip_features *chip,
434                                      const char *dev_path)
435 {
436         int i, fnum = 0, sfnum = 0, prev_slot;
437         static int max_subfeatures;
438         DIR *dir;
439         struct dirent *ent;
440         sensors_subfeature *all_subfeatures;
441         sensors_subfeature *dyn_subfeatures;
442         sensors_feature *dyn_features;
443         sensors_feature_type ftype;
444         sensors_subfeature_type sftype;
445
446         if (!(dir = opendir(dev_path)))
447                 return -errno;
448
449         /* Dynamically figure out the max number of subfeatures */
450         if (!max_subfeatures)
451                 max_subfeatures = sensors_compute_max();
452
453         /* We use a large sparse table at first to store all found
454            subfeatures, so that we can store them sorted at type and index
455            and then later create a dense sorted table. */
456         all_subfeatures = calloc(ALL_POSSIBLE_SUBFEATURES,
457                                  sizeof(sensors_subfeature));
458         if (!all_subfeatures)
459                 sensors_fatal_error(__func__, "Out of memory");
460
461         while ((ent = readdir(dir))) {
462                 char *name;
463                 int nr;
464
465                 /* Skip directories and symlinks */
466                 if (ent->d_type != DT_REG)
467                         continue;
468
469                 name = ent->d_name;
470
471                 sftype = sensors_subfeature_get_type(name, &nr);
472                 if (sftype == SENSORS_SUBFEATURE_UNKNOWN)
473                         continue;
474                 ftype = sftype >> 8;
475
476                 /* Adjust the channel number */
477                 switch (ftype) {
478                 case SENSORS_FEATURE_FAN:
479                 case SENSORS_FEATURE_TEMP:
480                 case SENSORS_FEATURE_POWER:
481                 case SENSORS_FEATURE_ENERGY:
482                 case SENSORS_FEATURE_CURR:
483                 case SENSORS_FEATURE_HUMIDITY:
484                         nr--;
485                         break;
486                 default:
487                         break;
488                 }
489
490                 if (nr < 0 || nr >= MAX_SENSORS_PER_TYPE) {
491                         /* More sensors of one type than MAX_SENSORS_PER_TYPE,
492                            we have to ignore it */
493 #ifdef DEBUG
494                         sensors_fatal_error(__func__,
495                                             "Increase MAX_SENSORS_PER_TYPE!");
496 #endif
497                         continue;
498                 }
499
500                 /* "calculate" a place to store the subfeature in our sparse,
501                    sorted table */
502                 switch (ftype) {
503                 case SENSORS_FEATURE_VID:
504                 case SENSORS_FEATURE_INTRUSION:
505                         i = SUB_OFFSET_OTHER +
506                             (ftype - SENSORS_FEATURE_VID) * FEATURE_TYPE_SIZE +
507                             nr * FEATURE_SIZE + (sftype & 0xFF);
508                         break;
509                 case SENSORS_FEATURE_BEEP_ENABLE:
510                         i = SUB_OFFSET_MISC +
511                             (ftype - SENSORS_FEATURE_BEEP_ENABLE);
512                         break;
513                 default:
514                         i = ftype * FEATURE_TYPE_SIZE +
515                             nr * FEATURE_SIZE +
516                             ((sftype & 0x80) >> 7) * max_subfeatures +
517                             (sftype & 0x7F);
518                 }
519
520                 if (all_subfeatures[i].name) {
521 #ifdef DEBUG
522                         sensors_fatal_error(__func__, "Duplicate subfeature");
523 #endif
524                         continue;
525                 }
526
527                 /* fill in the subfeature members */
528                 all_subfeatures[i].type = sftype;
529                 all_subfeatures[i].name = strdup(name);
530                 if (!all_subfeatures[i].name)
531                         sensors_fatal_error(__func__, "Out of memory");
532
533                 /* Other and misc subfeatures are never scaled */
534                 if (sftype < SENSORS_SUBFEATURE_VID && !(sftype & 0x80))
535                         all_subfeatures[i].flags |= SENSORS_COMPUTE_MAPPING;
536                 all_subfeatures[i].flags |= sensors_get_attr_mode(dev_path, name);
537
538                 sfnum++;
539         }
540         closedir(dir);
541
542         if (!sfnum) { /* No subfeature */
543                 chip->subfeature = NULL;
544                 goto exit_free;
545         }
546
547         /* How many main features? */
548         prev_slot = -1;
549         for (i = 0; i < ALL_POSSIBLE_SUBFEATURES; i++) {
550                 if (!all_subfeatures[i].name)
551                         continue;
552
553                 if (i >= SUB_OFFSET_MISC || i / FEATURE_SIZE != prev_slot) {
554                         fnum++;
555                         prev_slot = i / FEATURE_SIZE;
556                 }
557         }
558
559         dyn_subfeatures = calloc(sfnum, sizeof(sensors_subfeature));
560         dyn_features = calloc(fnum, sizeof(sensors_feature));
561         if (!dyn_subfeatures || !dyn_features)
562                 sensors_fatal_error(__func__, "Out of memory");
563
564         /* Copy from the sparse array to the compact array */
565         sfnum = 0;
566         fnum = -1;
567         prev_slot = -1;
568         for (i = 0; i < ALL_POSSIBLE_SUBFEATURES; i++) {
569                 if (!all_subfeatures[i].name)
570                         continue;
571
572                 /* New main feature? */
573                 if (i >= SUB_OFFSET_MISC || i / FEATURE_SIZE != prev_slot) {
574                         ftype = all_subfeatures[i].type >> 8;
575                         fnum++;
576                         prev_slot = i / FEATURE_SIZE;
577
578                         dyn_features[fnum].name = get_feature_name(ftype,
579                                                 all_subfeatures[i].name);
580                         dyn_features[fnum].number = fnum;
581                         dyn_features[fnum].first_subfeature = sfnum;
582                         dyn_features[fnum].type = ftype;
583                 }
584
585                 dyn_subfeatures[sfnum] = all_subfeatures[i];
586                 dyn_subfeatures[sfnum].number = sfnum;
587                 /* Back to the feature */
588                 dyn_subfeatures[sfnum].mapping = fnum;
589
590                 sfnum++;
591         }
592
593         chip->subfeature = dyn_subfeatures;
594         chip->subfeature_count = sfnum;
595         chip->feature = dyn_features;
596         chip->feature_count = ++fnum;
597
598 exit_free:
599         free(all_subfeatures);
600         return 0;
601 }
602
603 /* returns !0 if sysfs filesystem was found, 0 otherwise */
604 int sensors_init_sysfs(void)
605 {
606         struct statfs statfsbuf;
607
608         snprintf(sensors_sysfs_mount, NAME_MAX, "%s", "/sys");
609         if (statfs(sensors_sysfs_mount, &statfsbuf) < 0
610          || statfsbuf.f_type != SYSFS_MAGIC)
611                 return 0;
612
613         return 1;
614 }
615
616 /* returns: number of devices added (0 or 1) if successful, <0 otherwise */
617 static int sensors_read_one_sysfs_chip(const char *dev_path,
618                                        const char *dev_name,
619                                        const char *hwmon_path)
620 {
621         int domain, bus, slot, fn, vendor, product, id;
622         int err = -SENSORS_ERR_KERNEL;
623         char *bus_attr;
624         char bus_path[NAME_MAX];
625         char linkpath[NAME_MAX];
626         char subsys_path[NAME_MAX], *subsys;
627         int sub_len;
628         sensors_chip_features entry;
629
630         /* ignore any device without name attribute */
631         if (!(entry.chip.prefix = sysfs_read_attr(hwmon_path, "name")))
632                 return 0;
633
634         entry.chip.path = strdup(hwmon_path);
635         if (!entry.chip.path)
636                 sensors_fatal_error(__func__, "Out of memory");
637
638         if (dev_path == NULL) {
639                 /* Virtual device */
640                 entry.chip.bus.type = SENSORS_BUS_TYPE_VIRTUAL;
641                 entry.chip.bus.nr = 0;
642                 /* For now we assume that virtual devices are unique */
643                 entry.chip.addr = 0;
644                 goto done;
645         }
646
647         /* Find bus type */
648         snprintf(linkpath, NAME_MAX, "%s/subsystem", dev_path);
649         sub_len = readlink(linkpath, subsys_path, NAME_MAX - 1);
650         if (sub_len < 0 && errno == ENOENT) {
651                 /* Fallback to "bus" link for kernels <= 2.6.17 */
652                 snprintf(linkpath, NAME_MAX, "%s/bus", dev_path);
653                 sub_len = readlink(linkpath, subsys_path, NAME_MAX - 1);
654         }
655         if (sub_len < 0) {
656                 /* Older kernels (<= 2.6.11) have neither the subsystem
657                    symlink nor the bus symlink */
658                 if (errno == ENOENT)
659                         subsys = NULL;
660                 else
661                         goto exit_free;
662         } else {
663                 subsys_path[sub_len] = '\0';
664                 subsys = strrchr(subsys_path, '/') + 1;
665         }
666
667         if ((!subsys || !strcmp(subsys, "i2c")) &&
668             sscanf(dev_name, "%hd-%x", &entry.chip.bus.nr,
669                    &entry.chip.addr) == 2) {
670                 /* find out if legacy ISA or not */
671                 if (entry.chip.bus.nr == 9191) {
672                         entry.chip.bus.type = SENSORS_BUS_TYPE_ISA;
673                         entry.chip.bus.nr = 0;
674                 } else {
675                         entry.chip.bus.type = SENSORS_BUS_TYPE_I2C;
676                         snprintf(bus_path, sizeof(bus_path),
677                                 "%s/class/i2c-adapter/i2c-%d/device",
678                                 sensors_sysfs_mount, entry.chip.bus.nr);
679
680                         if ((bus_attr = sysfs_read_attr(bus_path, "name"))) {
681                                 if (!strncmp(bus_attr, "ISA ", 4)) {
682                                         entry.chip.bus.type = SENSORS_BUS_TYPE_ISA;
683                                         entry.chip.bus.nr = 0;
684                                 }
685
686                                 free(bus_attr);
687                         }
688                 }
689         } else
690         if ((!subsys || !strcmp(subsys, "spi")) &&
691             sscanf(dev_name, "spi%hd.%d", &entry.chip.bus.nr,
692                    &entry.chip.addr) == 2) {
693                 /* SPI */
694                 entry.chip.bus.type = SENSORS_BUS_TYPE_SPI;
695         } else
696         if ((!subsys || !strcmp(subsys, "pci")) &&
697             sscanf(dev_name, "%x:%x:%x.%x", &domain, &bus, &slot, &fn) == 4) {
698                 /* PCI */
699                 entry.chip.addr = (domain << 16) + (bus << 8) + (slot << 3) + fn;
700                 entry.chip.bus.type = SENSORS_BUS_TYPE_PCI;
701                 entry.chip.bus.nr = 0;
702         } else
703         if ((!subsys || !strcmp(subsys, "platform") ||
704                         !strcmp(subsys, "of_platform"))) {
705                 /* must be new ISA (platform driver) */
706                 if (sscanf(dev_name, "%*[a-z0-9_].%d", &entry.chip.addr) != 1)
707                         entry.chip.addr = 0;
708                 entry.chip.bus.type = SENSORS_BUS_TYPE_ISA;
709                 entry.chip.bus.nr = 0;
710         } else if (subsys && !strcmp(subsys, "acpi")) {
711                 entry.chip.bus.type = SENSORS_BUS_TYPE_ACPI;
712                 /* For now we assume that acpi devices are unique */
713                 entry.chip.bus.nr = 0;
714                 entry.chip.addr = 0;
715         } else
716         if (subsys && !strcmp(subsys, "hid") &&
717             sscanf(dev_name, "%x:%x:%x.%x", &bus, &vendor, &product, &id) == 4) {
718                 entry.chip.bus.type = SENSORS_BUS_TYPE_HID;
719                 /* As of kernel 2.6.32, the hid device names don't look good */
720                 entry.chip.bus.nr = bus;
721                 entry.chip.addr = id;
722         } else {
723                 /* Ignore unknown device */
724                 err = 0;
725                 goto exit_free;
726         }
727
728 done:
729         if (sensors_read_dynamic_chip(&entry, hwmon_path) < 0)
730                 goto exit_free;
731         if (!entry.subfeature) { /* No subfeature, discard chip */
732                 err = 0;
733                 goto exit_free;
734         }
735         sensors_add_proc_chips(&entry);
736
737         return 1;
738
739 exit_free:
740         free(entry.chip.prefix);
741         free(entry.chip.path);
742         return err;
743 }
744
745 static int sensors_add_hwmon_device_compat(const char *path,
746                                            const char *dev_name)
747 {
748         int err;
749
750         err = sensors_read_one_sysfs_chip(path, dev_name, path);
751         if (err < 0)
752                 return err;
753         return 0;
754 }
755
756 /* returns 0 if successful, !0 otherwise */
757 static int sensors_read_sysfs_chips_compat(void)
758 {
759         int ret;
760
761         ret = sysfs_foreach_busdev("i2c", sensors_add_hwmon_device_compat);
762         if (ret && ret != ENOENT)
763                 return -SENSORS_ERR_KERNEL;
764
765         return 0;
766 }
767
768 static int sensors_add_hwmon_device(const char *path, const char *classdev)
769 {
770         char linkpath[NAME_MAX];
771         char device[NAME_MAX], *device_p;
772         int dev_len, err;
773         (void)classdev; /* hide warning */
774
775         snprintf(linkpath, NAME_MAX, "%s/device", path);
776         dev_len = readlink(linkpath, device, NAME_MAX - 1);
777         if (dev_len < 0) {
778                 /* No device link? Treat as virtual */
779                 err = sensors_read_one_sysfs_chip(NULL, NULL, path);
780         } else {
781                 device[dev_len] = '\0';
782                 device_p = strrchr(device, '/') + 1;
783
784                 /* The attributes we want might be those of the hwmon class
785                    device, or those of the device itself. */
786                 err = sensors_read_one_sysfs_chip(linkpath, device_p, path);
787                 if (err == 0)
788                         err = sensors_read_one_sysfs_chip(linkpath, device_p,
789                                                           linkpath);
790         }
791         if (err < 0)
792                 return err;
793         return 0;
794 }
795
796 /* returns 0 if successful, !0 otherwise */
797 int sensors_read_sysfs_chips(void)
798 {
799         int ret;
800
801         ret = sysfs_foreach_classdev("hwmon", sensors_add_hwmon_device);
802         if (ret == ENOENT) {
803                 /* compatibility function for kernel 2.6.n where n <= 13 */
804                 return sensors_read_sysfs_chips_compat();
805         }
806
807         if (ret > 0)
808                 ret = -SENSORS_ERR_KERNEL;
809         return ret;
810 }
811
812 /* returns 0 if successful, !0 otherwise */
813 static int sensors_add_i2c_bus(const char *path, const char *classdev)
814 {
815         sensors_bus entry;
816
817         if (sscanf(classdev, "i2c-%hd", &entry.bus.nr) != 1 ||
818             entry.bus.nr == 9191) /* legacy ISA */
819                 return 0;
820         entry.bus.type = SENSORS_BUS_TYPE_I2C;
821
822         /* Get the adapter name from the classdev "name" attribute
823          * (Linux 2.6.20 and later). If it fails, fall back to
824          * the device "name" attribute (for older kernels). */
825         entry.adapter = sysfs_read_attr(path, "name");
826         if (!entry.adapter)
827                 entry.adapter = sysfs_read_attr(path, "device/name");
828         if (entry.adapter)
829                 sensors_add_proc_bus(&entry);
830
831         return 0;
832 }
833
834 /* returns 0 if successful, !0 otherwise */
835 int sensors_read_sysfs_bus(void)
836 {
837         int ret;
838
839         ret = sysfs_foreach_classdev("i2c-adapter", sensors_add_i2c_bus);
840         if (ret == ENOENT)
841                 ret = sysfs_foreach_busdev("i2c", sensors_add_i2c_bus);
842         if (ret && ret != ENOENT)
843                 return -SENSORS_ERR_KERNEL;
844
845         return 0;
846 }
847
848 int sensors_read_sysfs_attr(const sensors_chip_name *name,
849                             const sensors_subfeature *subfeature,
850                             double *value)
851 {
852         char n[NAME_MAX];
853         int f;
854
855         snprintf(n, NAME_MAX, "%s/%s", name->path, subfeature->name);
856         if ((f = open(n, O_RDONLY)) != -1) {
857                 int res, err = 0;
858                 char buf[512];
859                 int count;
860
861                 errno = 0;
862                 if ((count = read(f, buf, sizeof(buf) - 1)) == -1) {
863                         if (errno == EIO)
864                                 err = -SENSORS_ERR_IO;
865                         else 
866                                 err = -SENSORS_ERR_ACCESS_R;
867                 } else {
868                         buf[count] = '\0';
869                         errno = 0;
870                         res = sscanf(buf, "%lf", value);
871                         if (res == EOF && errno == EIO)
872                                 err = -SENSORS_ERR_IO;
873                         else if (res != 1)
874                                 err = -SENSORS_ERR_ACCESS_R;
875                 }
876                 res = close(f);
877                 if (err)
878                         return err;
879
880                 if (res != 0) {
881                         if (errno == EIO)
882                                 return -SENSORS_ERR_IO;
883                         else 
884                                 return -SENSORS_ERR_ACCESS_R;
885                 }
886                 if (!sensors_sysfs_no_scaling)
887                         *value /= get_type_scaling(subfeature->type);
888         } else
889                 return -SENSORS_ERR_KERNEL;
890
891         return 0;
892 }
893
894 int sensors_write_sysfs_attr(const sensors_chip_name *name,
895                              const sensors_subfeature *subfeature,
896                              double value)
897 {
898         char n[NAME_MAX];
899         FILE *f;
900
901         snprintf(n, NAME_MAX, "%s/%s", name->path, subfeature->name);
902         if ((f = fopen(n, "w"))) {
903                 int res, err = 0;
904
905                 if (!sensors_sysfs_no_scaling)
906                         value *= get_type_scaling(subfeature->type);
907                 res = fprintf(f, "%d", (int) value);
908                 if (res == -EIO)
909                         err = -SENSORS_ERR_IO;
910                 else if (res < 0)
911                         err = -SENSORS_ERR_ACCESS_W;
912                 res = fclose(f);
913                 if (err)
914                         return err;
915
916                 if (res == EOF) {
917                         if (errno == EIO)
918                                 return -SENSORS_ERR_IO;
919                         else 
920                                 return -SENSORS_ERR_ACCESS_W;
921                 }
922         } else
923                 return -SENSORS_ERR_KERNEL;
924
925         return 0;
926 }