root/lm-sensors/branches/lm-sensors-3.0.0/lib/sysfs.c @ 4367

Revision 4367, 10.1 KB (checked in by jwrdegoede, 6 years ago)

-comment abituguru entry in lib/chips.c and prog/sensors/main.c, as the

abituguru seems to work well with the new dynamic chip support and generic
chip printroutines. note: the abituguru code should be completly removed in
the future.

-comment k8temp entry in lib/chips.c and prog/sensors/main.c, as the

k8temp seems to work well with the new dynamic chip support and generic
chip printroutines. note: the k8temp code should be completly removed in
the future.

-make the match for the subtype exact instead of a strncmp, otherwise

an alarm_enable flag gets classified as an alarm, leading to all sensors who
have their alarm enabled getting an alarm reported, as the alarm_enabled gets
read as alarm.

-and do the same for the _input match to check if this is a main or subfeature

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
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
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*/
19
20/* this define needed for strndup() */
21#define _GNU_SOURCE
22
23#include <string.h>
24#include <limits.h>
25#include <errno.h>
26#include <sysfs/libsysfs.h>
27#include <regex.h>
28#include "data.h"
29#include "error.h"
30#include "access.h"
31#include "general.h"
32#include "sysfs.h"
33
34int sensors_found_sysfs = 0;
35
36char sensors_sysfs_mount[NAME_MAX];
37
38#define DYNAMIC_CHIP_REGEX "\\([[:alpha:]]\\{1,\\}[[:digit:]]\\{0,\\}\\)\\(\\_[[:alpha:]]\\{1,\\}\\)\\{0,1\\}"
39
40static int sensors_read_dynamic_chip_check_mapping(
41        sensors_chip_feature *minor,
42        sensors_chip_feature *major,
43        regmatch_t *pmatch)
44{
45        if (pmatch[1].rm_so == -1 || pmatch[2].rm_so == -1 || 
46                        strncmp(minor->data.name, major->data.name, 
47                        pmatch[1].rm_eo - pmatch[1].rm_so)) {
48                return 0;
49        } else {
50                minor->data.mapping = 
51                        minor->data.compute_mapping = 
52                        major->data.number;
53                       
54                return 1;
55        }
56}
57
58static 
59sensors_chip_features sensors_read_dynamic_chip(struct sysfs_device *sysdir)
60{
61        int fnum = 1, i, last_major = -1;
62        struct sysfs_attribute *attr;
63        struct dlist *attrs;
64        sensors_chip_features ret = {0, 0};
65        sensors_chip_feature features[256], *dyn_features;
66        regex_t preg;
67        regmatch_t pmatch[3];
68        char *name;
69               
70        attrs = sysfs_get_device_attributes(sysdir);
71       
72        if (attrs == NULL)
73                return ret;
74       
75        regcomp(&preg, DYNAMIC_CHIP_REGEX, 0);
76               
77        dlist_for_each_data(attrs, attr, struct sysfs_attribute) {
78                sensors_chip_feature feature = { { 0, }, 0, }; 
79                name = attr->name;
80               
81                if (!strcmp(name, "name")) {
82                        ret.prefix = strndup(attr->value, strlen(attr->value) - 1);
83                        continue;
84                } else if (regexec(&preg, name, 3, pmatch, 0) != 0) {
85                        continue;
86                }
87               
88                feature.data.number = fnum;
89                feature.data.mode = (attr->method & (SYSFS_METHOD_SHOW|SYSFS_METHOD_STORE)) == 
90                                                                                        (SYSFS_METHOD_SHOW|SYSFS_METHOD_STORE) ?
91                                                                                        SENSORS_MODE_RW :
92                                                        (attr->method & SYSFS_METHOD_SHOW) ? SENSORS_MODE_R :
93                                                        (attr->method & SYSFS_METHOD_STORE) ? SENSORS_MODE_W :
94                                                        SENSORS_MODE_NO_RW;
95                feature.data.mapping = SENSORS_NO_MAPPING;
96                feature.data.compute_mapping = SENSORS_NO_MAPPING;
97                       
98                if (pmatch[2].rm_so != -1) {
99                        if (!strcmp(name + pmatch[2].rm_so, "_input")) {
100                                int last_match;
101                               
102                                /* copy only the part before the _ */
103                                feature.data.name = strndup(name, 
104                                        pmatch[1].rm_eo - pmatch[1].rm_so);
105                               
106                                /* check if the features previously read are sub devices of this major
107                                   and update their mapping accordingly */ 
108                                last_match = fnum - 1;
109                                for(i = fnum - 2; i >= 0; i--) {
110                                        if (regexec(&preg, features[i].data.name, 3, pmatch, 0) == -1 ||
111                                                        !sensors_read_dynamic_chip_check_mapping(&features[i],
112                                                        &feature, pmatch)) {
113                                                break;                                         
114                                        } else {
115                                                last_match = i;
116                                        }
117                                }
118                               
119                                /* if so the major should be in the list before any minor feature,
120                                        so swap with the oldest read */
121                                if (last_match < fnum - 1) {
122                                        sensors_chip_feature tmp = features[last_match];
123                                        features[last_match] = feature;
124                                        features[fnum - 1] = tmp;
125                                                       
126                                        last_major = last_match;
127                                       
128                                        goto NEXT_NUM; /* NOTE: goto used */
129                                } else {
130                                        last_major = fnum - 1;
131                                }
132                               
133                        } else {
134                                feature.data.name = strdup(name);
135                       
136                                if (last_major != -1 && 
137                                                !sensors_read_dynamic_chip_check_mapping(&feature,
138                                                                &features[last_major], pmatch)) {
139                                        last_major = -1; /* no more features for current major */
140                                }
141                        }
142                } else {
143                        feature.data.name = strdup(name);
144                }
145                       
146                features[fnum - 1] = feature;           
147NEXT_NUM:
148                fnum++;
149        }
150               
151        regfree(&preg);
152       
153        dyn_features = malloc(sizeof(sensors_chip_feature) * fnum);
154        if (dyn_features == NULL) {
155                sensors_fatal_error(__FUNCTION__,"Out of memory");
156        }
157       
158        for(i = 0; i < fnum - 1; i++) {
159                dyn_features[i] = features[i];
160        }
161        dyn_features[fnum - 1].data.name = 0;
162       
163        ret.feature = dyn_features;
164       
165        return ret;
166}
167
168/* returns !0 if sysfs filesystem was found, 0 otherwise */
169int sensors_init_sysfs(void)
170{
171        if (sysfs_get_mnt_path(sensors_sysfs_mount, NAME_MAX) == 0)
172                sensors_found_sysfs = 1;
173
174        return sensors_found_sysfs;
175}
176
177/* returns: 0 if successful, !0 otherwise */
178static int sensors_read_one_sysfs_chip(struct sysfs_device *dev)
179{
180        static int total_dynamic = 0;
181        int domain, bus, slot, fn, i;
182        struct sysfs_attribute *attr, *bus_attr;
183        char bus_path[SYSFS_PATH_MAX];
184        sensors_proc_chips_entry entry;
185
186        /* ignore any device without name attribute */
187        if (!(attr = sysfs_get_device_attr(dev, "name")))
188                return 0;
189
190        /* ignore subclients */
191        if (attr->len >= 11 && !strcmp(attr->value + attr->len - 11,
192                        " subclient\n"))
193                return 0;
194
195        /* also ignore eeproms */
196        if (!strcmp(attr->value, "eeprom\n"))
197                return 0;
198
199        /* NB: attr->value[attr->len-1] == '\n'; chop that off */
200        entry.name.prefix = strndup(attr->value, attr->len - 1);
201        if (!entry.name.prefix)
202                sensors_fatal_error(__FUNCTION__, "out of memory");
203
204        entry.name.busname = strdup(dev->path);
205        if (!entry.name.busname)
206                sensors_fatal_error(__FUNCTION__, "out of memory");
207
208        if (sscanf(dev->name, "%d-%x", &entry.name.bus, &entry.name.addr) == 2) {
209                /* find out if legacy ISA or not */
210                if (entry.name.bus == 9191)
211                        entry.name.bus = SENSORS_CHIP_NAME_BUS_ISA;
212                else {
213                        snprintf(bus_path, sizeof(bus_path),
214                                "%s/class/i2c-adapter/i2c-%d/device/name",
215                                sensors_sysfs_mount, entry.name.bus);
216
217                        if ((bus_attr = sysfs_open_attribute(bus_path))) {
218                                if (sysfs_read_attribute(bus_attr))
219                                        return -SENSORS_ERR_PARSE;
220
221                                if (bus_attr->value
222                                 && !strncmp(bus_attr->value, "ISA ", 4))
223                                        entry.name.bus = SENSORS_CHIP_NAME_BUS_ISA;
224
225                                sysfs_close_attribute(bus_attr);
226                        }
227                }
228        } else if (sscanf(dev->name, "%*[a-z0-9_].%d", &entry.name.addr) == 1) {
229                /* must be new ISA (platform driver) */
230                entry.name.bus = SENSORS_CHIP_NAME_BUS_ISA;
231        } else if (sscanf(dev->name, "%x:%x:%x.%x", &domain, &bus, &slot, &fn) == 4) {
232                /* PCI */
233                entry.name.addr = (domain << 16) + (bus << 8) + (slot << 3) + fn;
234                entry.name.bus = SENSORS_CHIP_NAME_BUS_PCI;
235        } else
236                return -SENSORS_ERR_PARSE;
237       
238        /* check whether this chip is known in the static list */ 
239        for (i = 0; sensors_chip_features_list[i].prefix; i++)
240                if (!strcasecmp(sensors_chip_features_list[i].prefix, entry.name.prefix))
241                        break;
242
243        /* if no chip definition matches */
244        if (!sensors_chip_features_list[i].prefix && 
245                total_dynamic < N_PLACEHOLDER_ELEMENTS) {
246                sensors_chip_features n_entry = sensors_read_dynamic_chip(dev);
247
248                /* skip to end of list */
249                for(i = 0; sensors_chip_features_list[i].prefix; i++);
250
251                sensors_chip_features_list[i] = n_entry;       
252
253                total_dynamic++;
254        }
255               
256        sensors_add_proc_chips(&entry);
257
258        return 0;
259}
260
261/* returns 0 if successful, !0 otherwise */
262static int sensors_read_sysfs_chips_compat(void)
263{
264        struct sysfs_bus *bus;
265        struct dlist *devs;
266        struct sysfs_device *dev;
267        int ret = 0;
268
269        if (!(bus = sysfs_open_bus("i2c"))) {
270                if (errno && errno != ENOENT)
271                        ret = -SENSORS_ERR_PROC;
272                goto exit0;
273        }
274
275        if (!(devs = sysfs_get_bus_devices(bus))) {
276                if (errno && errno != ENOENT)
277                        ret = -SENSORS_ERR_PROC;
278                goto exit1;
279        }
280
281        dlist_for_each_data(devs, dev, struct sysfs_device)
282                if ((ret = sensors_read_one_sysfs_chip(dev)))
283                        goto exit1;
284
285exit1:
286        /* this frees bus and devs */
287        sysfs_close_bus(bus);
288
289exit0:
290        return ret;
291}
292
293/* returns 0 if successful, !0 otherwise */
294int sensors_read_sysfs_chips(void)
295{
296        struct sysfs_class *cls;
297        struct dlist *clsdevs;
298        struct sysfs_class_device *clsdev;
299        int ret = 0;
300
301        if (!(cls = sysfs_open_class("hwmon"))) {
302                /* compatibility function for kernel 2.6.n where n <= 13 */
303                return sensors_read_sysfs_chips_compat();
304        }
305
306        if (!(clsdevs = sysfs_get_class_devices(cls))) {
307                if (errno && errno != ENOENT)
308                        ret = -SENSORS_ERR_PROC;
309                goto exit;
310        }
311
312        dlist_for_each_data(clsdevs, clsdev, struct sysfs_class_device) {
313                struct sysfs_device *dev;
314                if (!(dev = sysfs_get_classdev_device(clsdev))) {
315                        ret = -SENSORS_ERR_PROC;
316                        goto exit;
317                }
318                if ((ret = sensors_read_one_sysfs_chip(dev)))
319                        goto exit;
320        }
321
322exit:
323        /* this frees cls and clsdevs */
324        sysfs_close_class(cls);
325        return ret;
326}
327
328/* returns 0 if successful, !0 otherwise */
329int sensors_read_sysfs_bus(void)
330{
331        struct sysfs_class *cls;
332        struct dlist *clsdevs;
333        struct sysfs_class_device *clsdev;
334        sensors_bus entry;
335        int ret = 0;
336
337        if (!(cls = sysfs_open_class("i2c-adapter"))) {
338                if (errno && errno != ENOENT)
339                        ret = -SENSORS_ERR_PROC;
340                goto exit0;
341        }
342
343        if (!(clsdevs = sysfs_get_class_devices(cls))) {
344                if (errno && errno != ENOENT)
345                        ret = -SENSORS_ERR_PROC;
346                goto exit1;
347        }
348
349        dlist_for_each_data(clsdevs, clsdev, struct sysfs_class_device) {
350                struct sysfs_device *dev;
351                struct sysfs_attribute *attr;
352
353                /* Get the adapter name from the classdev "name" attribute
354                 * (Linux 2.6.20 and later). If it fails, fall back to
355                 * the device "name" attribute (for older kernels). */
356                if (!(attr = sysfs_get_classdev_attr(clsdev, "name"))
357                 && !((dev = sysfs_get_classdev_device(clsdev)) &&
358                      (attr = sysfs_get_device_attr(dev, "name"))))
359                        continue;
360
361                /* NB: attr->value[attr->len-1] == '\n'; chop that off */
362                entry.adapter = strndup(attr->value, attr->len - 1);
363                if (!entry.adapter)
364                        sensors_fatal_error(__FUNCTION__, "out of memory");
365
366                if (!strncmp(entry.adapter, "ISA ", 4)) {
367                        entry.number = SENSORS_CHIP_NAME_BUS_ISA;
368                } else if (sscanf(clsdev->name, "i2c-%d", &entry.number) != 1) {
369                        entry.number = SENSORS_CHIP_NAME_BUS_DUMMY;
370                }
371
372                sensors_add_proc_bus(&entry);
373        }
374
375exit1:
376        /* this frees *cls _and_ *clsdevs */
377        sysfs_close_class(cls);
378
379exit0:
380        return ret;
381}
382
Note: See TracBrowser for help on using the browser.