~mmach/netext73/lm-sensors

« back to all changes in this revision

Viewing changes to lib/sysfs.c

  • Committer: mmach
  • Date: 2020-02-05 20:28:34 UTC
  • Revision ID: netbit73@gmail.com-20200205202834-zc3sla47j9e700w5
3.6

Show diffs side-by-side

added added

removed removed

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