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

Revision 4098, 8.4 kB (checked in by ruik, 2 years ago)

Add PCI bus support

  • 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, ambigious 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 new name");
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 int sensors_substitute_chip(sensors_chip_name *name,int lineno)
229 {
230   int i,j;
231   for (i = 0; i < sensors_config_busses_count; i++)
232     if (sensors_config_busses[i].number == name->bus)
233       break;
234
235   if (i == sensors_config_busses_count) {
236     sensors_parse_error("Undeclared i2c bus referenced",lineno);
237     name->bus = sensors_proc_bus_count;
238     return -SENSORS_ERR_BUS_NAME;
239   }
240
241   /* We used to compare both the adapter and the algorithm names for
242      bus matching, but Linux 2.6 has no more names for algorithms, and
243      it was redundant anyway. So we now only rely on the adapter name. */
244   for (j = 0; j < sensors_proc_bus_count; j++) {
245     if (!strcmp(sensors_config_busses[i].adapter,
246                 sensors_proc_bus[j].adapter)) {
247       name->bus = sensors_proc_bus[j].number;
248       return 0;
249     }
250   }
251
252   /* We did not find anything. sensors_proc_bus_count is not a valid
253      bus number, so it will never be matched. Good. */
254   name->bus = sensors_proc_bus_count;
255   return 0;
256 }
257
258      
259 int sensors_substitute_busses(void)
260 {
261   int err,i,j,lineno;
262   sensors_chip_name_list *chips;
263   int res=0;
264  
265   for(i = 0; i < sensors_config_chips_count; i++) {
266     lineno = sensors_config_chips[i].lineno;
267     chips = &sensors_config_chips[i].chips;
268     for(j = 0; j < chips->fits_count; j++)
269       if ((chips->fits[j].bus != SENSORS_CHIP_NAME_BUS_ISA) &&
270           (chips->fits[j].bus != SENSORS_CHIP_NAME_BUS_PCI) &&
271           (chips->fits[j].bus != SENSORS_CHIP_NAME_BUS_DUMMY) &&
272           (chips->fits[j].bus != SENSORS_CHIP_NAME_BUS_ANY) &&
273           (chips->fits[j].bus != SENSORS_CHIP_NAME_BUS_ANY_I2C))
274         if ((err = sensors_substitute_chip(chips->fits+j, lineno)))
275           res = err;
276   }
277   return res;
278 }
Note: See TracBrowser for help on using the browser.