2 * names.c -- USB name database manipulation routines
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 * Copyright (C) 2005 Takahiro Hirofuchi
25 * - names_deinit() is added.
29 #include <sys/types.h>
41 #include "usbip_common.h"
51 u_int16_t vendorid, productid;
62 struct subclass *next;
63 u_int8_t classid, subclassid;
68 struct protocol *next;
69 u_int8_t classid, subclassid, protocolid;
73 struct genericstrtable {
74 struct genericstrtable *next;
84 static unsigned int hashnum(unsigned int num)
86 unsigned int mask1 = HASH1 << 27, mask2 = HASH2 << 27;
88 for (; mask1 >= HASH1; mask1 >>= 1, mask2 >>= 1)
91 return num & (HASHSZ-1);
95 static struct vendor *vendors[HASHSZ] = { NULL, };
96 static struct product *products[HASHSZ] = { NULL, };
97 static struct class *classes[HASHSZ] = { NULL, };
98 static struct subclass *subclasses[HASHSZ] = { NULL, };
99 static struct protocol *protocols[HASHSZ] = { NULL, };
101 const char *names_vendor(u_int16_t vendorid)
105 v = vendors[hashnum(vendorid)];
106 for (; v; v = v->next)
107 if (v->vendorid == vendorid)
112 const char *names_product(u_int16_t vendorid, u_int16_t productid)
116 p = products[hashnum((vendorid << 16) | productid)];
117 for (; p; p = p->next)
118 if (p->vendorid == vendorid && p->productid == productid)
123 const char *names_class(u_int8_t classid)
127 c = classes[hashnum(classid)];
128 for (; c; c = c->next)
129 if (c->classid == classid)
134 const char *names_subclass(u_int8_t classid, u_int8_t subclassid)
138 s = subclasses[hashnum((classid << 8) | subclassid)];
139 for (; s; s = s->next)
140 if (s->classid == classid && s->subclassid == subclassid)
145 const char *names_protocol(u_int8_t classid, u_int8_t subclassid,
150 p = protocols[hashnum((classid << 16) | (subclassid << 8)
152 for (; p; p = p->next)
153 if (p->classid == classid && p->subclassid == subclassid &&
154 p->protocolid == protocolid)
159 /* add a cleanup function by takahiro */
165 static struct pool *pool_head;
167 static void *my_malloc(size_t size)
171 p = calloc(1, sizeof(struct pool));
175 p->mem = calloc(1, size);
187 void names_free(void)
194 for (pool = pool_head; pool != NULL; ) {
206 static int new_vendor(const char *name, u_int16_t vendorid)
209 unsigned int h = hashnum(vendorid);
212 for (; v; v = v->next)
213 if (v->vendorid == vendorid)
215 v = my_malloc(sizeof(struct vendor) + strlen(name));
218 strcpy(v->name, name);
219 v->vendorid = vendorid;
220 v->next = vendors[h];
225 static int new_product(const char *name, u_int16_t vendorid,
229 unsigned int h = hashnum((vendorid << 16) | productid);
232 for (; p; p = p->next)
233 if (p->vendorid == vendorid && p->productid == productid)
235 p = my_malloc(sizeof(struct product) + strlen(name));
238 strcpy(p->name, name);
239 p->vendorid = vendorid;
240 p->productid = productid;
241 p->next = products[h];
246 static int new_class(const char *name, u_int8_t classid)
249 unsigned int h = hashnum(classid);
252 for (; c; c = c->next)
253 if (c->classid == classid)
255 c = my_malloc(sizeof(struct class) + strlen(name));
258 strcpy(c->name, name);
259 c->classid = classid;
260 c->next = classes[h];
265 static int new_subclass(const char *name, u_int8_t classid, u_int8_t subclassid)
268 unsigned int h = hashnum((classid << 8) | subclassid);
271 for (; s; s = s->next)
272 if (s->classid == classid && s->subclassid == subclassid)
274 s = my_malloc(sizeof(struct subclass) + strlen(name));
277 strcpy(s->name, name);
278 s->classid = classid;
279 s->subclassid = subclassid;
280 s->next = subclasses[h];
285 static int new_protocol(const char *name, u_int8_t classid, u_int8_t subclassid,
289 unsigned int h = hashnum((classid << 16) | (subclassid << 8)
293 for (; p; p = p->next)
294 if (p->classid == classid && p->subclassid == subclassid
295 && p->protocolid == protocolid)
297 p = my_malloc(sizeof(struct protocol) + strlen(name));
300 strcpy(p->name, name);
301 p->classid = classid;
302 p->subclassid = subclassid;
303 p->protocolid = protocolid;
304 p->next = protocols[h];
309 static void parse(FILE *f)
312 unsigned int linectr = 0;
315 int lastsubclass = -1;
320 while (fgets(buf, sizeof(buf), f)) {
322 /* remove line ends */
323 cp = strchr(buf, '\r');
326 cp = strchr(buf, '\n');
329 if (buf[0] == '#' || !buf[0])
332 if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' &&
333 buf[3] == 'S' && buf[4] == 'D' &&
334 buf[5] == 'E' && buf[6] == 'S' && /*isspace(buf[7])*/
338 if (buf[0] == 'P' && buf[1] == 'H' &&
339 buf[2] == 'Y' && /*isspace(buf[3])*/ buf[3] == ' ') {
342 if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A' &&
343 buf[3] == 'S' && /*isspace(buf[4])*/ buf[4] == ' ') {
346 if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') {
347 lasthut = lastclass = lastvendor = lastsubclass = -1;
349 * set 1 as pseudo-id to indicate that the parser is
355 if (buf[0] == 'C' && /*isspace(buf[1])*/ buf[1] == ' ') {
360 if (!isxdigit(*cp)) {
361 err("Invalid class spec at line %u", linectr);
364 u = strtoul(cp, &cp, 16);
368 err("Invalid class spec at line %u", linectr);
371 if (new_class(cp, u))
372 err("Duplicate class spec at line %u class %04x %s",
374 dbg("line %5u class %02x %s", linectr, u, cp);
375 lasthut = lastlang = lastvendor = lastsubclass = -1;
379 if (buf[0] == 'A' && buf[1] == 'T' && isspace(buf[2])) {
380 /* audio terminal type spec */
383 if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C'
384 && isspace(buf[3])) {
385 /* HID Descriptor bCountryCode */
390 u = strtoul(cp, &cp, 16);
394 err("Invalid vendor spec at line %u", linectr);
397 if (new_vendor(cp, u))
398 err("Duplicate vendor spec at line %u vendor %04x %s",
400 dbg("line %5u vendor %04x %s", linectr, u, cp);
402 lasthut = lastlang = lastclass = lastsubclass = -1;
405 if (buf[0] == '\t' && isxdigit(buf[1])) {
406 /* product or subclass spec */
407 u = strtoul(buf+1, &cp, 16);
411 err("Invalid product/subclass spec at line %u",
415 if (lastvendor != -1) {
416 if (new_product(cp, lastvendor, u))
417 err("Duplicate product spec at line %u product %04x:%04x %s",
418 linectr, lastvendor, u, cp);
419 dbg("line %5u product %04x:%04x %s", linectr,
423 if (lastclass != -1) {
424 if (new_subclass(cp, lastclass, u))
425 err("Duplicate subclass spec at line %u class %02x:%02x %s",
426 linectr, lastclass, u, cp);
427 dbg("line %5u subclass %02x:%02x %s", linectr,
433 /* do not store hut */
436 if (lastlang != -1) {
437 /* do not store langid */
440 err("Product/Subclass spec without prior Vendor/Class spec at line %u",
444 if (buf[0] == '\t' && buf[1] == '\t' && isxdigit(buf[2])) {
446 u = strtoul(buf+2, &cp, 16);
450 err("Invalid protocol spec at line %u",
454 if (lastclass != -1 && lastsubclass != -1) {
455 if (new_protocol(cp, lastclass, lastsubclass,
457 err("Duplicate protocol spec at line %u class %02x:%02x:%02x %s",
458 linectr, lastclass, lastsubclass,
460 dbg("line %5u protocol %02x:%02x:%02x %s",
461 linectr, lastclass, lastsubclass, u, cp);
464 err("Protocol spec without prior Class and Subclass spec at line %u",
468 if (buf[0] == 'H' && buf[1] == 'I' &&
469 buf[2] == 'D' && /*isspace(buf[3])*/ buf[3] == ' ') {
472 if (buf[0] == 'H' && buf[1] == 'U' &&
473 buf[2] == 'T' && /*isspace(buf[3])*/ buf[3] == ' ') {
474 lastlang = lastclass = lastvendor = lastsubclass = -1;
476 * set 1 as pseudo-id to indicate that the parser is
477 * in a `HUT' section.
482 if (buf[0] == 'R' && buf[1] == ' ')
485 if (buf[0] == 'V' && buf[1] == 'T')
488 err("Unknown line at line %u", linectr);
493 int names_init(char *n)