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

Revision 4267, 6.0 kB (checked in by khali, 2 years ago)

libsensors: Get the i2c adapter names from the class device's "name"
attribute, falling back to the device's "name" attribute for
compatibility only. This change is needed to match ongoing cleanups in
Linux 2.6's i2c-core. i2c adapters will soon be class devices only, the
legacy i2c_adapter devices and driver are being removed.

  • 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                 snprintf(bus_path, sizeof(bus_path),
79                                 "%s/class/i2c-adapter/i2c-%d/device/name",
80                                 sensors_sysfs_mount, entry.name.bus);
81
82                 if ((bus_attr = sysfs_open_attribute(bus_path))) {
83                         if (sysfs_read_attribute(bus_attr))
84                                 return -SENSORS_ERR_PARSE;
85
86                         if (bus_attr->value && !strncmp(bus_attr->value, "ISA ", 4))
87                                 entry.name.bus = SENSORS_CHIP_NAME_BUS_ISA;
88
89                         sysfs_close_attribute(bus_attr);
90                 }
91         } else if (sscanf(dev->name, "%*[a-z0-9_].%d", &entry.name.addr) == 1) {
92                 /* must be new ISA (platform driver) */
93                 entry.name.bus = SENSORS_CHIP_NAME_BUS_ISA;
94         } else if (sscanf(dev->name, "%x:%x:%x.%x", &domain, &bus, &slot, &fn) == 4) {
95                 /* PCI */
96                 entry.name.addr = (domain << 16) + (bus << 8) + (slot << 3) + fn;
97                 entry.name.bus = SENSORS_CHIP_NAME_BUS_PCI;
98         } else
99                 return -SENSORS_ERR_PARSE;
100
101         sensors_add_proc_chips(&entry);
102
103         return 0;
104 }
105
106 /* returns 0 if successful, !0 otherwise */
107 static int sensors_read_sysfs_chips_compat(void)
108 {
109         struct sysfs_bus *bus;
110         struct dlist *devs;
111         struct sysfs_device *dev;
112         int ret = 0;
113
114         if (!(bus = sysfs_open_bus("i2c"))) {
115                 if (errno && errno != ENOENT)
116                         ret = -SENSORS_ERR_PROC;
117                 goto exit0;
118         }
119
120         if (!(devs = sysfs_get_bus_devices(bus))) {
121                 if (errno && errno != ENOENT)
122                         ret = -SENSORS_ERR_PROC;
123                 goto exit1;
124         }
125
126         dlist_for_each_data(devs, dev, struct sysfs_device)
127                 if ((ret = sensors_read_one_sysfs_chip(dev)))
128                         goto exit1;
129
130 exit1:
131         /* this frees bus and devs */
132         sysfs_close_bus(bus);
133
134 exit0:
135         return ret;
136 }
137
138 /* returns 0 if successful, !0 otherwise */
139 int sensors_read_sysfs_chips(void)
140 {
141         struct sysfs_class *cls;
142         struct dlist *clsdevs;
143         struct sysfs_class_device *clsdev;
144         int ret = 0;
145
146         if (!(cls = sysfs_open_class("hwmon"))) {
147                 /* compatibility function for kernel 2.6.n where n <= 13 */
148                 return sensors_read_sysfs_chips_compat();
149         }
150
151         if (!(clsdevs = sysfs_get_class_devices(cls))) {
152                 if (errno && errno != ENOENT)
153                         ret = -SENSORS_ERR_PROC;
154                 goto exit;
155         }
156
157         dlist_for_each_data(clsdevs, clsdev, struct sysfs_class_device) {
158                 struct sysfs_device *dev;
159                 if (!(dev = sysfs_get_classdev_device(clsdev))) {
160                         ret = -SENSORS_ERR_PROC;
161                         goto exit;
162                 }
163                 if ((ret = sensors_read_one_sysfs_chip(dev)))
164                         goto exit;
165         }
166
167 exit:
168         /* this frees cls and clsdevs */
169         sysfs_close_class(cls);
170         return ret;
171 }
172
173 /* returns 0 if successful, !0 otherwise */
174 int sensors_read_sysfs_bus(void)
175 {
176         struct sysfs_class *cls;
177         struct dlist *clsdevs;
178         struct sysfs_class_device *clsdev;
179         sensors_bus entry;
180         int ret = 0;
181
182         if (!(cls = sysfs_open_class("i2c-adapter"))) {
183                 if (errno && errno != ENOENT)
184                         ret = -SENSORS_ERR_PROC;
185                 goto exit0;
186         }
187
188         if (!(clsdevs = sysfs_get_class_devices(cls))) {
189                 if (errno && errno != ENOENT)
190                         ret = -SENSORS_ERR_PROC;
191                 goto exit1;
192         }
193
194         dlist_for_each_data(clsdevs, clsdev, struct sysfs_class_device) {
195                 struct sysfs_device *dev;
196                 struct sysfs_attribute *attr;
197
198                 if (!(dev = sysfs_get_classdev_device(clsdev)))
199                         continue;
200                 /* Get the adapter name from the classdev "name" attribute
201                  * (Linux 2.6.20 and later). If it fails, fall back to
202                  * the device "name" attribute (for older kernels). */
203                 if (!(attr = sysfs_get_classdev_attr(clsdev, "name"))
204                  && !(attr = sysfs_get_device_attr(dev, "name")))
205                         continue;
206
207                 /* NB: attr->value[attr->len-1] == '\n'; chop that off */
208                 entry.adapter = strndup(attr->value, attr->len - 1);
209                 if (!entry.adapter)
210                         sensors_fatal_error(__FUNCTION__, "out of memory");
211
212                 if (!strncmp(entry.adapter, "ISA ", 4)) {
213                         entry.number = SENSORS_CHIP_NAME_BUS_ISA;
214                 } else if (sscanf(clsdev->name, "i2c-%d", &entry.number) != 1) {
215                         entry.number = SENSORS_CHIP_NAME_BUS_DUMMY;
216                 }
217
218                 sensors_add_proc_bus(&entry);
219         }
220
221 exit1:
222         /* this frees *cls _and_ *clsdevs */
223         sysfs_close_class(cls);
224
225 exit0:
226         return ret;
227 }
228
Note: See TracBrowser for help on using the browser.