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

Revision 4690, 8.4 kB (checked in by khali, 1 year ago)

Contrary to what the comment says, sensors_proc_bus_count may be a
perfectly valid bus number. We need to use a different value for
chip configuration entries we want to ignore.

  • 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
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 #include <stdlib.h>
21 #include <string.h>
22
23 #include "error.h"
24 #include "data.h"
25 #include "sensors.h"
26 #include "../version.h"
27
28 const char *libsensors_version = LM_VERSION;
29 const char *libsensors_date = LM_DATE;
30
31 sensors_chip *sensors_config_chips = NULL;
32 int sensors_config_chips_count = 0;
33 int sensors_config_chips_max = 0;
34
35 sensors_bus *sensors_config_busses = NULL;
36 int sensors_config_busses_count = 0;
37 int sensors_config_busses_max = 0;
38
39 sensors_proc_chips_entry *sensors_proc_chips = NULL;
40 int sensors_proc_chips_count = 0;
41 int sensors_proc_chips_max = 0;
42
43 sensors_bus *sensors_proc_bus = NULL;
44 int sensors_proc_bus_count = 0;
45 int sensors_proc_bus_max = 0;
46
47 static int sensors_substitute_chip(sensors_chip_name *name,int lineno);
48
49 /* Wow, this must be one of the ugliest functions I have ever written.
50    The idea is that it parses a chip name. These are valid names:
51
52      lm78-i2c-10-5e             *-i2c-10-5e
53      lm78-i2c-10-*              *-i2c-10-*
54      lm78-i2c-*-5e              *-i2c-*-5e
55      lm78-i2c-*-*               *-i2c-*-*
56      lm78-isa-10dd              *-isa-10dd
57      lm78-isa-*                 *-isa-*
58      lm78-*                     *-*
59                                 *
60    Here 'lm78' can be any prefix. To complicate matters, such a prefix
61    can also contain dashes (like lm78-j, for example!). 'i2c' and 'isa' are
62    literal strings, just like all dashes '-' and wildcards '*'. '10' can
63    be any decimal i2c bus number. '5e' can be any hexadecimal i2c device
64    address, and '10dd' any hexadecimal isa address.
65
66    If '*' is used in prefixes, together with dashes, ambiguous parses are
67    introduced. In that case, the prefix is kept as small as possible.
68
69    The 'prefix' part in the result is freshly allocated. All old contents
70    of res is overwritten. res itself is not allocated. In case of an error
71    return (ie. != 0), res is undefined, but all allocations are undone.
72
73    Don't tell me there are bugs in here, because I'll start screaming :-)
74 */
75
76 int sensors_parse_chip_name(const char *orig_name, sensors_chip_name *res)
77 {
78   char *part2, *part3, *part4;
79   char *name = strdup(orig_name);
80   int i;
81
82   /* Play it safe */
83   res->busname = NULL;
84
85   if (! name)
86     sensors_fatal_error("sensors_parse_chip_name","Allocating new name");
87   /* First split name in upto four pieces. */
88   if ((part4 = strrchr(name,'-')))
89     *part4++ = '\0';
90   if ((part3 = strrchr(name,'-')))
91     *part3++ = '\0';
92   if ((part2 = strrchr(name,'-')))
93     *part2++ = '\0';
94
95   /* No dashes found? */
96   if (! part4) {
97     if (!strcmp(name,"*")) {
98       res->prefix = SENSORS_CHIP_NAME_PREFIX_ANY;
99       res->bus = SENSORS_CHIP_NAME_BUS_ANY;
100       res->addr = SENSORS_CHIP_NAME_ADDR_ANY;
101       goto SUCCES;
102     } else
103       goto ERROR;
104   }
105
106   /* At least one dash found. Now part4 is either '*', or an address */
107   if (!strcmp(part4,"*"))
108     res->addr = SENSORS_CHIP_NAME_ADDR_ANY;
109   else {
110     if ((strlen(part4) > 4) || (strlen(part4) == 0))
111       goto ERROR;
112     res->addr = 0;
113     for (i = 0; ; i++) {
114       switch (part4[i]) {
115       case '0': case '1': case '2': case '3': case '4':
116       case '5': case '6': case '7': case '8': case '9':
117         res->addr = res->addr * 16 + part4[i] - '0';
118         break;
119       case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
120         res->addr = res->addr * 16 + part4[i] - 'a' + 10;
121         break;
122       case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
123         res->addr = res->addr * 16 + part4[i] - 'A' + 10;
124         break;
125       case 0:
126         goto DONE;
127       default:
128         goto ERROR;
129       }
130     }
131 DONE:;
132   }
133
134   /* OK. So let's look at part3. It must either be the number of the
135      i2c bus (and then part2 *must* be "i2c"), or it must be "isa",
136      or, if part4 was "*", it belongs to 'prefix'. Or no second dash
137      was found at all, of course. */
138   if (! part3) {
139     if (res->addr == SENSORS_CHIP_NAME_ADDR_ANY) {
140       res->bus = SENSORS_CHIP_NAME_BUS_ANY;
141     } else
142       goto ERROR;
143   } else if (!strcmp(part3,"isa")) {
144     res->bus = SENSORS_CHIP_NAME_BUS_ISA;
145     if (part2)
146       *(part2-1) = '-';
147   } else if (!strcmp(part3,"pci")) {
148     res->bus = SENSORS_CHIP_NAME_BUS_PCI;
149     if (part2)
150       *(part2-1) = '-';
151   } else if (part2 && !strcmp(part2,"i2c") && !strcmp(part3,"*"))
152     res->bus = SENSORS_CHIP_NAME_BUS_ANY_I2C;
153   else if (part2 && !strcmp(part2,"i2c")) {
154     if ((strlen(part3) > 3) || (strlen(part3) == 0))
155       goto ERROR;
156     res->bus = 0;
157     for (i = 0; ; i++) {
158       switch (part3[i]) {
159       case '0': case '1': case '2': case '3': case '4':
160       case '5': case '6': case '7': case '8': case '9':
161         res->bus = res->bus * 10 + part3[i] - '0';
162         break;
163       case 0:
164         goto DONE2;
165       default:
166         goto ERROR;
167       }
168     }
169 DONE2:;
170   } else if (res->addr == SENSORS_CHIP_NAME_ADDR_ANY) {
171     res->bus = SENSORS_CHIP_NAME_BUS_ANY;
172     if (part2)
173       *(part2-1) = '-';
174     *(part3-1) = '-';
175   } else if(part3 && part4) {
176     res->bus = SENSORS_CHIP_NAME_BUS_DUMMY;
177     if (! (res->busname = strdup(part3)))
178       sensors_fatal_error("sensors_parse_chip_name","Allocating new busname");
179   } else
180     goto ERROR;
181
182   if (!strcmp(name,"*"))
183     res->prefix = SENSORS_CHIP_NAME_PREFIX_ANY;
184   else if (! (res->prefix = strdup(name)))
185     sensors_fatal_error("sensors_parse_chip_name", "Allocating name prefix");
186   goto SUCCES;
187
188 SUCCES:
189   free(name);
190   return 0;
191
192 ERROR:
193   free(name);
194   return -SENSORS_ERR_CHIP_NAME;
195 }
196
197 int sensors_parse_i2cbus_name(const char *name, int *res)
198 {
199   int i;
200
201   if (! strcmp(name,"isa")) {
202     *res = SENSORS_CHIP_NAME_BUS_ISA;
203     return 0;
204   }
205   if (strncmp(name,"i2c-",4)) {
206     *res = SENSORS_CHIP_NAME_BUS_DUMMY;
207     return 0;
208   }
209   name += 4;
210   if ((strlen(name) > 3) || (strlen(name) == 0))
211     return -SENSORS_ERR_BUS_NAME;
212   *res = 0;
213   for (i = 0; ; i++) {
214     switch (name[i]) {
215     case '0': case '1': case '2': case '3': case '4':
216     case '5': case '6': case '7': case '8': case '9':
217       *res = *res * 10 + name[i] - '0';
218       break;
219     case 0:
220       return 0;
221     default:
222       return -SENSORS_ERR_BUS_NAME;
223     }
224   }
225 }
226
227
228 #define SENSORS_CHIP_NAME_BUS_IGNORE -42
229
230 int sensors_substitute_chip(sensors_chip_name *name,int lineno)
231 {
232   int i,j;
233   for (i = 0; i < sensors_config_busses_count; i++)
234     if (sensors_config_busses[i].number == name->bus)
235       break;
236
237   if (i == sensors_config_busses_count) {
238     sensors_parse_error("Undeclared i2c bus referenced",lineno);
239     name->bus = SENSORS_CHIP_NAME_BUS_IGNORE;
240     return -SENSORS_ERR_BUS_NAME;
241   }
242
243   /* We used to compare both the adapter and the algorithm names for
244      bus matching, but Linux 2.6 has no more names for algorithms, and
245      it was redundant anyway. So we now only rely on the adapter name. */
246   for (j = 0; j < sensors_proc_bus_count; j++) {
247     if (!strcmp(sensors_config_busses[i].adapter,
248                 sensors_proc_bus[j].adapter)) {
249       name->bus = sensors_proc_bus[j].number;
250       return 0;
251     }
252   }
253
254   /* We did not find a matching bus name, simply ignore this chip
255      config entry. */
256   name->bus = SENSORS_CHIP_NAME_BUS_IGNORE;
257   return 0;
258 }
259
260
261 int sensors_substitute_busses(void)
262 {
263   int err,i,j,lineno;
264   sensors_chip_name_list *chips;
265   int res=0;
266
267   for(i = 0; i < sensors_config_chips_count; i++) {
268     lineno = sensors_config_chips[i].lineno;
269     chips = &sensors_config_chips[i].chips;
270     for(j = 0; j < chips->fits_count; j++)
271       if ((chips->fits[j].bus != SENSORS_CHIP_NAME_BUS_ISA) &&
272           (chips->fits[j].bus != SENSORS_CHIP_NAME_BUS_PCI) &&
273           (chips->fits[j].bus != SENSORS_CHIP_NAME_BUS_DUMMY) &&
274           (chips->fits[j].bus != SENSORS_CHIP_NAME_BUS_ANY) &&
275           (chips->fits[j].bus != SENSORS_CHIP_NAME_BUS_ANY_I2C))
276         if ((err = sensors_substitute_chip(chips->fits+j, lineno)))
277           res = err;
278   }
279   return res;
280 }
Note: See TracBrowser for help on using the browser.