root/lm-sensors/branches/lm-sensors-3.0.0/lib/data.c @ 5176

Revision 5176, 6.9 KB (checked in by khali, 5 years ago)

Add support for virtual hwmon devices. This closes Red Hat bug #437637
and ticket #2305.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    data.c - Part of libsensors, a Linux library for reading sensor data.
3    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
4    Copyright (C) 2007        Jean Delvare <khali@linux-fr.org>
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program 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 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 <stdlib.h>
26#include <string.h>
27
28#include "access.h"
29#include "error.h"
30#include "data.h"
31#include "sensors.h"
32#include "../version.h"
33
34const char *libsensors_version = LM_VERSION;
35
36sensors_chip *sensors_config_chips = NULL;
37int sensors_config_chips_count = 0;
38int sensors_config_chips_max = 0;
39
40sensors_bus *sensors_config_busses = NULL;
41int sensors_config_busses_count = 0;
42int sensors_config_busses_max = 0;
43
44sensors_chip_features *sensors_proc_chips = NULL;
45int sensors_proc_chips_count = 0;
46int sensors_proc_chips_max = 0;
47
48sensors_bus *sensors_proc_bus = NULL;
49int sensors_proc_bus_count = 0;
50int sensors_proc_bus_max = 0;
51
52static int sensors_substitute_chip(sensors_chip_name *name, int lineno);
53
54/*
55   Parse a chip name to the internal representation. These are valid names:
56
57     lm78-i2c-10-5e             *-i2c-10-5e
58     lm78-i2c-10-*              *-i2c-10-*
59     lm78-i2c-*-5e              *-i2c-*-5e
60     lm78-i2c-*-*               *-i2c-*-*
61     lm78-isa-10dd              *-isa-10dd
62     lm78-isa-*                 *-isa-*
63     lm78-*                     *-*
64
65   Here 'lm78' can be any prefix. 'i2c' and 'isa' are
66   literal strings, just like all dashes '-' and wildcards '*'. '10' can
67   be any decimal i2c bus number. '5e' can be any hexadecimal i2c device
68   address, and '10dd' any hexadecimal isa address.
69
70   The 'prefix' part in the result is freshly allocated. All old contents
71   of res is overwritten. res itself is not allocated. In case of an error
72   return (ie. != 0), res is undefined, but all allocations are undone.
73*/
74
75int sensors_parse_chip_name(const char *name, sensors_chip_name *res)
76{
77        char *dash;
78
79        /* First, the prefix. It's either "*" or a real chip name. */
80        if (!strncmp(name, "*-", 2)) {
81                res->prefix = SENSORS_CHIP_NAME_PREFIX_ANY;
82                name += 2;
83        } else {
84                if (!(dash = strchr(name, '-')))
85                        return -SENSORS_ERR_CHIP_NAME;
86                res->prefix = strndup(name, dash - name);
87                if (!res->prefix)
88                        sensors_fatal_error("sensors_parse_chip_name",
89                                            "Allocating name prefix");
90                name = dash + 1;
91        }
92
93        /* Then we have either a sole "*" (all chips with this name) or a bus
94           type and an address. */
95        if (!strcmp(name, "*")) {
96                res->bus.type = SENSORS_BUS_TYPE_ANY;
97                res->bus.nr = SENSORS_BUS_NR_ANY;
98                res->addr = SENSORS_CHIP_NAME_ADDR_ANY;
99                return 0;
100        }
101
102        if (!(dash = strchr(name, '-')))
103                goto ERROR;
104        if (!strncmp(name, "i2c", dash - name))
105                res->bus.type = SENSORS_BUS_TYPE_I2C;
106        else if (!strncmp(name, "isa", dash - name))
107                res->bus.type = SENSORS_BUS_TYPE_ISA;
108        else if (!strncmp(name, "pci", dash - name))
109                res->bus.type = SENSORS_BUS_TYPE_PCI;
110        else if (!strncmp(name, "spi", dash - name))
111                res->bus.type = SENSORS_BUS_TYPE_SPI;
112        else if (!strncmp(name, "virtual", dash - name))
113                res->bus.type = SENSORS_BUS_TYPE_VIRTUAL;
114        else
115                goto ERROR;
116        name = dash + 1;
117
118        /* Some bus types (i2c, spi) have an additional bus number.
119           For these, the next part is either a "*" (any bus of that type)
120           or a decimal number. */
121        switch (res->bus.type) {
122        case SENSORS_BUS_TYPE_I2C:
123        case SENSORS_BUS_TYPE_SPI:
124                if (!strncmp(name, "*-", 2)) {
125                        res->bus.nr = SENSORS_BUS_NR_ANY;
126                        name += 2;
127                        break;
128                }
129
130                res->bus.nr = strtoul(name, &dash, 10);
131                if (*name == '\0' || *dash != '-' || res->bus.nr < 0)
132                        goto ERROR;
133                name = dash + 1;
134                break;
135        default:
136                res->bus.nr = SENSORS_BUS_NR_ANY;
137        }
138
139        /* Last part is the chip address, or "*" for any address. */
140        if (!strcmp(name, "*")) {
141                res->addr = SENSORS_CHIP_NAME_ADDR_ANY;
142        } else {
143                res->addr = strtoul(name, &dash, 16);
144                if (*name == '\0' || *dash != '\0' || res->addr < 0)
145                        goto ERROR;
146        }
147
148        return 0;
149
150ERROR:
151        free(res->prefix);
152        return -SENSORS_ERR_CHIP_NAME;
153}
154
155int sensors_snprintf_chip_name(char *str, size_t size,
156                               const sensors_chip_name *chip)
157{
158        if (sensors_chip_name_has_wildcards(chip))
159                return -SENSORS_ERR_WILDCARDS;
160
161        switch (chip->bus.type) {
162        case SENSORS_BUS_TYPE_ISA:
163                return snprintf(str, size, "%s-isa-%04x", chip->prefix,
164                                chip->addr);
165        case SENSORS_BUS_TYPE_PCI:
166                return snprintf(str, size, "%s-pci-%04x", chip->prefix,
167                                chip->addr);
168        case SENSORS_BUS_TYPE_I2C:
169                return snprintf(str, size, "%s-i2c-%hd-%02x", chip->prefix,
170                                chip->bus.nr, chip->addr);
171        case SENSORS_BUS_TYPE_SPI:
172                return snprintf(str, size, "%s-spi-%hd-%x", chip->prefix,
173                                chip->bus.nr, chip->addr);
174        case SENSORS_BUS_TYPE_VIRTUAL:
175                return snprintf(str, size, "%s-virtual-%x", chip->prefix,
176                                chip->addr);
177        }
178
179        return -SENSORS_ERR_CHIP_NAME;
180}
181
182int sensors_parse_bus_id(const char *name, sensors_bus_id *bus)
183{
184        char *endptr;
185
186        if (strncmp(name, "i2c-", 4)) {
187                return -SENSORS_ERR_BUS_NAME;
188        }
189        name += 4;
190        bus->type = SENSORS_BUS_TYPE_I2C;
191        bus->nr = strtoul(name, &endptr, 10);
192        if (*name == '\0' || *endptr != '\0' || bus->nr < 0)
193                return -SENSORS_ERR_BUS_NAME;
194        return 0;
195}
196
197int sensors_substitute_chip(sensors_chip_name *name, int lineno)
198{
199        int i, j;
200        for (i = 0; i < sensors_config_busses_count; i++)
201                if (sensors_config_busses[i].bus.type == name->bus.type &&
202                    sensors_config_busses[i].bus.nr == name->bus.nr)
203                        break;
204
205        if (i == sensors_config_busses_count) {
206                sensors_parse_error("Undeclared bus id referenced", lineno);
207                name->bus.nr = SENSORS_BUS_NR_IGNORE;
208                return -SENSORS_ERR_BUS_NAME;
209        }
210
211        /* Compare the adapter names */
212        for (j = 0; j < sensors_proc_bus_count; j++) {
213                if (!strcmp(sensors_config_busses[i].adapter,
214                            sensors_proc_bus[j].adapter)) {
215                        name->bus.nr = sensors_proc_bus[j].bus.nr;
216                        return 0;
217                }
218        }
219
220        /* We did not find a matching bus name, simply ignore this chip
221           config entry. */
222        name->bus.nr = SENSORS_BUS_NR_IGNORE;
223        return 0;
224}
225
226int sensors_substitute_busses(void)
227{
228        int err, i, j, lineno;
229        sensors_chip_name_list *chips;
230        int res = 0;
231
232        for (i = 0; i < sensors_config_chips_count; i++) {
233                lineno = sensors_config_chips[i].lineno;
234                chips = &sensors_config_chips[i].chips;
235                for (j = 0; j < chips->fits_count; j++) {
236                        /* We can only substitute if a specific bus number
237                           is given. */
238                        if (chips->fits[j].bus.nr == SENSORS_BUS_NR_ANY)
239                                continue;
240
241                        err = sensors_substitute_chip(&chips->fits[j], lineno);
242                        if (err)
243                                res = err;
244                }
245        }
246        return res;
247}
Note: See TracBrowser for help on using the browser.