162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * names.c -- USB name database manipulation routines 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 1999, 2000 Thomas Sailer (sailer@ife.ee.ethz.ch) 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2005 Takahiro Hirofuchi 862306a36Sopenharmony_ci * - names_deinit() is added. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <sys/types.h> 1262306a36Sopenharmony_ci#include <sys/stat.h> 1362306a36Sopenharmony_ci#include <fcntl.h> 1462306a36Sopenharmony_ci#include <dirent.h> 1562306a36Sopenharmony_ci#include <string.h> 1662306a36Sopenharmony_ci#include <errno.h> 1762306a36Sopenharmony_ci#include <stdlib.h> 1862306a36Sopenharmony_ci#include <unistd.h> 1962306a36Sopenharmony_ci#include <stdio.h> 2062306a36Sopenharmony_ci#include <ctype.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include "names.h" 2362306a36Sopenharmony_ci#include "usbip_common.h" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistruct vendor { 2662306a36Sopenharmony_ci struct vendor *next; 2762306a36Sopenharmony_ci u_int16_t vendorid; 2862306a36Sopenharmony_ci char name[1]; 2962306a36Sopenharmony_ci}; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistruct product { 3262306a36Sopenharmony_ci struct product *next; 3362306a36Sopenharmony_ci u_int16_t vendorid, productid; 3462306a36Sopenharmony_ci char name[1]; 3562306a36Sopenharmony_ci}; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistruct class { 3862306a36Sopenharmony_ci struct class *next; 3962306a36Sopenharmony_ci u_int8_t classid; 4062306a36Sopenharmony_ci char name[1]; 4162306a36Sopenharmony_ci}; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistruct subclass { 4462306a36Sopenharmony_ci struct subclass *next; 4562306a36Sopenharmony_ci u_int8_t classid, subclassid; 4662306a36Sopenharmony_ci char name[1]; 4762306a36Sopenharmony_ci}; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistruct protocol { 5062306a36Sopenharmony_ci struct protocol *next; 5162306a36Sopenharmony_ci u_int8_t classid, subclassid, protocolid; 5262306a36Sopenharmony_ci char name[1]; 5362306a36Sopenharmony_ci}; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistruct genericstrtable { 5662306a36Sopenharmony_ci struct genericstrtable *next; 5762306a36Sopenharmony_ci unsigned int num; 5862306a36Sopenharmony_ci char name[1]; 5962306a36Sopenharmony_ci}; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#define HASH1 0x10 6362306a36Sopenharmony_ci#define HASH2 0x02 6462306a36Sopenharmony_ci#define HASHSZ 16 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic unsigned int hashnum(unsigned int num) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci unsigned int mask1 = HASH1 << 27, mask2 = HASH2 << 27; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci for (; mask1 >= HASH1; mask1 >>= 1, mask2 >>= 1) 7162306a36Sopenharmony_ci if (num & mask1) 7262306a36Sopenharmony_ci num ^= mask2; 7362306a36Sopenharmony_ci return num & (HASHSZ-1); 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic struct vendor *vendors[HASHSZ] = { NULL, }; 7862306a36Sopenharmony_cistatic struct product *products[HASHSZ] = { NULL, }; 7962306a36Sopenharmony_cistatic struct class *classes[HASHSZ] = { NULL, }; 8062306a36Sopenharmony_cistatic struct subclass *subclasses[HASHSZ] = { NULL, }; 8162306a36Sopenharmony_cistatic struct protocol *protocols[HASHSZ] = { NULL, }; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ciconst char *names_vendor(u_int16_t vendorid) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci struct vendor *v; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci v = vendors[hashnum(vendorid)]; 8862306a36Sopenharmony_ci for (; v; v = v->next) 8962306a36Sopenharmony_ci if (v->vendorid == vendorid) 9062306a36Sopenharmony_ci return v->name; 9162306a36Sopenharmony_ci return NULL; 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ciconst char *names_product(u_int16_t vendorid, u_int16_t productid) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci struct product *p; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci p = products[hashnum((vendorid << 16) | productid)]; 9962306a36Sopenharmony_ci for (; p; p = p->next) 10062306a36Sopenharmony_ci if (p->vendorid == vendorid && p->productid == productid) 10162306a36Sopenharmony_ci return p->name; 10262306a36Sopenharmony_ci return NULL; 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ciconst char *names_class(u_int8_t classid) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci struct class *c; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci c = classes[hashnum(classid)]; 11062306a36Sopenharmony_ci for (; c; c = c->next) 11162306a36Sopenharmony_ci if (c->classid == classid) 11262306a36Sopenharmony_ci return c->name; 11362306a36Sopenharmony_ci return NULL; 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ciconst char *names_subclass(u_int8_t classid, u_int8_t subclassid) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci struct subclass *s; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci s = subclasses[hashnum((classid << 8) | subclassid)]; 12162306a36Sopenharmony_ci for (; s; s = s->next) 12262306a36Sopenharmony_ci if (s->classid == classid && s->subclassid == subclassid) 12362306a36Sopenharmony_ci return s->name; 12462306a36Sopenharmony_ci return NULL; 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ciconst char *names_protocol(u_int8_t classid, u_int8_t subclassid, 12862306a36Sopenharmony_ci u_int8_t protocolid) 12962306a36Sopenharmony_ci{ 13062306a36Sopenharmony_ci struct protocol *p; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci p = protocols[hashnum((classid << 16) | (subclassid << 8) 13362306a36Sopenharmony_ci | protocolid)]; 13462306a36Sopenharmony_ci for (; p; p = p->next) 13562306a36Sopenharmony_ci if (p->classid == classid && p->subclassid == subclassid && 13662306a36Sopenharmony_ci p->protocolid == protocolid) 13762306a36Sopenharmony_ci return p->name; 13862306a36Sopenharmony_ci return NULL; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci/* add a cleanup function by takahiro */ 14262306a36Sopenharmony_cistruct pool { 14362306a36Sopenharmony_ci struct pool *next; 14462306a36Sopenharmony_ci void *mem; 14562306a36Sopenharmony_ci}; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic struct pool *pool_head; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cistatic void *my_malloc(size_t size) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci struct pool *p; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci p = calloc(1, sizeof(struct pool)); 15462306a36Sopenharmony_ci if (!p) 15562306a36Sopenharmony_ci return NULL; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci p->mem = calloc(1, size); 15862306a36Sopenharmony_ci if (!p->mem) { 15962306a36Sopenharmony_ci free(p); 16062306a36Sopenharmony_ci return NULL; 16162306a36Sopenharmony_ci } 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci p->next = pool_head; 16462306a36Sopenharmony_ci pool_head = p; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci return p->mem; 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_civoid names_free(void) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci struct pool *pool; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci if (!pool_head) 17462306a36Sopenharmony_ci return; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci for (pool = pool_head; pool != NULL; ) { 17762306a36Sopenharmony_ci struct pool *tmp; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci if (pool->mem) 18062306a36Sopenharmony_ci free(pool->mem); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci tmp = pool; 18362306a36Sopenharmony_ci pool = pool->next; 18462306a36Sopenharmony_ci free(tmp); 18562306a36Sopenharmony_ci } 18662306a36Sopenharmony_ci} 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cistatic int new_vendor(const char *name, u_int16_t vendorid) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci struct vendor *v; 19162306a36Sopenharmony_ci unsigned int h = hashnum(vendorid); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci v = vendors[h]; 19462306a36Sopenharmony_ci for (; v; v = v->next) 19562306a36Sopenharmony_ci if (v->vendorid == vendorid) 19662306a36Sopenharmony_ci return -1; 19762306a36Sopenharmony_ci v = my_malloc(sizeof(struct vendor) + strlen(name)); 19862306a36Sopenharmony_ci if (!v) 19962306a36Sopenharmony_ci return -1; 20062306a36Sopenharmony_ci strcpy(v->name, name); 20162306a36Sopenharmony_ci v->vendorid = vendorid; 20262306a36Sopenharmony_ci v->next = vendors[h]; 20362306a36Sopenharmony_ci vendors[h] = v; 20462306a36Sopenharmony_ci return 0; 20562306a36Sopenharmony_ci} 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_cistatic int new_product(const char *name, u_int16_t vendorid, 20862306a36Sopenharmony_ci u_int16_t productid) 20962306a36Sopenharmony_ci{ 21062306a36Sopenharmony_ci struct product *p; 21162306a36Sopenharmony_ci unsigned int h = hashnum((vendorid << 16) | productid); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci p = products[h]; 21462306a36Sopenharmony_ci for (; p; p = p->next) 21562306a36Sopenharmony_ci if (p->vendorid == vendorid && p->productid == productid) 21662306a36Sopenharmony_ci return -1; 21762306a36Sopenharmony_ci p = my_malloc(sizeof(struct product) + strlen(name)); 21862306a36Sopenharmony_ci if (!p) 21962306a36Sopenharmony_ci return -1; 22062306a36Sopenharmony_ci strcpy(p->name, name); 22162306a36Sopenharmony_ci p->vendorid = vendorid; 22262306a36Sopenharmony_ci p->productid = productid; 22362306a36Sopenharmony_ci p->next = products[h]; 22462306a36Sopenharmony_ci products[h] = p; 22562306a36Sopenharmony_ci return 0; 22662306a36Sopenharmony_ci} 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_cistatic int new_class(const char *name, u_int8_t classid) 22962306a36Sopenharmony_ci{ 23062306a36Sopenharmony_ci struct class *c; 23162306a36Sopenharmony_ci unsigned int h = hashnum(classid); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci c = classes[h]; 23462306a36Sopenharmony_ci for (; c; c = c->next) 23562306a36Sopenharmony_ci if (c->classid == classid) 23662306a36Sopenharmony_ci return -1; 23762306a36Sopenharmony_ci c = my_malloc(sizeof(struct class) + strlen(name)); 23862306a36Sopenharmony_ci if (!c) 23962306a36Sopenharmony_ci return -1; 24062306a36Sopenharmony_ci strcpy(c->name, name); 24162306a36Sopenharmony_ci c->classid = classid; 24262306a36Sopenharmony_ci c->next = classes[h]; 24362306a36Sopenharmony_ci classes[h] = c; 24462306a36Sopenharmony_ci return 0; 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistatic int new_subclass(const char *name, u_int8_t classid, u_int8_t subclassid) 24862306a36Sopenharmony_ci{ 24962306a36Sopenharmony_ci struct subclass *s; 25062306a36Sopenharmony_ci unsigned int h = hashnum((classid << 8) | subclassid); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci s = subclasses[h]; 25362306a36Sopenharmony_ci for (; s; s = s->next) 25462306a36Sopenharmony_ci if (s->classid == classid && s->subclassid == subclassid) 25562306a36Sopenharmony_ci return -1; 25662306a36Sopenharmony_ci s = my_malloc(sizeof(struct subclass) + strlen(name)); 25762306a36Sopenharmony_ci if (!s) 25862306a36Sopenharmony_ci return -1; 25962306a36Sopenharmony_ci strcpy(s->name, name); 26062306a36Sopenharmony_ci s->classid = classid; 26162306a36Sopenharmony_ci s->subclassid = subclassid; 26262306a36Sopenharmony_ci s->next = subclasses[h]; 26362306a36Sopenharmony_ci subclasses[h] = s; 26462306a36Sopenharmony_ci return 0; 26562306a36Sopenharmony_ci} 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_cistatic int new_protocol(const char *name, u_int8_t classid, u_int8_t subclassid, 26862306a36Sopenharmony_ci u_int8_t protocolid) 26962306a36Sopenharmony_ci{ 27062306a36Sopenharmony_ci struct protocol *p; 27162306a36Sopenharmony_ci unsigned int h = hashnum((classid << 16) | (subclassid << 8) 27262306a36Sopenharmony_ci | protocolid); 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci p = protocols[h]; 27562306a36Sopenharmony_ci for (; p; p = p->next) 27662306a36Sopenharmony_ci if (p->classid == classid && p->subclassid == subclassid 27762306a36Sopenharmony_ci && p->protocolid == protocolid) 27862306a36Sopenharmony_ci return -1; 27962306a36Sopenharmony_ci p = my_malloc(sizeof(struct protocol) + strlen(name)); 28062306a36Sopenharmony_ci if (!p) 28162306a36Sopenharmony_ci return -1; 28262306a36Sopenharmony_ci strcpy(p->name, name); 28362306a36Sopenharmony_ci p->classid = classid; 28462306a36Sopenharmony_ci p->subclassid = subclassid; 28562306a36Sopenharmony_ci p->protocolid = protocolid; 28662306a36Sopenharmony_ci p->next = protocols[h]; 28762306a36Sopenharmony_ci protocols[h] = p; 28862306a36Sopenharmony_ci return 0; 28962306a36Sopenharmony_ci} 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_cistatic void parse(FILE *f) 29262306a36Sopenharmony_ci{ 29362306a36Sopenharmony_ci char buf[512], *cp; 29462306a36Sopenharmony_ci unsigned int linectr = 0; 29562306a36Sopenharmony_ci int lastvendor = -1; 29662306a36Sopenharmony_ci int lastclass = -1; 29762306a36Sopenharmony_ci int lastsubclass = -1; 29862306a36Sopenharmony_ci int lasthut = -1; 29962306a36Sopenharmony_ci int lastlang = -1; 30062306a36Sopenharmony_ci unsigned int u; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci while (fgets(buf, sizeof(buf), f)) { 30362306a36Sopenharmony_ci linectr++; 30462306a36Sopenharmony_ci /* remove line ends */ 30562306a36Sopenharmony_ci cp = strchr(buf, '\r'); 30662306a36Sopenharmony_ci if (cp) 30762306a36Sopenharmony_ci *cp = 0; 30862306a36Sopenharmony_ci cp = strchr(buf, '\n'); 30962306a36Sopenharmony_ci if (cp) 31062306a36Sopenharmony_ci *cp = 0; 31162306a36Sopenharmony_ci if (buf[0] == '#' || !buf[0]) 31262306a36Sopenharmony_ci continue; 31362306a36Sopenharmony_ci cp = buf; 31462306a36Sopenharmony_ci if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' && 31562306a36Sopenharmony_ci buf[3] == 'S' && buf[4] == 'D' && 31662306a36Sopenharmony_ci buf[5] == 'E' && buf[6] == 'S' && /*isspace(buf[7])*/ 31762306a36Sopenharmony_ci buf[7] == ' ') { 31862306a36Sopenharmony_ci continue; 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci if (buf[0] == 'P' && buf[1] == 'H' && 32162306a36Sopenharmony_ci buf[2] == 'Y' && /*isspace(buf[3])*/ buf[3] == ' ') { 32262306a36Sopenharmony_ci continue; 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A' && 32562306a36Sopenharmony_ci buf[3] == 'S' && /*isspace(buf[4])*/ buf[4] == ' ') { 32662306a36Sopenharmony_ci continue; 32762306a36Sopenharmony_ci } 32862306a36Sopenharmony_ci if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') { 32962306a36Sopenharmony_ci lasthut = lastclass = lastvendor = lastsubclass = -1; 33062306a36Sopenharmony_ci /* 33162306a36Sopenharmony_ci * set 1 as pseudo-id to indicate that the parser is 33262306a36Sopenharmony_ci * in a `L' section. 33362306a36Sopenharmony_ci */ 33462306a36Sopenharmony_ci lastlang = 1; 33562306a36Sopenharmony_ci continue; 33662306a36Sopenharmony_ci } 33762306a36Sopenharmony_ci if (buf[0] == 'C' && /*isspace(buf[1])*/ buf[1] == ' ') { 33862306a36Sopenharmony_ci /* class spec */ 33962306a36Sopenharmony_ci cp = buf+2; 34062306a36Sopenharmony_ci while (isspace(*cp)) 34162306a36Sopenharmony_ci cp++; 34262306a36Sopenharmony_ci if (!isxdigit(*cp)) { 34362306a36Sopenharmony_ci err("Invalid class spec at line %u", linectr); 34462306a36Sopenharmony_ci continue; 34562306a36Sopenharmony_ci } 34662306a36Sopenharmony_ci u = strtoul(cp, &cp, 16); 34762306a36Sopenharmony_ci while (isspace(*cp)) 34862306a36Sopenharmony_ci cp++; 34962306a36Sopenharmony_ci if (!*cp) { 35062306a36Sopenharmony_ci err("Invalid class spec at line %u", linectr); 35162306a36Sopenharmony_ci continue; 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci if (new_class(cp, u)) 35462306a36Sopenharmony_ci err("Duplicate class spec at line %u class %04x %s", 35562306a36Sopenharmony_ci linectr, u, cp); 35662306a36Sopenharmony_ci dbg("line %5u class %02x %s", linectr, u, cp); 35762306a36Sopenharmony_ci lasthut = lastlang = lastvendor = lastsubclass = -1; 35862306a36Sopenharmony_ci lastclass = u; 35962306a36Sopenharmony_ci continue; 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci if (buf[0] == 'A' && buf[1] == 'T' && isspace(buf[2])) { 36262306a36Sopenharmony_ci /* audio terminal type spec */ 36362306a36Sopenharmony_ci continue; 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C' 36662306a36Sopenharmony_ci && isspace(buf[3])) { 36762306a36Sopenharmony_ci /* HID Descriptor bCountryCode */ 36862306a36Sopenharmony_ci continue; 36962306a36Sopenharmony_ci } 37062306a36Sopenharmony_ci if (isxdigit(*cp)) { 37162306a36Sopenharmony_ci /* vendor */ 37262306a36Sopenharmony_ci u = strtoul(cp, &cp, 16); 37362306a36Sopenharmony_ci while (isspace(*cp)) 37462306a36Sopenharmony_ci cp++; 37562306a36Sopenharmony_ci if (!*cp) { 37662306a36Sopenharmony_ci err("Invalid vendor spec at line %u", linectr); 37762306a36Sopenharmony_ci continue; 37862306a36Sopenharmony_ci } 37962306a36Sopenharmony_ci if (new_vendor(cp, u)) 38062306a36Sopenharmony_ci err("Duplicate vendor spec at line %u vendor %04x %s", 38162306a36Sopenharmony_ci linectr, u, cp); 38262306a36Sopenharmony_ci dbg("line %5u vendor %04x %s", linectr, u, cp); 38362306a36Sopenharmony_ci lastvendor = u; 38462306a36Sopenharmony_ci lasthut = lastlang = lastclass = lastsubclass = -1; 38562306a36Sopenharmony_ci continue; 38662306a36Sopenharmony_ci } 38762306a36Sopenharmony_ci if (buf[0] == '\t' && isxdigit(buf[1])) { 38862306a36Sopenharmony_ci /* product or subclass spec */ 38962306a36Sopenharmony_ci u = strtoul(buf+1, &cp, 16); 39062306a36Sopenharmony_ci while (isspace(*cp)) 39162306a36Sopenharmony_ci cp++; 39262306a36Sopenharmony_ci if (!*cp) { 39362306a36Sopenharmony_ci err("Invalid product/subclass spec at line %u", 39462306a36Sopenharmony_ci linectr); 39562306a36Sopenharmony_ci continue; 39662306a36Sopenharmony_ci } 39762306a36Sopenharmony_ci if (lastvendor != -1) { 39862306a36Sopenharmony_ci if (new_product(cp, lastvendor, u)) 39962306a36Sopenharmony_ci err("Duplicate product spec at line %u product %04x:%04x %s", 40062306a36Sopenharmony_ci linectr, lastvendor, u, cp); 40162306a36Sopenharmony_ci dbg("line %5u product %04x:%04x %s", linectr, 40262306a36Sopenharmony_ci lastvendor, u, cp); 40362306a36Sopenharmony_ci continue; 40462306a36Sopenharmony_ci } 40562306a36Sopenharmony_ci if (lastclass != -1) { 40662306a36Sopenharmony_ci if (new_subclass(cp, lastclass, u)) 40762306a36Sopenharmony_ci err("Duplicate subclass spec at line %u class %02x:%02x %s", 40862306a36Sopenharmony_ci linectr, lastclass, u, cp); 40962306a36Sopenharmony_ci dbg("line %5u subclass %02x:%02x %s", linectr, 41062306a36Sopenharmony_ci lastclass, u, cp); 41162306a36Sopenharmony_ci lastsubclass = u; 41262306a36Sopenharmony_ci continue; 41362306a36Sopenharmony_ci } 41462306a36Sopenharmony_ci if (lasthut != -1) { 41562306a36Sopenharmony_ci /* do not store hut */ 41662306a36Sopenharmony_ci continue; 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci if (lastlang != -1) { 41962306a36Sopenharmony_ci /* do not store langid */ 42062306a36Sopenharmony_ci continue; 42162306a36Sopenharmony_ci } 42262306a36Sopenharmony_ci err("Product/Subclass spec without prior Vendor/Class spec at line %u", 42362306a36Sopenharmony_ci linectr); 42462306a36Sopenharmony_ci continue; 42562306a36Sopenharmony_ci } 42662306a36Sopenharmony_ci if (buf[0] == '\t' && buf[1] == '\t' && isxdigit(buf[2])) { 42762306a36Sopenharmony_ci /* protocol spec */ 42862306a36Sopenharmony_ci u = strtoul(buf+2, &cp, 16); 42962306a36Sopenharmony_ci while (isspace(*cp)) 43062306a36Sopenharmony_ci cp++; 43162306a36Sopenharmony_ci if (!*cp) { 43262306a36Sopenharmony_ci err("Invalid protocol spec at line %u", 43362306a36Sopenharmony_ci linectr); 43462306a36Sopenharmony_ci continue; 43562306a36Sopenharmony_ci } 43662306a36Sopenharmony_ci if (lastclass != -1 && lastsubclass != -1) { 43762306a36Sopenharmony_ci if (new_protocol(cp, lastclass, lastsubclass, 43862306a36Sopenharmony_ci u)) 43962306a36Sopenharmony_ci err("Duplicate protocol spec at line %u class %02x:%02x:%02x %s", 44062306a36Sopenharmony_ci linectr, lastclass, lastsubclass, 44162306a36Sopenharmony_ci u, cp); 44262306a36Sopenharmony_ci dbg("line %5u protocol %02x:%02x:%02x %s", 44362306a36Sopenharmony_ci linectr, lastclass, lastsubclass, u, cp); 44462306a36Sopenharmony_ci continue; 44562306a36Sopenharmony_ci } 44662306a36Sopenharmony_ci err("Protocol spec without prior Class and Subclass spec at line %u", 44762306a36Sopenharmony_ci linectr); 44862306a36Sopenharmony_ci continue; 44962306a36Sopenharmony_ci } 45062306a36Sopenharmony_ci if (buf[0] == 'H' && buf[1] == 'I' && 45162306a36Sopenharmony_ci buf[2] == 'D' && /*isspace(buf[3])*/ buf[3] == ' ') { 45262306a36Sopenharmony_ci continue; 45362306a36Sopenharmony_ci } 45462306a36Sopenharmony_ci if (buf[0] == 'H' && buf[1] == 'U' && 45562306a36Sopenharmony_ci buf[2] == 'T' && /*isspace(buf[3])*/ buf[3] == ' ') { 45662306a36Sopenharmony_ci lastlang = lastclass = lastvendor = lastsubclass = -1; 45762306a36Sopenharmony_ci /* 45862306a36Sopenharmony_ci * set 1 as pseudo-id to indicate that the parser is 45962306a36Sopenharmony_ci * in a `HUT' section. 46062306a36Sopenharmony_ci */ 46162306a36Sopenharmony_ci lasthut = 1; 46262306a36Sopenharmony_ci continue; 46362306a36Sopenharmony_ci } 46462306a36Sopenharmony_ci if (buf[0] == 'R' && buf[1] == ' ') 46562306a36Sopenharmony_ci continue; 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci if (buf[0] == 'V' && buf[1] == 'T') 46862306a36Sopenharmony_ci continue; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci err("Unknown line at line %u", linectr); 47162306a36Sopenharmony_ci } 47262306a36Sopenharmony_ci} 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ciint names_init(char *n) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci FILE *f; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci f = fopen(n, "r"); 48062306a36Sopenharmony_ci if (!f) 48162306a36Sopenharmony_ci return errno; 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci parse(f); 48462306a36Sopenharmony_ci fclose(f); 48562306a36Sopenharmony_ci return 0; 48662306a36Sopenharmony_ci} 487