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