root/lm-sensors/tags/V2-10-4/lib/sysfs.c

Revision 4337, 6.1 kB (checked in by khali, 2 years ago)

library: Handle the i2c-isa case properly even after the class_dev
removal. In recent kernels we can detect i2c-isa devices by checking
the i2c bus number: i2c-isa always uses 9191 as its bus number.

  • 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
33 int sensors_found_sysfs = 0;
34
35 char sensors_sysfs_mount[NAME_MAX];
36
37 /* returns !0 if sysfs filesystem was found, 0 otherwise */
38 int 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 */
47 static 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 */
112 static 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
135 exit1:
136         /* this frees bus and devs */
137         sysfs_close_bus(bus);
138
139 exit0:
140         return ret;
141 }
142
143 /* returns 0 if successful, !0 otherwise */
144 int 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
172 exit:
173         /* this frees cls and clsdevs */
174         sysfs_close_class(cls);
175         return ret;
176 }
177
178 /* returns 0 if successful, !0 otherwise */
179 int 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
225 exit1:
226         /* this frees *cls _and_ *clsdevs */
227         sysfs_close_class(cls);
228
229 exit0:
230         return ret;
231 }
232
Note: See TracBrowser for help on using the browser.