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