root/lm-sensors/trunk/lib/data.c @ 5786

Revision 5786, 7.9 KB (checked in by khali, 4 years ago)

Add support for HID devices.

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