blob: 3b151dff85a6d4821d050297791fd57494b3284f [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/*
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +010025 * Copyright (C) 2005 Takahiro Hirofuchi
26 * - names_deinit() is added.
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -070027 */
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 {
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +010085 struct genericstrtable *next;
86 unsigned int num;
87 char name[1];
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -070088};
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
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100125static const char *names_genericstrtable(struct genericstrtable *t[HASHSZ],
126 unsigned int index)
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700127{
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100128 struct genericstrtable *h;
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700129
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100130 for (h = t[hashnum(index)]; h; h = h->next)
131 if (h->num == index)
132 return h->name;
133 return NULL;
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700134}
135
136const char *names_hid(u_int8_t hidd)
137{
138 return names_genericstrtable(hiddescriptors, hidd);
139}
140
141const char *names_reporttag(u_int8_t rt)
142{
143 return names_genericstrtable(reports, rt);
144}
145
146const char *names_huts(unsigned int data)
147{
148 return names_genericstrtable(huts, data);
149}
150
151const char *names_hutus(unsigned int data)
152{
153 return names_genericstrtable(hutus, data);
154}
155
156const char *names_langid(u_int16_t langid)
157{
158 return names_genericstrtable(langids, langid);
159}
160
161const char *names_physdes(u_int8_t ph)
162{
163 return names_genericstrtable(physdess, ph);
164}
165
166const char *names_bias(u_int8_t b)
167{
168 return names_genericstrtable(biass, b);
169}
170
171const char *names_countrycode(unsigned int countrycode)
172{
173 return names_genericstrtable(countrycodes, countrycode);
174}
175
176const char *names_vendor(u_int16_t vendorid)
177{
178 struct vendor *v;
179
180 v = vendors[hashnum(vendorid)];
181 for (; v; v = v->next)
182 if (v->vendorid == vendorid)
183 return v->name;
184 return NULL;
185}
186
187const char *names_product(u_int16_t vendorid, u_int16_t productid)
188{
189 struct product *p;
190
191 p = products[hashnum((vendorid << 16) | productid)];
192 for (; p; p = p->next)
193 if (p->vendorid == vendorid && p->productid == productid)
194 return p->name;
195 return NULL;
196}
197
198const char *names_class(u_int8_t classid)
199{
200 struct class *c;
201
202 c = classes[hashnum(classid)];
203 for (; c; c = c->next)
204 if (c->classid == classid)
205 return c->name;
206 return NULL;
207}
208
209const char *names_subclass(u_int8_t classid, u_int8_t subclassid)
210{
211 struct subclass *s;
212
213 s = subclasses[hashnum((classid << 8) | subclassid)];
214 for (; s; s = s->next)
215 if (s->classid == classid && s->subclassid == subclassid)
216 return s->name;
217 return NULL;
218}
219
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100220const char *names_protocol(u_int8_t classid, u_int8_t subclassid,
221 u_int8_t protocolid)
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700222{
223 struct protocol *p;
224
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100225 p = protocols[hashnum((classid << 16) | (subclassid << 8)
226 | protocolid)];
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700227 for (; p; p = p->next)
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100228 if (p->classid == classid && p->subclassid == subclassid &&
229 p->protocolid == protocolid)
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700230 return p->name;
231 return NULL;
232}
233
234const char *names_audioterminal(u_int16_t termt)
235{
236 struct audioterminal *at;
237
238 at = audioterminals[hashnum(termt)];
239 for (; at; at = at->next)
240 if (at->termt == termt)
241 return at->name;
242 return NULL;
243}
244
245/* ---------------------------------------------------------------------- */
246/* add a cleanup function by takahiro */
247
248struct pool {
249 struct pool *next;
250 void *mem;
251};
252
Kurt Kanzenbach5af7746f2013-02-22 12:13:26 +0100253static struct pool *pool_head;
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700254
255static void *my_malloc(size_t size)
256{
257 struct pool *p;
258
259 p = calloc(1, sizeof(struct pool));
260 if (!p) {
261 free(p);
262 return NULL;
263 }
264
265 p->mem = calloc(1, size);
266 if (!p->mem)
267 return NULL;
268
269 p->next = pool_head;
270 pool_head = p;
271
272 return p->mem;
273}
274
275void names_free(void)
276{
277 struct pool *pool;
278
279 if (!pool_head)
280 return;
281
282 for (pool = pool_head; pool != NULL; ) {
283 struct pool *tmp;
284
285 if (pool->mem)
286 free(pool->mem);
287
288 tmp = pool;
289 pool = pool->next;
290 free(tmp);
291 }
292}
293
294/* ---------------------------------------------------------------------- */
295
296static int new_vendor(const char *name, u_int16_t vendorid)
297{
298 struct vendor *v;
299 unsigned int h = hashnum(vendorid);
300
301 v = vendors[h];
302 for (; v; v = v->next)
303 if (v->vendorid == vendorid)
304 return -1;
305 v = my_malloc(sizeof(struct vendor) + strlen(name));
306 if (!v)
307 return -1;
308 strcpy(v->name, name);
309 v->vendorid = vendorid;
310 v->next = vendors[h];
311 vendors[h] = v;
312 return 0;
313}
314
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100315static int new_product(const char *name, u_int16_t vendorid,
316 u_int16_t productid)
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700317{
318 struct product *p;
319 unsigned int h = hashnum((vendorid << 16) | productid);
320
321 p = products[h];
322 for (; p; p = p->next)
323 if (p->vendorid == vendorid && p->productid == productid)
324 return -1;
325 p = my_malloc(sizeof(struct product) + strlen(name));
326 if (!p)
327 return -1;
328 strcpy(p->name, name);
329 p->vendorid = vendorid;
330 p->productid = productid;
331 p->next = products[h];
332 products[h] = p;
333 return 0;
334}
335
336static int new_class(const char *name, u_int8_t classid)
337{
338 struct class *c;
339 unsigned int h = hashnum(classid);
340
341 c = classes[h];
342 for (; c; c = c->next)
343 if (c->classid == classid)
344 return -1;
345 c = my_malloc(sizeof(struct class) + strlen(name));
346 if (!c)
347 return -1;
348 strcpy(c->name, name);
349 c->classid = classid;
350 c->next = classes[h];
351 classes[h] = c;
352 return 0;
353}
354
355static int new_subclass(const char *name, u_int8_t classid, u_int8_t subclassid)
356{
357 struct subclass *s;
358 unsigned int h = hashnum((classid << 8) | subclassid);
359
360 s = subclasses[h];
361 for (; s; s = s->next)
362 if (s->classid == classid && s->subclassid == subclassid)
363 return -1;
364 s = my_malloc(sizeof(struct subclass) + strlen(name));
365 if (!s)
366 return -1;
367 strcpy(s->name, name);
368 s->classid = classid;
369 s->subclassid = subclassid;
370 s->next = subclasses[h];
371 subclasses[h] = s;
372 return 0;
373}
374
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100375static int new_protocol(const char *name, u_int8_t classid, u_int8_t subclassid,
376 u_int8_t protocolid)
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700377{
378 struct protocol *p;
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100379 unsigned int h = hashnum((classid << 16) | (subclassid << 8)
380 | protocolid);
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700381
382 p = protocols[h];
383 for (; p; p = p->next)
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100384 if (p->classid == classid && p->subclassid == subclassid
385 && p->protocolid == protocolid)
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700386 return -1;
387 p = my_malloc(sizeof(struct protocol) + strlen(name));
388 if (!p)
389 return -1;
390 strcpy(p->name, name);
391 p->classid = classid;
392 p->subclassid = subclassid;
393 p->protocolid = protocolid;
394 p->next = protocols[h];
395 protocols[h] = p;
396 return 0;
397}
398
399static int new_audioterminal(const char *name, u_int16_t termt)
400{
401 struct audioterminal *at;
402 unsigned int h = hashnum(termt);
403
404 at = audioterminals[h];
405 for (; at; at = at->next)
406 if (at->termt == termt)
407 return -1;
408 at = my_malloc(sizeof(struct audioterminal) + strlen(name));
409 if (!at)
410 return -1;
411 strcpy(at->name, name);
412 at->termt = termt;
413 at->next = audioterminals[h];
414 audioterminals[h] = at;
415 return 0;
416}
417
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100418static int new_genericstrtable(struct genericstrtable *t[HASHSZ],
419 const char *name, unsigned int index)
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700420{
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100421 struct genericstrtable *g;
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700422 unsigned int h = hashnum(index);
423
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100424 for (g = t[h]; g; g = g->next)
425 if (g->num == index)
426 return -1;
427 g = my_malloc(sizeof(struct genericstrtable) + strlen(name));
428 if (!g)
429 return -1;
430 strcpy(g->name, name);
431 g->num = index;
432 g->next = t[h];
433 t[h] = g;
434 return 0;
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700435}
436
437static int new_hid(const char *name, u_int8_t hidd)
438{
439 return new_genericstrtable(hiddescriptors, name, hidd);
440}
441
442static int new_reporttag(const char *name, u_int8_t rt)
443{
444 return new_genericstrtable(reports, name, rt);
445}
446
447static int new_huts(const char *name, unsigned int data)
448{
449 return new_genericstrtable(huts, name, data);
450}
451
452static int new_hutus(const char *name, unsigned int data)
453{
454 return new_genericstrtable(hutus, name, data);
455}
456
457static int new_langid(const char *name, u_int16_t langid)
458{
459 return new_genericstrtable(langids, name, langid);
460}
461
462static int new_physdes(const char *name, u_int8_t ph)
463{
464 return new_genericstrtable(physdess, name, ph);
465}
466static int new_bias(const char *name, u_int8_t b)
467{
468 return new_genericstrtable(biass, name, b);
469}
470
471static int new_countrycode(const char *name, unsigned int countrycode)
472{
473 return new_genericstrtable(countrycodes, name, countrycode);
474}
475
476/* ---------------------------------------------------------------------- */
477
478#define DBG(x)
479
480static void parse(FILE *f)
481{
482 char buf[512], *cp;
483 unsigned int linectr = 0;
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100484 int lastvendor = -1;
485 int lastclass = -1;
486 int lastsubclass = -1;
487 int lasthut = -1;
488 int lastlang = -1;
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700489 unsigned int u;
490
491 while (fgets(buf, sizeof(buf), f)) {
492 linectr++;
493 /* remove line ends */
Kurt Kanzenbach6f19a2b2013-02-22 12:13:30 +0100494 cp = strchr(buf, 13);
495 if (cp)
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700496 *cp = 0;
Kurt Kanzenbach6f19a2b2013-02-22 12:13:30 +0100497 cp = strchr(buf, 10);
498 if (cp)
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700499 *cp = 0;
500 if (buf[0] == '#' || !buf[0])
501 continue;
502 cp = buf;
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100503 if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y'
504 && buf[3] == 'S' && buf[4] == 'D' && buf[5] == 'E'
505 && buf[6] == 'S' && /*isspace(buf[7])*/ buf[7] == ' ') {
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100506 cp = buf + 8;
507 while (isspace(*cp))
508 cp++;
509 if (!isxdigit(*cp)) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100510 fprintf(stderr, "Invalid Physdes type at line %u\n",
511 linectr);
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100512 continue;
513 }
514 u = strtoul(cp, &cp, 16);
515 while (isspace(*cp))
516 cp++;
517 if (!*cp) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100518 fprintf(stderr, "Invalid Physdes type at line %u\n",
519 linectr);
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100520 continue;
521 }
522 if (new_physdes(cp, u))
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100523 fprintf(stderr, "Duplicate Physdes type spec at line %u terminal type %04x %s\n",
524 linectr, u, cp);
525 DBG(printf("line %5u physdes type %02x %s\n", linectr,
526 u, cp));
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100527 continue;
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700528
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100529 }
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100530 if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y'
531 && /*isspace(buf[3])*/ buf[3] == ' ') {
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100532 cp = buf + 4;
533 while (isspace(*cp))
534 cp++;
535 if (!isxdigit(*cp)) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100536 fprintf(stderr, "Invalid PHY type at line %u\n",
537 linectr);
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100538 continue;
539 }
540 u = strtoul(cp, &cp, 16);
541 while (isspace(*cp))
542 cp++;
543 if (!*cp) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100544 fprintf(stderr, "Invalid PHY type at line %u\n",
545 linectr);
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100546 continue;
547 }
548 if (new_physdes(cp, u))
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100549 fprintf(stderr, "Duplicate PHY type spec at line %u terminal type %04x %s\n",
550 linectr, u, cp);
551 DBG(printf("line %5u PHY type %02x %s\n", linectr, u,
552 cp));
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100553 continue;
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700554
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100555 }
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100556 if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A'
557 && buf[3] == 'S' && /*isspace(buf[4])*/ buf[4] == ' ') {
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100558 cp = buf + 5;
559 while (isspace(*cp))
560 cp++;
561 if (!isxdigit(*cp)) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100562 fprintf(stderr, "Invalid BIAS type at line %u\n",
563 linectr);
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100564 continue;
565 }
566 u = strtoul(cp, &cp, 16);
567 while (isspace(*cp))
568 cp++;
569 if (!*cp) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100570 fprintf(stderr, "Invalid BIAS type at line %u\n",
571 linectr);
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100572 continue;
573 }
574 if (new_bias(cp, u))
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100575 fprintf(stderr, "Duplicate BIAS type spec at line %u terminal type %04x %s\n",
576 linectr, u, cp);
577 DBG(printf("line %5u BIAS type %02x %s\n", linectr, u,
578 cp));
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100579 continue;
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700580
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100581 }
582 if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') {
583 cp = buf+2;
584 while (isspace(*cp))
585 cp++;
586 if (!isxdigit(*cp)) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100587 fprintf(stderr, "Invalid LANGID spec at line %u\n",
588 linectr);
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100589 continue;
590 }
591 u = strtoul(cp, &cp, 16);
592 while (isspace(*cp))
593 cp++;
594 if (!*cp) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100595 fprintf(stderr, "Invalid LANGID spec at line %u\n",
596 linectr);
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100597 continue;
598 }
599 if (new_langid(cp, u))
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100600 fprintf(stderr, "Duplicate LANGID spec at line %u language-id %04x %s\n",
601 linectr, u, cp);
602 DBG(printf("line %5u LANGID %02x %s\n", linectr, u,
603 cp));
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100604 lasthut = lastclass = lastvendor = lastsubclass = -1;
605 lastlang = u;
606 continue;
607 }
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700608 if (buf[0] == 'C' && /*isspace(buf[1])*/ buf[1] == ' ') {
609 /* class spec */
610 cp = buf+2;
611 while (isspace(*cp))
612 cp++;
613 if (!isxdigit(*cp)) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100614 fprintf(stderr, "Invalid class spec at line %u\n",
615 linectr);
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700616 continue;
617 }
618 u = strtoul(cp, &cp, 16);
619 while (isspace(*cp))
620 cp++;
621 if (!*cp) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100622 fprintf(stderr, "Invalid class spec at line %u\n",
623 linectr);
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700624 continue;
625 }
626 if (new_class(cp, u))
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100627 fprintf(stderr, "Duplicate class spec at line %u class %04x %s\n",
628 linectr, u, cp);
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700629 DBG(printf("line %5u class %02x %s\n", linectr, u, cp));
630 lasthut = lastlang = lastvendor = lastsubclass = -1;
631 lastclass = u;
632 continue;
633 }
634 if (buf[0] == 'A' && buf[1] == 'T' && isspace(buf[2])) {
635 /* audio terminal type spec */
636 cp = buf+3;
637 while (isspace(*cp))
638 cp++;
639 if (!isxdigit(*cp)) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100640 fprintf(stderr, "Invalid audio terminal type at line %u\n",
641 linectr);
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700642 continue;
643 }
644 u = strtoul(cp, &cp, 16);
645 while (isspace(*cp))
646 cp++;
647 if (!*cp) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100648 fprintf(stderr, "Invalid audio terminal type at line %u\n",
649 linectr);
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700650 continue;
651 }
652 if (new_audioterminal(cp, u))
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100653 fprintf(stderr, "Duplicate audio terminal type spec at line %u terminal type %04x %s\n",
654 linectr, u, cp);
655 DBG(printf("line %5u audio terminal type %02x %s\n",
656 linectr, u, cp));
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700657 continue;
658 }
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100659 if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C'
660 && isspace(buf[3])) {
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700661 /* HID Descriptor bCountryCode */
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100662 cp = buf+3;
663 while (isspace(*cp))
664 cp++;
665 if (!isxdigit(*cp)) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100666 fprintf(stderr, "Invalid HID country code at line %u\n",
667 linectr);
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100668 continue;
669 }
670 u = strtoul(cp, &cp, 10);
671 while (isspace(*cp))
672 cp++;
673 if (!*cp) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100674 fprintf(stderr, "Invalid HID country code at line %u\n",
675 linectr);
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100676 continue;
677 }
678 if (new_countrycode(cp, u))
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100679 fprintf(stderr, "Duplicate HID country code at line %u country %02u %s\n",
680 linectr, u, cp);
681 DBG(printf("line %5u keyboard country code %02u %s\n",
682 linectr, u, cp));
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100683 continue;
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700684 }
685 if (isxdigit(*cp)) {
686 /* vendor */
687 u = strtoul(cp, &cp, 16);
688 while (isspace(*cp))
689 cp++;
690 if (!*cp) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100691 fprintf(stderr, "Invalid vendor spec at line %u\n",
692 linectr);
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700693 continue;
694 }
695 if (new_vendor(cp, u))
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100696 fprintf(stderr, "Duplicate vendor spec at line %u vendor %04x %s\n",
697 linectr, u, cp);
698 DBG(printf("line %5u vendor %04x %s\n", linectr, u,
699 cp));
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700700 lastvendor = u;
701 lasthut = lastlang = lastclass = lastsubclass = -1;
702 continue;
703 }
704 if (buf[0] == '\t' && isxdigit(buf[1])) {
705 /* product or subclass spec */
706 u = strtoul(buf+1, &cp, 16);
707 while (isspace(*cp))
708 cp++;
709 if (!*cp) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100710 fprintf(stderr, "Invalid product/subclass spec at line %u\n",
711 linectr);
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700712 continue;
713 }
714 if (lastvendor != -1) {
715 if (new_product(cp, lastvendor, u))
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100716 fprintf(stderr, "Duplicate product spec at line %u product %04x:%04x %s\n",
717 linectr, lastvendor, u, cp);
718 DBG(printf("line %5u product %04x:%04x %s\n",
719 linectr, lastvendor, u, cp));
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700720 continue;
721 }
722 if (lastclass != -1) {
723 if (new_subclass(cp, lastclass, u))
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100724 fprintf(stderr, "Duplicate subclass spec at line %u class %02x:%02x %s\n",
725 linectr, lastclass, u, cp);
726 DBG(printf("line %5u subclass %02x:%02x %s\n",
727 linectr, lastclass, u, cp));
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700728 lastsubclass = u;
729 continue;
730 }
731 if (lasthut != -1) {
732 if (new_hutus(cp, (lasthut << 16)+u))
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100733 fprintf(stderr, "Duplicate HUT Usage Spec at line %u\n",
734 linectr);
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700735 continue;
736 }
737 if (lastlang != -1) {
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100738 if (new_langid(cp, lastlang+(u<<10)))
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100739 fprintf(stderr, "Duplicate LANGID Usage Spec at line %u\n",
740 linectr);
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100741 continue;
742 }
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100743 fprintf(stderr, "Product/Subclass spec without prior Vendor/Class spec at line %u\n",
744 linectr);
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700745 continue;
746 }
747 if (buf[0] == '\t' && buf[1] == '\t' && isxdigit(buf[2])) {
748 /* protocol spec */
749 u = strtoul(buf+2, &cp, 16);
750 while (isspace(*cp))
751 cp++;
752 if (!*cp) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100753 fprintf(stderr, "Invalid protocol spec at line %u\n",
754 linectr);
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700755 continue;
756 }
757 if (lastclass != -1 && lastsubclass != -1) {
758 if (new_protocol(cp, lastclass, lastsubclass, u))
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100759 fprintf(stderr, "Duplicate protocol spec at line %u class %02x:%02x:%02x %s\n",
760 linectr, lastclass, lastsubclass, u, cp);
761 DBG(printf("line %5u protocol %02x:%02x:%02x %s\n",
762 linectr, lastclass, lastsubclass, u, cp));
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700763 continue;
764 }
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100765 fprintf(stderr, "Protocol spec without prior Class and Subclass spec at line %u\n",
766 linectr);
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700767 continue;
768 }
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100769 if (buf[0] == 'H' && buf[1] == 'I' && buf[2] == 'D'
770 && /*isspace(buf[3])*/ buf[3] == ' ') {
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700771 cp = buf + 4;
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100772 while (isspace(*cp))
773 cp++;
774 if (!isxdigit(*cp)) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100775 fprintf(stderr, "Invalid HID type at line %u\n",
776 linectr);
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100777 continue;
778 }
779 u = strtoul(cp, &cp, 16);
780 while (isspace(*cp))
781 cp++;
782 if (!*cp) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100783 fprintf(stderr, "Invalid HID type at line %u\n",
784 linectr);
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100785 continue;
786 }
787 if (new_hid(cp, u))
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100788 fprintf(stderr, "Duplicate HID type spec at line %u terminal type %04x %s\n",
789 linectr, u, cp);
790 DBG(printf("line %5u HID type %02x %s\n", linectr, u,
791 cp));
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100792 continue;
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700793
794 }
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100795 if (buf[0] == 'H' && buf[1] == 'U' && buf[2] == 'T'
796 && /*isspace(buf[3])*/ buf[3] == ' ') {
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100797 cp = buf + 4;
798 while (isspace(*cp))
799 cp++;
800 if (!isxdigit(*cp)) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100801 fprintf(stderr, "Invalid HUT type at line %u\n",
802 linectr);
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100803 continue;
804 }
805 u = strtoul(cp, &cp, 16);
806 while (isspace(*cp))
807 cp++;
808 if (!*cp) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100809 fprintf(stderr, "Invalid HUT type at line %u\n",
810 linectr);
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100811 continue;
812 }
813 if (new_huts(cp, u))
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100814 fprintf(stderr, "Duplicate HUT type spec at line %u terminal type %04x %s\n",
815 linectr, u, cp);
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700816 lastlang = lastclass = lastvendor = lastsubclass = -1;
817 lasthut = u;
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100818 DBG(printf("line %5u HUT type %02x %s\n", linectr, u,
819 cp));
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100820 continue;
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700821
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100822 }
823 if (buf[0] == 'R' && buf[1] == ' ') {
824 cp = buf + 2;
825 while (isspace(*cp))
826 cp++;
827 if (!isxdigit(*cp)) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100828 fprintf(stderr, "Invalid Report type at line %u\n",
829 linectr);
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100830 continue;
831 }
832 u = strtoul(cp, &cp, 16);
833 while (isspace(*cp))
834 cp++;
835 if (!*cp) {
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100836 fprintf(stderr, "Invalid Report type at line %u\n",
837 linectr);
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100838 continue;
839 }
840 if (new_reporttag(cp, u))
Kurt Kanzenbach9db91e12013-02-22 12:13:29 +0100841 fprintf(stderr, "Duplicate Report type spec at line %u terminal type %04x %s\n",
842 linectr, u, cp);
843 DBG(printf("line %5u Report type %02x %s\n", linectr,
844 u, cp));
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100845 continue;
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700846
Kurt Kanzenbachcbb86712013-02-22 12:13:25 +0100847 }
848 if (buf[0] == 'V' && buf[1] == 'T') {
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700849 /* add here */
850 continue;
851 }
852 fprintf(stderr, "Unknown line at line %u\n", linectr);
853 }
854}
855
856/* ---------------------------------------------------------------------- */
857
858int names_init(char *n)
859{
860 FILE *f;
861
Kurt Kanzenbach6f19a2b2013-02-22 12:13:30 +0100862 f = fopen(n, "r");
863 if (!f)
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700864 return errno;
Kurt Kanzenbach6f19a2b2013-02-22 12:13:30 +0100865
Takahiro Hirofuchi0945b4f2011-05-14 03:55:07 -0700866 parse(f);
867 fclose(f);
868 return 0;
869}