]>
Commit | Line | Data |
---|---|---|
93afd047 MT |
1 | #include <stdlib.h> |
2 | #include <stdio.h> | |
3 | #include <string.h> | |
4 | #include <errno.h> | |
5 | #include "hd.h" | |
6 | #include "hd_int.h" | |
7 | ||
8 | #define debprintf(a...) | |
9 | // #define debprintf(a...) fprintf(stderr, ## a) | |
10 | ||
11 | /* private data */ | |
12 | ||
13 | #include "cdb/isdn_cdb.h" | |
14 | #include "cdb/cdb_hwdb.h" | |
15 | ||
16 | static int CDBISDN_vendor_cnt; | |
17 | static int CDBISDN_card_cnt; | |
18 | static int CDBISDN_vario_cnt; | |
19 | static int CDBISDN_name_size; | |
20 | static char *CDBISDN_names; | |
21 | ||
22 | static cdb_isdn_vendor *cdb_isdnvendor_info; | |
23 | static cdb_isdn_card *cdb_isdncard_info; | |
24 | static int *cdb_isdncard_idsorted; | |
25 | static cdb_isdn_vario *cdb_isdnvario_info; | |
26 | static int cdb_dbversion; | |
27 | static char cdb_date[32]; | |
28 | ||
29 | static char line[1024]; | |
30 | ||
31 | static int CDBISDN_readhwdb; | |
32 | ||
33 | static int | |
34 | init_cdbisdn(void) | |
35 | { | |
36 | FILE *cdb; | |
37 | char *s, *p = NULL; | |
38 | int rectyp, l, cnt = 0, icnt = 0; | |
39 | ||
40 | cdb = fopen(CDBISDN_HWDB_FILE, "rb"); | |
41 | if (!cdb) { | |
42 | debprintf("open failure %s\n", CDBISDN_HWDB_FILE); | |
43 | goto fallback; | |
44 | } | |
45 | while (!feof(cdb)) { | |
46 | s = fgets(line, 1024, cdb); | |
47 | if (!s) | |
48 | break; | |
49 | if (!s[0] || s[0] == '!' || s[0] == '#' || s[0] == '\n') | |
50 | continue; | |
51 | if (s[0] != '$') { | |
52 | debprintf("got wrong line %s\n", s); | |
53 | continue; | |
54 | } | |
55 | sscanf(s, "$%d", &rectyp); | |
56 | switch(rectyp) { | |
57 | case IWHREC_TYPE_VERSION: | |
58 | sscanf(s + 4, "%d", &cdb_dbversion); | |
59 | break; | |
60 | case IWHREC_TYPE_DATE: | |
61 | l = strlen(s + 4); | |
62 | if (!l) | |
63 | continue; | |
64 | l--; | |
65 | if (l > 31) | |
66 | l = 31; | |
67 | strncpy(cdb_date, s + 4, l); | |
68 | cdb_date[l] = 0; | |
69 | break; | |
70 | case IWHREC_TYPE_NAME_SIZE: | |
71 | sscanf(s + 4, "%d", &CDBISDN_name_size); | |
72 | CDBISDN_names = calloc(CDBISDN_name_size + 1, 1); | |
73 | if (!CDBISDN_names) { | |
74 | debprintf("fail to allocate %d bytes for CDBISDN_names\n", CDBISDN_name_size); | |
75 | goto fallback_close; | |
76 | } | |
77 | p = CDBISDN_names; | |
78 | cnt = 0; | |
79 | icnt = 0; | |
80 | break; | |
81 | case IWHREC_TYPE_NAME_DATA: | |
82 | if (!p) | |
83 | goto fallback_close; | |
84 | l = strlen(s + 4); | |
85 | icnt += l; | |
86 | if (icnt > CDBISDN_name_size) { | |
87 | debprintf("name_size overflow %d/%d\n", icnt, CDBISDN_name_size); | |
88 | goto fallback_close; | |
89 | } | |
90 | strcpy(p, s + 4); | |
91 | p[l-1] = 0; | |
92 | p += l; | |
93 | cnt++; | |
94 | break; | |
95 | case IWHREC_TYPE_NAME_COUNT: | |
96 | sscanf(s + 4, "%d", &l); | |
97 | if (cnt != l) | |
98 | goto fallback_close; | |
99 | break; | |
100 | case IWHREC_TYPE_VENDOR_COUNT: | |
101 | sscanf(s + 4, "%d", &CDBISDN_vendor_cnt); | |
102 | cdb_isdnvendor_info = calloc(CDBISDN_vendor_cnt, sizeof(cdb_isdn_vendor)); | |
103 | if (!cdb_isdnvendor_info) { | |
104 | debprintf("fail to allocate %d vendor structs\n", CDBISDN_vendor_cnt); | |
105 | goto fallback_close; | |
106 | } | |
107 | cnt = 0; | |
108 | break; | |
109 | case IWHREC_TYPE_VENDOR_RECORD: | |
110 | if (cnt >= CDBISDN_vendor_cnt) { | |
111 | debprintf("vendor overflow %d/%d\n", cnt, CDBISDN_vendor_cnt); | |
112 | goto fallback_close; | |
113 | } | |
114 | l = sscanf(s + 4, "%p %p %d %d", | |
115 | &cdb_isdnvendor_info[cnt].name, | |
116 | &cdb_isdnvendor_info[cnt].shortname, | |
117 | &cdb_isdnvendor_info[cnt].vnr, | |
118 | &cdb_isdnvendor_info[cnt].refcnt); | |
119 | if (l != 4) { | |
120 | debprintf("error reading vendor record %s\n", s); | |
121 | goto fallback_close; | |
122 | } | |
123 | cdb_isdnvendor_info[cnt].name = CDBISDN_names + (u_long)cdb_isdnvendor_info[cnt].name; | |
124 | cdb_isdnvendor_info[cnt].shortname = CDBISDN_names + (u_long)cdb_isdnvendor_info[cnt].shortname; | |
125 | cnt++; | |
126 | break; | |
127 | case IWHREC_TYPE_CARD_COUNT: | |
128 | sscanf(s + 4, "%d", &CDBISDN_card_cnt); | |
129 | cdb_isdncard_info = calloc(CDBISDN_card_cnt + 1, sizeof(cdb_isdn_card)); | |
130 | cdb_isdncard_idsorted = calloc(CDBISDN_card_cnt, sizeof(int)); | |
131 | if (!cdb_isdncard_info || !cdb_isdncard_idsorted) { | |
132 | debprintf("fail to allocate %d vendor structs\n", CDBISDN_card_cnt); | |
133 | goto fallback_close; | |
134 | } | |
135 | cnt = 0; | |
136 | icnt = 0; | |
137 | break; | |
138 | case IWHREC_TYPE_CARD_RECORD: | |
139 | if (cnt > CDBISDN_card_cnt) { | |
140 | debprintf("card overflow %d/%d\n", cnt, CDBISDN_card_cnt); | |
141 | goto fallback_close; | |
142 | } | |
143 | l = sscanf(s + 4, "%d %d %p %p %p %p %d %d %d %d %d %d %d %d %d", | |
144 | &cdb_isdncard_info[cnt].handle, /* internal identifier idx in database */ | |
145 | &cdb_isdncard_info[cnt].vhandle, /* internal identifier to vendor database */ | |
146 | &cdb_isdncard_info[cnt].name, /* cardname */ | |
147 | &cdb_isdncard_info[cnt].lname, /* vendor short name + cardname */ | |
148 | &cdb_isdncard_info[cnt].Class, /* CLASS of the card */ | |
149 | &cdb_isdncard_info[cnt].bus, /* bus type */ | |
150 | &cdb_isdncard_info[cnt].revision, /* revision used with USB */ | |
151 | &cdb_isdncard_info[cnt].vendor, /* Vendor ID for ISAPNP and PCI cards */ | |
152 | &cdb_isdncard_info[cnt].device, /* Device ID for ISAPNP and PCI cards */ | |
153 | &cdb_isdncard_info[cnt].subvendor, /* Subvendor ID for PCI cards */ | |
154 | &cdb_isdncard_info[cnt].subdevice, /* Subdevice ID for PCI cards */ | |
155 | &cdb_isdncard_info[cnt].features, /* feature flags */ | |
156 | &cdb_isdncard_info[cnt].line_cnt, /* count of ISDN ports */ | |
157 | &cdb_isdncard_info[cnt].vario_cnt, /* count of driver varios */ | |
158 | &cdb_isdncard_info[cnt].vario); /* referenz to driver vario record */ | |
159 | if (l != 15) { | |
160 | debprintf("error reading card record %s\n", s); | |
161 | goto fallback_close; | |
162 | } | |
163 | cdb_isdncard_info[cnt].name = CDBISDN_names + (u_long)cdb_isdncard_info[cnt].name; | |
164 | cdb_isdncard_info[cnt].lname = CDBISDN_names + (u_long)cdb_isdncard_info[cnt].lname; | |
165 | cdb_isdncard_info[cnt].Class = CDBISDN_names + (u_long)cdb_isdncard_info[cnt].Class; | |
166 | cdb_isdncard_info[cnt].bus = CDBISDN_names + (u_long)cdb_isdncard_info[cnt].bus; | |
167 | cnt++; | |
168 | break; | |
169 | case IWHREC_TYPE_CARD_IDSORTED: | |
170 | if (icnt >= CDBISDN_card_cnt) { | |
171 | debprintf("card overflow %d/%d\n", icnt, CDBISDN_card_cnt); | |
172 | goto fallback_close; | |
173 | } | |
174 | sscanf(s + 4, "%d", &cdb_isdncard_idsorted[icnt]); | |
175 | icnt++; | |
176 | break; | |
177 | case IWHREC_TYPE_VARIO_COUNT: | |
178 | sscanf(s + 4, "%d", &CDBISDN_vario_cnt); | |
179 | cdb_isdnvario_info = calloc(CDBISDN_vario_cnt+1, sizeof(cdb_isdn_vario)); | |
180 | if (!cdb_isdnvario_info) { | |
181 | debprintf("fail to allocate %d vario structs\n", CDBISDN_vario_cnt); | |
182 | goto fallback_close; | |
183 | } | |
184 | cnt = 0; | |
185 | break; | |
186 | case IWHREC_TYPE_VARIO_RECORD: | |
187 | if (cnt > CDBISDN_vario_cnt) { | |
188 | debprintf("vario overflow %d/%d\n", cnt, CDBISDN_vario_cnt); | |
189 | goto fallback_close; | |
190 | } | |
191 | l = sscanf(s + 4, "%d %d %d %d %d %d %p %p %p %p %p %p %p %p %p %p %p %p %p %p %d %p", | |
192 | &cdb_isdnvario_info[cnt].handle, /* idx in database */ | |
193 | &cdb_isdnvario_info[cnt].next_vario, /* link to alternate vario */ | |
194 | &cdb_isdnvario_info[cnt].drvid, /* unique id of the driver vario */ | |
195 | &cdb_isdnvario_info[cnt].typ, /* Type to identify the driver */ | |
196 | &cdb_isdnvario_info[cnt].subtyp, /* Subtype of the driver type */ | |
197 | &cdb_isdnvario_info[cnt].smp, /* SMP supported ? */ | |
198 | &cdb_isdnvario_info[cnt].mod_name, /* name of the driver module */ | |
199 | &cdb_isdnvario_info[cnt].para_str, /* optional parameter string */ | |
200 | &cdb_isdnvario_info[cnt].mod_preload, /* optional modules to preload */ | |
201 | &cdb_isdnvario_info[cnt].cfg_prog, /* optional cfg prog */ | |
202 | &cdb_isdnvario_info[cnt].firmware, /* optional firmware to load */ | |
203 | &cdb_isdnvario_info[cnt].description, /* optional description */ | |
204 | &cdb_isdnvario_info[cnt].need_pkg, /* list of packages needed for function */ | |
205 | &cdb_isdnvario_info[cnt].info, /* optional additional info */ | |
206 | &cdb_isdnvario_info[cnt].protocol, /* supported D-channel protocols */ | |
207 | &cdb_isdnvario_info[cnt].interface, /* supported API interfaces */ | |
208 | &cdb_isdnvario_info[cnt].io, /* possible IO ports with legacy ISA cards */ | |
209 | &cdb_isdnvario_info[cnt].irq, /* possible interrupts with legacy ISA cards */ | |
210 | &cdb_isdnvario_info[cnt].membase, /* possible membase with legacy ISA cards */ | |
211 | &cdb_isdnvario_info[cnt].features, /* optional features*/ | |
212 | &cdb_isdnvario_info[cnt].card_ref, /* reference to a card */ | |
213 | &cdb_isdnvario_info[cnt].name); /* driver name */ | |
214 | if (l != 22) { | |
215 | debprintf("error reading vario record %s\n", s); | |
216 | goto fallback_close; | |
217 | } | |
218 | cdb_isdnvario_info[cnt].mod_name = CDBISDN_names + (u_long)cdb_isdnvario_info[cnt].mod_name; | |
219 | cdb_isdnvario_info[cnt].para_str = CDBISDN_names + (u_long)cdb_isdnvario_info[cnt].para_str; | |
220 | cdb_isdnvario_info[cnt].mod_preload = CDBISDN_names + (u_long)cdb_isdnvario_info[cnt].mod_preload; | |
221 | cdb_isdnvario_info[cnt].cfg_prog = CDBISDN_names + (u_long)cdb_isdnvario_info[cnt].cfg_prog; | |
222 | cdb_isdnvario_info[cnt].firmware = CDBISDN_names + (u_long)cdb_isdnvario_info[cnt].firmware; | |
223 | cdb_isdnvario_info[cnt].description = CDBISDN_names + (u_long)cdb_isdnvario_info[cnt].description; | |
224 | cdb_isdnvario_info[cnt].need_pkg = CDBISDN_names + (u_long)cdb_isdnvario_info[cnt].need_pkg; | |
225 | cdb_isdnvario_info[cnt].info = CDBISDN_names + (u_long)cdb_isdnvario_info[cnt].info; | |
226 | cdb_isdnvario_info[cnt].protocol = CDBISDN_names + (u_long)cdb_isdnvario_info[cnt].protocol; | |
227 | cdb_isdnvario_info[cnt].interface = CDBISDN_names + (u_long)cdb_isdnvario_info[cnt].interface; | |
228 | cdb_isdnvario_info[cnt].io = CDBISDN_names + (u_long)cdb_isdnvario_info[cnt].io; | |
229 | cdb_isdnvario_info[cnt].irq = CDBISDN_names + (u_long)cdb_isdnvario_info[cnt].irq; | |
230 | cdb_isdnvario_info[cnt].membase = CDBISDN_names + (u_long)cdb_isdnvario_info[cnt].membase; | |
231 | cdb_isdnvario_info[cnt].features = CDBISDN_names + (u_long)cdb_isdnvario_info[cnt].features; | |
232 | cdb_isdnvario_info[cnt].name = CDBISDN_names + (u_long)cdb_isdnvario_info[cnt].name; | |
233 | cnt++; | |
234 | break; | |
235 | default: | |
236 | debprintf("got wrong RecType %d\n", rectyp); | |
237 | break; | |
238 | } | |
239 | } | |
240 | fclose(cdb); | |
241 | if (CDBISDN_name_size == 0 || | |
242 | CDBISDN_vendor_cnt == 0 || | |
243 | CDBISDN_card_cnt == 0 || | |
244 | CDBISDN_vario_cnt == 0) | |
245 | goto fallback; | |
246 | debprintf("successfull reading %s\n", CDBISDN_HWDB_FILE); | |
247 | CDBISDN_readhwdb = 1; | |
248 | return(0); | |
249 | fallback_close: | |
250 | fclose(cdb); | |
251 | fallback: | |
252 | debprintf("error reading %s\n", CDBISDN_HWDB_FILE); | |
253 | CDBISDN_vendor_cnt = (sizeof(cdb_isdnvendor_info_init) / sizeof(cdb_isdn_vendor)); | |
254 | CDBISDN_card_cnt = ((sizeof(cdb_isdncard_info_init) / sizeof(cdb_isdn_card)) -1); | |
255 | CDBISDN_vario_cnt = ((sizeof(cdb_isdnvario_info_init) / sizeof(cdb_isdn_vario))-1); | |
256 | cdb_isdnvendor_info = cdb_isdnvendor_info_init; | |
257 | cdb_isdncard_info = cdb_isdncard_info_init; | |
258 | cdb_isdncard_idsorted = cdb_isdncard_idsorted_init; | |
259 | cdb_isdnvario_info = cdb_isdnvario_info_init; | |
260 | cdb_dbversion = CDBISDN_DBVERSION; | |
261 | strncpy(cdb_date, CDBISDN_DATE, 31); | |
262 | CDBISDN_readhwdb = 1; | |
263 | return(1); | |
264 | } | |
265 | ||
266 | typedef int (*fcmp) (const void *, const void *); | |
267 | ||
268 | static int compare_type(cdb_isdn_vario *v1, cdb_isdn_vario *v2) { | |
269 | int x= v1->typ - v2->typ; | |
270 | ||
271 | if (!x) | |
272 | x=v1->subtyp - v2->subtyp; | |
273 | return(x); | |
274 | } | |
275 | ||
276 | static int compare_id(const int *c1, const int *c2) { | |
277 | int x= cdb_isdncard_info[*c1].vendor - cdb_isdncard_info[*c2].vendor; | |
278 | ||
279 | if (!x) | |
280 | x=cdb_isdncard_info[*c1].device - cdb_isdncard_info[*c2].device; | |
281 | if (!x) | |
282 | x=cdb_isdncard_info[*c1].subvendor - cdb_isdncard_info[*c2].subvendor; | |
283 | if (!x) | |
284 | x=cdb_isdncard_info[*c1].subdevice - cdb_isdncard_info[*c2].subdevice; | |
285 | return(x); | |
286 | } | |
287 | ||
288 | /* interface */ | |
289 | ||
290 | cdb_isdn_vendor *hd_cdbisdn_get_vendor(int handle) | |
291 | { | |
292 | if (!CDBISDN_readhwdb) | |
293 | init_cdbisdn(); | |
294 | if (handle<0) | |
295 | return(NULL); | |
296 | if ((unsigned)handle >= CDBISDN_vendor_cnt) | |
297 | return(NULL); | |
298 | return(&cdb_isdnvendor_info[handle]); | |
299 | } | |
300 | ||
301 | cdb_isdn_card *hd_cdbisdn_get_card(int handle) | |
302 | { | |
303 | if (!CDBISDN_readhwdb) | |
304 | init_cdbisdn(); | |
305 | if (handle<=0) | |
306 | return(NULL); | |
307 | if ((unsigned) handle>CDBISDN_card_cnt) | |
308 | return(NULL); | |
309 | return(&cdb_isdncard_info[handle]); | |
310 | } | |
311 | ||
312 | cdb_isdn_vario *hd_cdbisdn_get_vario_from_type(int typ, int subtyp) | |
313 | { | |
314 | cdb_isdn_vario key, *ret; | |
315 | ||
316 | if (!CDBISDN_readhwdb) | |
317 | CDBISDN_readhwdb = init_cdbisdn(); | |
318 | key.typ = typ; | |
319 | key.subtyp = subtyp; | |
320 | if (!(ret=bsearch(&key, &cdb_isdnvario_info[1], CDBISDN_vario_cnt, sizeof(cdb_isdn_vario), (fcmp)compare_type))) { | |
321 | debprintf("ret NULL\n"); | |
322 | return(NULL); | |
323 | } | |
324 | return(ret); | |
325 | } | |
326 | ||
327 | cdb_isdn_card *hd_cdbisdn_get_card_from_type(int typ, int subtyp) | |
328 | { | |
329 | cdb_isdn_vario *civ; | |
330 | ||
331 | if (!CDBISDN_readhwdb) | |
332 | init_cdbisdn(); | |
333 | civ = hd_cdbisdn_get_vario_from_type(typ, subtyp); | |
334 | if (civ) { | |
335 | if (civ->card_ref > 0) | |
336 | return(&cdb_isdncard_info[civ->card_ref]); | |
337 | } | |
338 | return(NULL); | |
339 | } | |
340 | ||
341 | cdb_isdn_card *hd_cdbisdn_get_card_from_id(int vendor, int device, int subvendor, int subdevice) | |
342 | { | |
343 | int key, *ret; | |
344 | ||
345 | if (!CDBISDN_readhwdb) | |
346 | init_cdbisdn(); | |
347 | key = 0; | |
348 | cdb_isdncard_info[key].vendor = vendor; | |
349 | cdb_isdncard_info[key].device = device; | |
350 | cdb_isdncard_info[key].subvendor = subvendor; | |
351 | cdb_isdncard_info[key].subdevice = subdevice; | |
352 | if (!(ret=bsearch(&key, cdb_isdncard_idsorted, CDBISDN_card_cnt, sizeof(int), (fcmp)compare_id))) { | |
353 | debprintf("bs1 ret NULL\n"); | |
354 | key = 0; | |
355 | cdb_isdncard_info[key].subvendor = PCI_ANY_ID; | |
356 | cdb_isdncard_info[key].subdevice = PCI_ANY_ID; | |
357 | if (!(ret=bsearch(&key, cdb_isdncard_idsorted, CDBISDN_card_cnt, sizeof(int), (fcmp)compare_id))) { | |
358 | debprintf("bs2 ret NULL\n"); | |
359 | return(NULL); | |
360 | } | |
361 | } | |
362 | debprintf("ret idx %d\n", *ret); | |
363 | if (*ret <= 0) | |
364 | return(NULL); | |
365 | if ((unsigned) *ret > CDBISDN_card_cnt) | |
366 | return(NULL); | |
367 | return(&cdb_isdncard_info[*ret]); | |
368 | } | |
369 | ||
370 | cdb_isdn_vario *hd_cdbisdn_get_vario(int handle) | |
371 | { | |
372 | if (!CDBISDN_readhwdb) | |
373 | init_cdbisdn(); | |
374 | if (handle<=0) | |
375 | return(NULL); | |
376 | if ((unsigned) handle > CDBISDN_vario_cnt) | |
377 | return(NULL); | |
378 | return(&cdb_isdnvario_info[handle]); | |
379 | } | |
380 | ||
381 | int hd_cdbisdn_get_version(void) | |
382 | { | |
383 | if (!CDBISDN_readhwdb) | |
384 | init_cdbisdn(); | |
385 | return(CDBISDN_VERSION); | |
386 | } | |
387 | ||
388 | int hd_cdbisdn_get_db_version(void) | |
389 | { | |
390 | if (!CDBISDN_readhwdb) | |
391 | init_cdbisdn(); | |
392 | return(cdb_dbversion); | |
393 | } | |
394 | ||
395 | char *hd_cdbisdn_get_db_date(void) | |
396 | { | |
397 | if (!CDBISDN_readhwdb) | |
398 | init_cdbisdn(); | |
399 | return(cdb_date); | |
400 | } |