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

Revision 4357, 6.1 KB (checked in by mmh, 6 years ago)

Merge from trunk (4303:4355) out to 3.0.0 branch.

  • 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 "data.h"
28#include "error.h"
29#include "access.h"
30#include "general.h"
31#include "sysfs.h"
32
33int sensors_found_sysfs = 0;
34
35char sensors_sysfs_mount[NAME_MAX];
36
37/* returns !0 if sysfs filesystem was found, 0 otherwise */
38int sensors_init_sysfs(void)
39{
40        if (sysfs_get_mnt_path(sensors_sysfs_mount, NAME_MAX) == 0)
41                sensors_found_sysfs = 1;
42
43        return sensors_found_sysfs;
44}
45
46/* returns: 0 if successful, !0 otherwise */
47static int sensors_read_one_sysfs_chip(struct sysfs_device *dev)
48{
49        int domain, bus, slot, fn;
50        struct sysfs_attribute *attr, *bus_attr;
51        char bus_path[SYSFS_PATH_MAX];
52        sensors_proc_chips_entry entry;
53
54        /* ignore any device without name attribute */
55        if (!(attr = sysfs_get_device_attr(dev, "name")))
56                return 0;
57
58        /* ignore subclients */
59        if (attr->len >= 11 && !strcmp(attr->value + attr->len - 11,
60                        " subclient\n"))
61                return 0;
62
63        /* also ignore eeproms */
64        if (!strcmp(attr->value, "eeprom\n"))
65                return 0;
66
67        /* NB: attr->value[attr->len-1] == '\n'; chop that off */
68        entry.name.prefix = strndup(attr->value, attr->len - 1);
69        if (!entry.name.prefix)
70                sensors_fatal_error(__FUNCTION__, "out of memory");
71
72        entry.name.busname = strdup(dev->path);
73        if (!entry.name.busname)
74                sensors_fatal_error(__FUNCTION__, "out of memory");
75
76        if (sscanf(dev->name, "%d-%x", &entry.name.bus, &entry.name.addr) == 2) {
77                /* find out if legacy ISA or not */
78                if (entry.name.bus == 9191)
79                        entry.name.bus = SENSORS_CHIP_NAME_BUS_ISA;
80                else {
81                        snprintf(bus_path, sizeof(bus_path),
82                                "%s/class/i2c-adapter/i2c-%d/device/name",
83                                sensors_sysfs_mount, entry.name.bus);
84
85                        if ((bus_attr = sysfs_open_attribute(bus_path))) {
86                                if (sysfs_read_attribute(bus_attr))
87                                        return -SENSORS_ERR_PARSE;
88
89                                if (bus_attr->value
90                                 && !strncmp(bus_attr->value, "ISA ", 4))
91                                        entry.name.bus = SENSORS_CHIP_NAME_BUS_ISA;
92
93                                sysfs_close_attribute(bus_attr);
94                        }
95                }
96        } else if (sscanf(dev->name, "%*[a-z0-9_].%d", &entry.name.addr) == 1) {
97                /* must be new ISA (platform driver) */
98                entry.name.bus = SENSORS_CHIP_NAME_BUS_ISA;
99        } else if (sscanf(dev->name, "%x:%x:%x.%x", &domain, &bus, &slot, &fn) == 4) {
100                /* PCI */
101                entry.name.addr = (domain << 16) + (bus << 8) + (slot << 3) + fn;
102                entry.name.bus = SENSORS_CHIP_NAME_BUS_PCI;
103        } else
104                return -SENSORS_ERR_PARSE;
105
106        sensors_add_proc_chips(&entry);
107
108        return 0;
109}
110
111/* returns 0 if successful, !0 otherwise */
112static int sensors_read_sysfs_chips_compat(void)
113{
114        struct sysfs_bus *bus;
115        struct dlist *devs;
116        struct sysfs_device *dev;
117        int ret = 0;
118
119        if (!(bus = sysfs_open_bus("i2c"))) {
120                if (errno && errno != ENOENT)
121                        ret = -SENSORS_ERR_PROC;
122                goto exit0;
123        }
124
125        if (!(devs = sysfs_get_bus_devices(bus))) {
126                if (errno && errno != ENOENT)
127                        ret = -SENSORS_ERR_PROC;
128                goto exit1;
129        }
130
131        dlist_for_each_data(devs, dev, struct sysfs_device)
132                if ((ret = sensors_read_one_sysfs_chip(dev)))
133                        goto exit1;
134
135exit1:
136        /* this frees bus and devs */
137        sysfs_close_bus(bus);
138
139exit0:
140        return ret;
141}
142
143/* returns 0 if successful, !0 otherwise */
144int sensors_read_sysfs_chips(void)
145{
146        struct sysfs_class *cls;
147        struct dlist *clsdevs;
148        struct sysfs_class_device *clsdev;
149        int ret = 0;
150
151        if (!(cls = sysfs_open_class("hwmon"))) {
152                /* compatibility function for kernel 2.6.n where n <= 13 */
153                return sensors_read_sysfs_chips_compat();
154        }
155
156        if (!(clsdevs = sysfs_get_class_devices(cls))) {
157                if (errno && errno != ENOENT)
158                        ret = -SENSORS_ERR_PROC;
159                goto exit;
160        }
161
162        dlist_for_each_data(clsdevs, clsdev, struct sysfs_class_device) {
163                struct sysfs_device *dev;
164                if (!(dev = sysfs_get_classdev_device(clsdev))) {
165                        ret = -SENSORS_ERR_PROC;
166                        goto exit;
167                }
168                if ((ret = sensors_read_one_sysfs_chip(dev)))
169                        goto exit;
170        }
171
172exit:
173        /* this frees cls and clsdevs */
174        sysfs_close_class(cls);
175        return ret;
176}
177
178/* returns 0 if successful, !0 otherwise */
179int sensors_read_sysfs_bus(void)
180{
181        struct sysfs_class *cls;
182        struct dlist *clsdevs;
183        struct sysfs_class_device *clsdev;
184        sensors_bus entry;
185        int ret = 0;
186
187        if (!(cls = sysfs_open_class("i2c-adapter"))) {
188                if (errno && errno != ENOENT)
189                        ret = -SENSORS_ERR_PROC;
190                goto exit0;
191        }
192
193        if (!(clsdevs = sysfs_get_class_devices(cls))) {
194                if (errno && errno != ENOENT)
195                        ret = -SENSORS_ERR_PROC;
196                goto exit1;
197        }
198
199        dlist_for_each_data(clsdevs, clsdev, struct sysfs_class_device) {
200                struct sysfs_device *dev;
201                struct sysfs_attribute *attr;
202
203                /* Get the adapter name from the classdev "name" attribute
204                 * (Linux 2.6.20 and later). If it fails, fall back to
205                 * the device "name" attribute (for older kernels). */
206                if (!(attr = sysfs_get_classdev_attr(clsdev, "name"))
207                 && !((dev = sysfs_get_classdev_device(clsdev)) &&
208                      (attr = sysfs_get_device_attr(dev, "name"))))
209                        continue;
210
211                /* NB: attr->value[attr->len-1] == '\n'; chop that off */
212                entry.adapter = strndup(attr->value, attr->len - 1);
213                if (!entry.adapter)
214                        sensors_fatal_error(__FUNCTION__, "out of memory");
215
216                if (!strncmp(entry.adapter, "ISA ", 4)) {
217                        entry.number = SENSORS_CHIP_NAME_BUS_ISA;
218                } else if (sscanf(clsdev->name, "i2c-%d", &entry.number) != 1) {
219                        entry.number = SENSORS_CHIP_NAME_BUS_DUMMY;
220                }
221
222                sensors_add_proc_bus(&entry);
223        }
224
225exit1:
226        /* this frees *cls _and_ *clsdevs */
227        sysfs_close_class(cls);
228
229exit0:
230        return ret;
231}
232
Note: See TracBrowser for help on using the browser.