upload tizen2.0 source
[framework/system/usbutils.git] / names.c
1 /*****************************************************************************/
2 /*
3  *      names.c  --  USB name database manipulation routines
4  *
5  *      Copyright (C) 1999, 2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
6  *
7  *      This program is free software; you can redistribute it and/or modify
8  *      it under the terms of the GNU General Public License as published by
9  *      the Free Software Foundation; either version 2 of the License, or
10  *      (at your option) any later version.
11  *
12  *      This program is distributed in the hope that it will be useful,
13  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *      GNU General Public License for more details.
16  *
17  *      You should have received a copy of the GNU General Public License
18  *      along with this program; if not, write to the Free Software
19  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  *
22  */
23
24 /*****************************************************************************/
25
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <dirent.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <stdio.h>
35 #include <ctype.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40
41 #ifdef HAVE_LIBZ
42 #include <zlib.h>
43 #define         usb_file                                gzFile
44 #define         usb_fopen(path, mode)           gzopen(path, mode)
45 #define         usb_fgets(s, size, stream)      gzgets(stream, s, size)
46 #define         usb_close(f)                    gzclose(f)
47 #else
48 #define         usb_file                                FILE*
49 #define         usb_fopen(path, mode)           fopen(path, mode)
50 #define         usb_fgets(s, size, stream)      fgets(s, size, stream)
51 #define         usb_close(f)                    fclose(f)
52 #endif
53
54 #include "names.h"
55
56
57 /* ---------------------------------------------------------------------- */
58
59 struct vendor {
60         struct vendor *next;
61         u_int16_t vendorid;
62         char name[1];
63 };
64
65 struct product {
66         struct product *next;
67         u_int16_t vendorid, productid;
68         char name[1];
69 };
70
71 struct class {
72         struct class *next;
73         u_int8_t classid;
74         char name[1];
75 };
76
77 struct subclass {
78         struct subclass *next;
79         u_int8_t classid, subclassid;
80         char name[1];
81 };
82
83 struct protocol {
84         struct protocol *next;
85         u_int8_t classid, subclassid, protocolid;
86         char name[1];
87 };
88
89 struct audioterminal {
90         struct audioterminal *next;
91         u_int16_t termt;
92         char name[1];
93 };
94
95 struct videoterminal {
96         struct videoterminal *next;
97         u_int16_t termt;
98         char name[1];
99 };
100
101 struct genericstrtable {
102         struct genericstrtable *next;
103         unsigned int num;
104         char name[1];
105 };
106
107 /* ---------------------------------------------------------------------- */
108
109 #define HASH1  0x10
110 #define HASH2  0x02
111 #define HASHSZ 16
112
113 static unsigned int hashnum(unsigned int num)
114 {
115         unsigned int mask1 = HASH1 << 27, mask2 = HASH2 << 27;
116
117         for (; mask1 >= HASH1; mask1 >>= 1, mask2 >>= 1)
118                 if (num & mask1)
119                         num ^= mask2;
120         return num & (HASHSZ-1);
121 }
122
123 /* ---------------------------------------------------------------------- */
124
125 static struct vendor *vendors[HASHSZ] = { NULL, };
126 static struct product *products[HASHSZ] = { NULL, };
127 static struct class *classes[HASHSZ] = { NULL, };
128 static struct subclass *subclasses[HASHSZ] = { NULL, };
129 static struct protocol *protocols[HASHSZ] = { NULL, };
130 static struct audioterminal *audioterminals[HASHSZ] = { NULL, };
131 static struct videoterminal *videoterminals[HASHSZ] = { NULL, };
132 static struct genericstrtable *hiddescriptors[HASHSZ] = { NULL, };
133 static struct genericstrtable *reports[HASHSZ] = { NULL, };
134 static struct genericstrtable *huts[HASHSZ] = { NULL, };
135 static struct genericstrtable *biass[HASHSZ] = { NULL, };
136 static struct genericstrtable *physdess[HASHSZ] = { NULL, };
137 static struct genericstrtable *hutus[HASHSZ] = { NULL, };
138 static struct genericstrtable *langids[HASHSZ] = { NULL, };
139 static struct genericstrtable *countrycodes[HASHSZ] = { NULL, };
140
141 /* ---------------------------------------------------------------------- */
142
143 static const char *names_genericstrtable(struct genericstrtable *t[HASHSZ], unsigned int index)
144 {
145         struct genericstrtable *h;
146
147         for (h = t[hashnum(index)]; h; h = h->next)
148                 if (h->num == index)
149                         return h->name;
150         return NULL;
151 }
152
153 const char *names_hid(u_int8_t hidd)
154 {
155         return names_genericstrtable(hiddescriptors, hidd);
156 }
157
158 const char *names_reporttag(u_int8_t rt)
159 {
160         return names_genericstrtable(reports, rt);
161 }
162
163 const char *names_huts(unsigned int data)
164 {
165         return names_genericstrtable(huts, data);
166 }
167
168 const char *names_hutus(unsigned int data)
169 {
170         return names_genericstrtable(hutus, data);
171 }
172
173 const char *names_langid(u_int16_t langid)
174 {
175         return names_genericstrtable(langids, langid);
176 }
177
178 const char *names_physdes(u_int8_t ph)
179 {
180         return names_genericstrtable(physdess, ph);
181 }
182
183 const char *names_bias(u_int8_t b)
184 {
185         return names_genericstrtable(biass, b);
186 }
187
188 const char *names_countrycode(unsigned int countrycode)
189 {
190         return names_genericstrtable(countrycodes, countrycode);
191 }
192
193 const char *names_vendor(u_int16_t vendorid)
194 {
195         struct vendor *v;
196
197         v = vendors[hashnum(vendorid)];
198         for (; v; v = v->next)
199                 if (v->vendorid == vendorid)
200                         return v->name;
201         return NULL;
202 }
203
204 const char *names_product(u_int16_t vendorid, u_int16_t productid)
205 {
206         struct product *p;
207
208         p = products[hashnum((vendorid << 16) | productid)];
209         for (; p; p = p->next)
210                 if (p->vendorid == vendorid && p->productid == productid)
211                         return p->name;
212         return NULL;
213 }
214
215 const char *names_class(u_int8_t classid)
216 {
217         struct class *c;
218
219         c = classes[hashnum(classid)];
220         for (; c; c = c->next)
221                 if (c->classid == classid)
222                         return c->name;
223         return NULL;
224 }
225
226 const char *names_subclass(u_int8_t classid, u_int8_t subclassid)
227 {
228         struct subclass *s;
229
230         s = subclasses[hashnum((classid << 8) | subclassid)];
231         for (; s; s = s->next)
232                 if (s->classid == classid && s->subclassid == subclassid)
233                         return s->name;
234         return NULL;
235 }
236
237 const char *names_protocol(u_int8_t classid, u_int8_t subclassid, u_int8_t protocolid)
238 {
239         struct protocol *p;
240
241         p = protocols[hashnum((classid << 16) | (subclassid << 8) | protocolid)];
242         for (; p; p = p->next)
243                 if (p->classid == classid && p->subclassid == subclassid && p->protocolid == protocolid)
244                         return p->name;
245         return NULL;
246 }
247
248 const char *names_audioterminal(u_int16_t termt)
249 {
250         struct audioterminal *at;
251
252         at = audioterminals[hashnum(termt)];
253         for (; at; at = at->next)
254                 if (at->termt == termt)
255                         return at->name;
256         return NULL;
257 }
258
259 const char *names_videoterminal(u_int16_t termt)
260 {
261         struct videoterminal *vt;
262
263         vt = videoterminals[hashnum(termt)];
264         for (; vt; vt = vt->next)
265                 if (vt->termt == termt)
266                         return vt->name;
267         return NULL;
268 }
269
270 /* ---------------------------------------------------------------------- */
271
272 static int new_vendor(const char *name, u_int16_t vendorid)
273 {
274         struct vendor *v;
275         unsigned int h = hashnum(vendorid);
276
277         v = vendors[h];
278         for (; v; v = v->next)
279                 if (v->vendorid == vendorid)
280                         return -1;
281         v = malloc(sizeof(struct vendor) + strlen(name));
282         if (!v)
283                 return -1;
284         strcpy(v->name, name);
285         v->vendorid = vendorid;
286         v->next = vendors[h];
287         vendors[h] = v;
288         return 0;
289 }
290
291 static int new_product(const char *name, u_int16_t vendorid, u_int16_t productid)
292 {
293         struct product *p;
294         unsigned int h = hashnum((vendorid << 16) | productid);
295
296         p = products[h];
297         for (; p; p = p->next)
298                 if (p->vendorid == vendorid && p->productid == productid)
299                         return -1;
300         p = malloc(sizeof(struct product) + strlen(name));
301         if (!p)
302                 return -1;
303         strcpy(p->name, name);
304         p->vendorid = vendorid;
305         p->productid = productid;
306         p->next = products[h];
307         products[h] = p;
308         return 0;
309 }
310
311 static int new_class(const char *name, u_int8_t classid)
312 {
313         struct class *c;
314         unsigned int h = hashnum(classid);
315
316         c = classes[h];
317         for (; c; c = c->next)
318                 if (c->classid == classid)
319                         return -1;
320         c = malloc(sizeof(struct class) + strlen(name));
321         if (!c)
322                 return -1;
323         strcpy(c->name, name);
324         c->classid = classid;
325         c->next = classes[h];
326         classes[h] = c;
327         return 0;
328 }
329
330 static int new_subclass(const char *name, u_int8_t classid, u_int8_t subclassid)
331 {
332         struct subclass *s;
333         unsigned int h = hashnum((classid << 8) | subclassid);
334
335         s = subclasses[h];
336         for (; s; s = s->next)
337                 if (s->classid == classid && s->subclassid == subclassid)
338                         return -1;
339         s = malloc(sizeof(struct subclass) + strlen(name));
340         if (!s)
341                 return -1;
342         strcpy(s->name, name);
343         s->classid = classid;
344         s->subclassid = subclassid;
345         s->next = subclasses[h];
346         subclasses[h] = s;
347         return 0;
348 }
349
350 static int new_protocol(const char *name, u_int8_t classid, u_int8_t subclassid, u_int8_t protocolid)
351 {
352         struct protocol *p;
353         unsigned int h = hashnum((classid << 16) | (subclassid << 8) | protocolid);
354
355         p = protocols[h];
356         for (; p; p = p->next)
357                 if (p->classid == classid && p->subclassid == subclassid && p->protocolid == protocolid)
358                         return -1;
359         p = malloc(sizeof(struct protocol) + strlen(name));
360         if (!p)
361                 return -1;
362         strcpy(p->name, name);
363         p->classid = classid;
364         p->subclassid = subclassid;
365         p->protocolid = protocolid;
366         p->next = protocols[h];
367         protocols[h] = p;
368         return 0;
369 }
370
371 static int new_audioterminal(const char *name, u_int16_t termt)
372 {
373         struct audioterminal *at;
374         unsigned int h = hashnum(termt);
375
376         at = audioterminals[h];
377         for (; at; at = at->next)
378                 if (at->termt == termt)
379                         return -1;
380         at = malloc(sizeof(struct audioterminal) + strlen(name));
381         if (!at)
382                 return -1;
383         strcpy(at->name, name);
384         at->termt = termt;
385         at->next = audioterminals[h];
386         audioterminals[h] = at;
387         return 0;
388 }
389
390 static int new_videoterminal(const char *name, u_int16_t termt)
391 {
392         struct videoterminal *vt;
393         unsigned int h = hashnum(termt);
394
395         vt = videoterminals[h];
396         for (; vt; vt = vt->next)
397                 if (vt->termt == termt)
398                         return -1;
399         vt = malloc(sizeof(struct videoterminal) + strlen(name));
400         if (!vt)
401                 return -1;
402         strcpy(vt->name, name);
403         vt->termt = termt;
404         vt->next = videoterminals[h];
405         videoterminals[h] = vt;
406         return 0;
407 }
408
409 static int new_genericstrtable(struct genericstrtable *t[HASHSZ], const char *name, unsigned int index)
410 {
411         struct genericstrtable *g;
412         unsigned int h = hashnum(index);
413         
414         for (g = t[h]; g; g = g->next)
415                 if (g->num == index)
416                         return -1;
417         g = malloc(sizeof(struct genericstrtable) + strlen(name));
418         if (!g)
419                 return -1;
420         strcpy(g->name, name);
421         g->num = index;
422         g->next = t[h];
423         t[h] = g;
424         return 0;
425 }
426
427 static int new_hid(const char *name, u_int8_t hidd)
428 {
429         return new_genericstrtable(hiddescriptors, name, hidd);
430 }
431
432 static int new_reporttag(const char *name, u_int8_t rt)
433 {
434         return new_genericstrtable(reports, name, rt);
435 }
436
437 static int new_huts(const char *name, unsigned int data)
438 {
439         return new_genericstrtable(huts, name, data);
440 }
441
442 static int new_hutus(const char *name, unsigned int data)
443 {
444         return new_genericstrtable(hutus, name, data);
445 }
446
447 static int new_langid(const char *name, u_int16_t langid)
448 {
449         return new_genericstrtable(langids, name, langid);
450 }
451
452 static int new_physdes(const char *name, u_int8_t ph)
453 {
454         return new_genericstrtable(physdess, name, ph);
455 }
456 static int new_bias(const char *name, u_int8_t b)
457 {
458         return new_genericstrtable(biass, name, b);
459 }
460
461 static int new_countrycode(const char *name, unsigned int countrycode)
462 {
463         return new_genericstrtable(countrycodes, name, countrycode);
464 }
465
466 /* ---------------------------------------------------------------------- */
467
468 #define DBG(x) 
469
470 static void parse(usb_file f)
471 {
472         char buf[512], *cp;
473         unsigned int linectr = 0;
474         int lastvendor = -1, lastclass = -1, lastsubclass = -1, lasthut=-1, lastlang=-1;
475         unsigned int u;
476
477         while (usb_fgets(buf, sizeof(buf), f)) {
478                 linectr++;
479                 /* remove line ends */
480                 if ((cp = strchr(buf, 13)))
481                         *cp = 0;
482                 if ((cp = strchr(buf, 10)))
483                         *cp = 0;
484                 if (buf[0] == '#' || !buf[0])
485                         continue;
486                 cp = buf;
487                 if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' && buf[3] == 'S' && buf[4] == 'D' &&
488                     buf[5] == 'E' && buf[6] == 'S' && /*isspace(buf[7])*/ buf[7] == ' ') {
489                         cp = buf + 8;
490                         while (isspace(*cp))
491                                 cp++;
492                         if (!isxdigit(*cp)) {
493                                 fprintf(stderr, "Invalid Physdes type at line %u\n", linectr);
494                                 continue;
495                         }
496                         u = strtoul(cp, &cp, 16);
497                         while (isspace(*cp))
498                                 cp++;
499                         if (!*cp) {
500                                 fprintf(stderr, "Invalid Physdes type at line %u\n", linectr);
501                                 continue;
502                         }
503                         if (new_physdes(cp, u))
504                                 fprintf(stderr, "Duplicate Physdes  type spec at line %u terminal type %04x %s\n", linectr, u, cp);
505                         DBG(printf("line %5u physdes type %02x %s\n", linectr, u, cp));
506                         continue;
507
508                 }
509                 if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' && /*isspace(buf[3])*/ buf[3] == ' ') {
510                         cp = buf + 4;
511                         while (isspace(*cp))
512                                 cp++;
513                         if (!isxdigit(*cp)) {
514                                 fprintf(stderr, "Invalid PHY type at line %u\n", linectr);
515                                 continue;
516                         }
517                         u = strtoul(cp, &cp, 16);
518                         while (isspace(*cp))
519                                 cp++;
520                         if (!*cp) {
521                                 fprintf(stderr, "Invalid PHY type at line %u\n", linectr);
522                                 continue;
523                         }
524                         if (new_physdes(cp, u))
525                                 fprintf(stderr, "Duplicate PHY type spec at line %u terminal type %04x %s\n", linectr, u, cp);
526                         DBG(printf("line %5u PHY type %02x %s\n", linectr, u, cp));
527                         continue;
528
529                 }
530                 if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A' && buf[3] == 'S' && /*isspace(buf[4])*/ buf[4] == ' ') {
531                         cp = buf + 5;
532                         while (isspace(*cp))
533                                 cp++;
534                         if (!isxdigit(*cp)) {
535                                 fprintf(stderr, "Invalid BIAS type at line %u\n", linectr);
536                                 continue;
537                         }
538                         u = strtoul(cp, &cp, 16);
539                         while (isspace(*cp))
540                                 cp++;
541                         if (!*cp) {
542                                 fprintf(stderr, "Invalid BIAS type at line %u\n", linectr);
543                                 continue;
544                         }
545                         if (new_bias(cp, u))
546                                 fprintf(stderr, "Duplicate BIAS  type spec at line %u terminal type %04x %s\n", linectr, u, cp);
547                         DBG(printf("line %5u BIAS type %02x %s\n", linectr, u, cp));
548                         continue;
549
550                 }
551                 if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') {
552                         cp =  buf+2;
553                         while (isspace(*cp))
554                                 cp++;
555                         if (!isxdigit(*cp)) {
556                                 fprintf(stderr, "Invalid LANGID spec at line %u\n", linectr);
557                                 continue;
558                         }
559                         u = strtoul(cp, &cp, 16);
560                         while (isspace(*cp))
561                                 cp++;
562                         if (!*cp) {
563                                 fprintf(stderr, "Invalid LANGID spec at line %u\n", linectr);
564                                 continue;
565                         }
566                         if (new_langid(cp, u))
567                                 fprintf(stderr, "Duplicate LANGID spec at line %u language-id %04x %s\n", linectr, u, cp);
568                         DBG(printf("line %5u LANGID %02x %s\n", linectr, u, cp));
569                         lasthut = lastclass = lastvendor = lastsubclass = -1;
570                         lastlang = u;
571                         continue;
572                 }
573                 if (buf[0] == 'C' && /*isspace(buf[1])*/ buf[1] == ' ') {
574                         /* class spec */
575                         cp = buf+2;
576                         while (isspace(*cp))
577                                 cp++;
578                         if (!isxdigit(*cp)) {
579                                 fprintf(stderr, "Invalid class spec at line %u\n", linectr);
580                                 continue;
581                         }
582                         u = strtoul(cp, &cp, 16);
583                         while (isspace(*cp))
584                                 cp++;
585                         if (!*cp) {
586                                 fprintf(stderr, "Invalid class spec at line %u\n", linectr);
587                                 continue;
588                         }
589                         if (new_class(cp, u))
590                                 fprintf(stderr, "Duplicate class spec at line %u class %04x %s\n", linectr, u, cp);
591                         DBG(printf("line %5u class %02x %s\n", linectr, u, cp));
592                         lasthut = lastlang = lastvendor = lastsubclass = -1;
593                         lastclass = u;
594                         continue;
595                 }
596                 if (buf[0] == 'A' && buf[1] == 'T' && isspace(buf[2])) {
597                         /* audio terminal type spec */
598                         cp = buf+3;
599                         while (isspace(*cp))
600                                 cp++;
601                         if (!isxdigit(*cp)) {
602                                 fprintf(stderr, "Invalid audio terminal type at line %u\n", linectr);
603                                 continue;
604                         }
605                         u = strtoul(cp, &cp, 16);
606                         while (isspace(*cp))
607                                 cp++;
608                         if (!*cp) {
609                                 fprintf(stderr, "Invalid audio terminal type at line %u\n", linectr);
610                                 continue;
611                         }
612                         if (new_audioterminal(cp, u))
613                                 fprintf(stderr, "Duplicate audio terminal type spec at line %u terminal type %04x %s\n", linectr, u, cp);
614                         DBG(printf("line %5u audio terminal type %02x %s\n", linectr, u, cp));
615                         continue;
616                 }
617                 if (buf[0] == 'V' && buf[1] == 'T' && isspace(buf[2])) {
618                         /* video terminal type spec */
619                         cp = buf+3;
620                         while (isspace(*cp))
621                                 cp++;
622                         if (!isxdigit(*cp)) {
623                                 fprintf(stderr, "Invalid video terminal type at line %u\n", linectr);
624                                 continue;
625                         }
626                         u = strtoul(cp, &cp, 16);
627                         while (isspace(*cp))
628                                 cp++;
629                         if (!*cp) {
630                                 fprintf(stderr, "Invalid video terminal type at line %u\n", linectr);
631                                 continue;
632                         }
633                         if (new_videoterminal(cp, u))
634                                 fprintf(stderr, "Duplicate video terminal type spec at line %u terminal type %04x %s\n", linectr, u, cp);
635                         DBG(printf("line %5u video terminal type %02x %s\n", linectr, u, cp));
636                         continue;
637                 }
638                 if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C' && isspace(buf[3])) {
639                         /* HID Descriptor bCountryCode */
640                         cp =  buf+3;
641                         while (isspace(*cp))
642                                 cp++;
643                         if (!isxdigit(*cp)) {
644                                 fprintf(stderr, "Invalid HID country code at line %u\n", linectr);
645                                 continue;
646                         }
647                         u = strtoul(cp, &cp, 10);
648                         while (isspace(*cp))
649                                 cp++;
650                         if (!*cp) {
651                                 fprintf(stderr, "Invalid HID country code at line %u\n", linectr);
652                                 continue;
653                         }
654                         if (new_countrycode(cp, u))
655                                 fprintf(stderr, "Duplicate HID country code at line %u country %02u %s\n", linectr, u, cp);
656                         DBG(printf("line %5u keyboard country code %02u %s\n", linectr, u, cp));
657                         continue;
658                 }
659                 if (isxdigit(*cp)) {
660                         /* vendor */
661                         u = strtoul(cp, &cp, 16);
662                         while (isspace(*cp))
663                                 cp++;
664                         if (!*cp) {
665                                 fprintf(stderr, "Invalid vendor spec at line %u\n", linectr);
666                                 continue;
667                         }
668                         if (new_vendor(cp, u))
669                                 fprintf(stderr, "Duplicate vendor spec at line %u vendor %04x %s\n", linectr, u, cp);
670                         DBG(printf("line %5u vendor %04x %s\n", linectr, u, cp));
671                         lastvendor = u;
672                         lasthut = lastlang = lastclass = lastsubclass = -1;
673                         continue;
674                 }
675                 if (buf[0] == '\t' && isxdigit(buf[1])) {
676                         /* product or subclass spec */
677                         u = strtoul(buf+1, &cp, 16);
678                         while (isspace(*cp))
679                                 cp++;
680                         if (!*cp) {
681                                 fprintf(stderr, "Invalid product/subclass spec at line %u\n", linectr);
682                                 continue;
683                         }
684                         if (lastvendor != -1) {
685                                 if (new_product(cp, lastvendor, u))
686                                         fprintf(stderr, "Duplicate product spec at line %u product %04x:%04x %s\n", linectr, lastvendor, u, cp);
687                                 DBG(printf("line %5u product %04x:%04x %s\n", linectr, lastvendor, u, cp));
688                                 continue;
689                         }
690                         if (lastclass != -1) {
691                                 if (new_subclass(cp, lastclass, u))
692                                         fprintf(stderr, "Duplicate subclass spec at line %u class %02x:%02x %s\n", linectr, lastclass, u, cp);
693                                 DBG(printf("line %5u subclass %02x:%02x %s\n", linectr, lastclass, u, cp));
694                                 lastsubclass = u;
695                                 continue;
696                         }
697                         if (lasthut != -1) {
698                                 if (new_hutus(cp, (lasthut << 16)+u))
699                                         fprintf(stderr, "Duplicate HUT Usage Spec at line %u\n", linectr);
700                                 continue;
701                         }
702                         if (lastlang != -1) {
703                                 if (new_langid(cp, lastlang+(u<<10)))
704                                         fprintf(stderr, "Duplicate LANGID Usage Spec at line %u\n", linectr);
705                                 continue;
706                         }
707                         fprintf(stderr, "Product/Subclass spec without prior Vendor/Class spec at line %u\n", linectr);
708                         continue;
709                 }
710                 if (buf[0] == '\t' && buf[1] == '\t' && isxdigit(buf[2])) {
711                         /* protocol spec */
712                         u = strtoul(buf+2, &cp, 16);
713                         while (isspace(*cp))
714                                 cp++;
715                         if (!*cp) {
716                                 fprintf(stderr, "Invalid protocol spec at line %u\n", linectr);
717                                 continue;
718                         }
719                         if (lastclass != -1 && lastsubclass != -1) {
720                                 if (new_protocol(cp, lastclass, lastsubclass, u))
721                                         fprintf(stderr, "Duplicate protocol spec at line %u class %02x:%02x:%02x %s\n", linectr, lastclass, lastsubclass, u, cp);
722                                 DBG(printf("line %5u protocol %02x:%02x:%02x %s\n", linectr, lastclass, lastsubclass, u, cp));
723                                 continue;
724                         }
725                         fprintf(stderr, "Protocol spec without prior Class and Subclass spec at line %u\n", linectr);
726                         continue;
727                 }
728                 if (buf[0] == 'H' && buf[1] == 'I' && buf[2] == 'D' && /*isspace(buf[3])*/ buf[3] == ' ') {
729                         cp = buf + 4;
730                         while (isspace(*cp))
731                                 cp++;
732                         if (!isxdigit(*cp)) {
733                                 fprintf(stderr, "Invalid HID type at line %u\n", linectr);
734                                 continue;
735                         }
736                         u = strtoul(cp, &cp, 16);
737                         while (isspace(*cp))
738                                 cp++;
739                         if (!*cp) {
740                                 fprintf(stderr, "Invalid HID type at line %u\n", linectr);
741                                 continue;
742                         }
743                         if (new_hid(cp, u))
744                                 fprintf(stderr, "Duplicate HID type spec at line %u terminal type %04x %s\n", linectr, u, cp);
745                         DBG(printf("line %5u HID type %02x %s\n", linectr, u, cp));
746                         continue;
747
748                 }
749                 if (buf[0] == 'H' && buf[1] == 'U' && buf[2] == 'T' && /*isspace(buf[3])*/ buf[3] == ' ') {
750                         cp = buf + 4;
751                         while (isspace(*cp))
752                                 cp++;
753                         if (!isxdigit(*cp)) {
754                                 fprintf(stderr, "Invalid HUT type at line %u\n", linectr);
755                                 continue;
756                         }
757                         u = strtoul(cp, &cp, 16);
758                         while (isspace(*cp))
759                                 cp++;
760                         if (!*cp) {
761                                 fprintf(stderr, "Invalid HUT type at line %u\n", linectr);
762                                 continue;
763                         }
764                         if (new_huts(cp, u))
765                                 fprintf(stderr, "Duplicate HUT type spec at line %u terminal type %04x %s\n", linectr, u, cp);
766                         lastlang = lastclass = lastvendor = lastsubclass = -1;
767                         lasthut = u;
768                         DBG(printf("line %5u HUT type %02x %s\n", linectr, u, cp));
769                         continue;
770
771                 }
772                 if (buf[0] == 'R' && buf[1] == ' ') {
773                         cp = buf + 2;
774                         while (isspace(*cp))
775                                 cp++;
776                         if (!isxdigit(*cp)) {
777                                 fprintf(stderr, "Invalid Report type at line %u\n", linectr);
778                                 continue;
779                         }
780                         u = strtoul(cp, &cp, 16);
781                         while (isspace(*cp))
782                                 cp++;
783                         if (!*cp) {
784                                 fprintf(stderr, "Invalid Report type at line %u\n", linectr);
785                                 continue;
786                         }
787                         if (new_reporttag(cp, u))
788                                 fprintf(stderr, "Duplicate Report type spec at line %u terminal type %04x %s\n", linectr, u, cp);
789                         DBG(printf("line %5u Report type %02x %s\n", linectr, u, cp));
790                         continue;
791
792                 }                       
793                 fprintf(stderr, "Unknown line at line %u\n", linectr);
794         }
795 }
796
797 /* ---------------------------------------------------------------------- */
798
799 int names_init(char *n)
800 {
801         usb_file f;
802         
803         if (!(f = usb_fopen(n, "r"))) {
804                 return errno;
805         }
806         parse(f);
807         usb_close(f);
808         return 0;
809 }