1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * names.c -- USB name database manipulation routines
7 * Copyright (C) 2005 Takahiro Hirofuchi
8 * - names_deinit() is added.
11 #include <sys/types.h>
23 #include "usbip_common.h"
33 u_int16_t vendorid, productid;
44 struct subclass *next;
45 u_int8_t classid, subclassid;
50 struct protocol *next;
51 u_int8_t classid, subclassid, protocolid;
55 struct genericstrtable {
56 struct genericstrtable *next;
66 static unsigned int hashnum(unsigned int num)
68 unsigned int mask1 = HASH1 << 27, mask2 = HASH2 << 27;
70 for (; mask1 >= HASH1; mask1 >>= 1, mask2 >>= 1)
73 return num & (HASHSZ-1);
77 static struct vendor *vendors[HASHSZ] = { NULL, };
78 static struct product *products[HASHSZ] = { NULL, };
79 static struct class *classes[HASHSZ] = { NULL, };
80 static struct subclass *subclasses[HASHSZ] = { NULL, };
81 static struct protocol *protocols[HASHSZ] = { NULL, };
83 const char *names_vendor(u_int16_t vendorid)
87 v = vendors[hashnum(vendorid)];
88 for (; v; v = v->next)
89 if (v->vendorid == vendorid)
94 const char *names_product(u_int16_t vendorid, u_int16_t productid)
98 p = products[hashnum((vendorid << 16) | productid)];
99 for (; p; p = p->next)
100 if (p->vendorid == vendorid && p->productid == productid)
105 const char *names_class(u_int8_t classid)
109 c = classes[hashnum(classid)];
110 for (; c; c = c->next)
111 if (c->classid == classid)
116 const char *names_subclass(u_int8_t classid, u_int8_t subclassid)
120 s = subclasses[hashnum((classid << 8) | subclassid)];
121 for (; s; s = s->next)
122 if (s->classid == classid && s->subclassid == subclassid)
127 const char *names_protocol(u_int8_t classid, u_int8_t subclassid,
132 p = protocols[hashnum((classid << 16) | (subclassid << 8)
134 for (; p; p = p->next)
135 if (p->classid == classid && p->subclassid == subclassid &&
136 p->protocolid == protocolid)
141 /* add a cleanup function by takahiro */
147 static struct pool *pool_head;
149 static void *my_malloc(size_t size)
153 p = calloc(1, sizeof(struct pool));
157 p->mem = calloc(1, size);
169 void names_free(void)
176 for (pool = pool_head; pool != NULL; ) {
188 static int new_vendor(const char *name, u_int16_t vendorid)
191 unsigned int h = hashnum(vendorid);
194 for (; v; v = v->next)
195 if (v->vendorid == vendorid)
197 v = my_malloc(sizeof(struct vendor) + strlen(name));
200 strcpy(v->name, name);
201 v->vendorid = vendorid;
202 v->next = vendors[h];
207 static int new_product(const char *name, u_int16_t vendorid,
211 unsigned int h = hashnum((vendorid << 16) | productid);
214 for (; p; p = p->next)
215 if (p->vendorid == vendorid && p->productid == productid)
217 p = my_malloc(sizeof(struct product) + strlen(name));
220 strcpy(p->name, name);
221 p->vendorid = vendorid;
222 p->productid = productid;
223 p->next = products[h];
228 static int new_class(const char *name, u_int8_t classid)
231 unsigned int h = hashnum(classid);
234 for (; c; c = c->next)
235 if (c->classid == classid)
237 c = my_malloc(sizeof(struct class) + strlen(name));
240 strcpy(c->name, name);
241 c->classid = classid;
242 c->next = classes[h];
247 static int new_subclass(const char *name, u_int8_t classid, u_int8_t subclassid)
250 unsigned int h = hashnum((classid << 8) | subclassid);
253 for (; s; s = s->next)
254 if (s->classid == classid && s->subclassid == subclassid)
256 s = my_malloc(sizeof(struct subclass) + strlen(name));
259 strcpy(s->name, name);
260 s->classid = classid;
261 s->subclassid = subclassid;
262 s->next = subclasses[h];
267 static int new_protocol(const char *name, u_int8_t classid, u_int8_t subclassid,
271 unsigned int h = hashnum((classid << 16) | (subclassid << 8)
275 for (; p; p = p->next)
276 if (p->classid == classid && p->subclassid == subclassid
277 && p->protocolid == protocolid)
279 p = my_malloc(sizeof(struct protocol) + strlen(name));
282 strcpy(p->name, name);
283 p->classid = classid;
284 p->subclassid = subclassid;
285 p->protocolid = protocolid;
286 p->next = protocols[h];
291 static void parse(FILE *f)
294 unsigned int linectr = 0;
297 int lastsubclass = -1;
302 while (fgets(buf, sizeof(buf), f)) {
304 /* remove line ends */
305 cp = strchr(buf, '\r');
308 cp = strchr(buf, '\n');
311 if (buf[0] == '#' || !buf[0])
314 if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' &&
315 buf[3] == 'S' && buf[4] == 'D' &&
316 buf[5] == 'E' && buf[6] == 'S' && /*isspace(buf[7])*/
320 if (buf[0] == 'P' && buf[1] == 'H' &&
321 buf[2] == 'Y' && /*isspace(buf[3])*/ buf[3] == ' ') {
324 if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A' &&
325 buf[3] == 'S' && /*isspace(buf[4])*/ buf[4] == ' ') {
328 if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') {
329 lasthut = lastclass = lastvendor = lastsubclass = -1;
331 * set 1 as pseudo-id to indicate that the parser is
337 if (buf[0] == 'C' && /*isspace(buf[1])*/ buf[1] == ' ') {
342 if (!isxdigit(*cp)) {
343 err("Invalid class spec at line %u", linectr);
346 u = strtoul(cp, &cp, 16);
350 err("Invalid class spec at line %u", linectr);
353 if (new_class(cp, u))
354 err("Duplicate class spec at line %u class %04x %s",
356 dbg("line %5u class %02x %s", linectr, u, cp);
357 lasthut = lastlang = lastvendor = lastsubclass = -1;
361 if (buf[0] == 'A' && buf[1] == 'T' && isspace(buf[2])) {
362 /* audio terminal type spec */
365 if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C'
366 && isspace(buf[3])) {
367 /* HID Descriptor bCountryCode */
372 u = strtoul(cp, &cp, 16);
376 err("Invalid vendor spec at line %u", linectr);
379 if (new_vendor(cp, u))
380 err("Duplicate vendor spec at line %u vendor %04x %s",
382 dbg("line %5u vendor %04x %s", linectr, u, cp);
384 lasthut = lastlang = lastclass = lastsubclass = -1;
387 if (buf[0] == '\t' && isxdigit(buf[1])) {
388 /* product or subclass spec */
389 u = strtoul(buf+1, &cp, 16);
393 err("Invalid product/subclass spec at line %u",
397 if (lastvendor != -1) {
398 if (new_product(cp, lastvendor, u))
399 err("Duplicate product spec at line %u product %04x:%04x %s",
400 linectr, lastvendor, u, cp);
401 dbg("line %5u product %04x:%04x %s", linectr,
405 if (lastclass != -1) {
406 if (new_subclass(cp, lastclass, u))
407 err("Duplicate subclass spec at line %u class %02x:%02x %s",
408 linectr, lastclass, u, cp);
409 dbg("line %5u subclass %02x:%02x %s", linectr,
415 /* do not store hut */
418 if (lastlang != -1) {
419 /* do not store langid */
422 err("Product/Subclass spec without prior Vendor/Class spec at line %u",
426 if (buf[0] == '\t' && buf[1] == '\t' && isxdigit(buf[2])) {
428 u = strtoul(buf+2, &cp, 16);
432 err("Invalid protocol spec at line %u",
436 if (lastclass != -1 && lastsubclass != -1) {
437 if (new_protocol(cp, lastclass, lastsubclass,
439 err("Duplicate protocol spec at line %u class %02x:%02x:%02x %s",
440 linectr, lastclass, lastsubclass,
442 dbg("line %5u protocol %02x:%02x:%02x %s",
443 linectr, lastclass, lastsubclass, u, cp);
446 err("Protocol spec without prior Class and Subclass spec at line %u",
450 if (buf[0] == 'H' && buf[1] == 'I' &&
451 buf[2] == 'D' && /*isspace(buf[3])*/ buf[3] == ' ') {
454 if (buf[0] == 'H' && buf[1] == 'U' &&
455 buf[2] == 'T' && /*isspace(buf[3])*/ buf[3] == ' ') {
456 lastlang = lastclass = lastvendor = lastsubclass = -1;
458 * set 1 as pseudo-id to indicate that the parser is
459 * in a `HUT' section.
464 if (buf[0] == 'R' && buf[1] == ' ')
467 if (buf[0] == 'V' && buf[1] == 'T')
470 err("Unknown line at line %u", linectr);
475 int names_init(char *n)