18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * names.c -- USB name database manipulation routines 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 1999, 2000 Thomas Sailer (sailer@ife.ee.ethz.ch) 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) 2005 Takahiro Hirofuchi 88c2ecf20Sopenharmony_ci * - names_deinit() is added. 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <sys/types.h> 128c2ecf20Sopenharmony_ci#include <sys/stat.h> 138c2ecf20Sopenharmony_ci#include <fcntl.h> 148c2ecf20Sopenharmony_ci#include <dirent.h> 158c2ecf20Sopenharmony_ci#include <string.h> 168c2ecf20Sopenharmony_ci#include <errno.h> 178c2ecf20Sopenharmony_ci#include <stdlib.h> 188c2ecf20Sopenharmony_ci#include <unistd.h> 198c2ecf20Sopenharmony_ci#include <stdio.h> 208c2ecf20Sopenharmony_ci#include <ctype.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include "names.h" 238c2ecf20Sopenharmony_ci#include "usbip_common.h" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistruct vendor { 268c2ecf20Sopenharmony_ci struct vendor *next; 278c2ecf20Sopenharmony_ci u_int16_t vendorid; 288c2ecf20Sopenharmony_ci char name[1]; 298c2ecf20Sopenharmony_ci}; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistruct product { 328c2ecf20Sopenharmony_ci struct product *next; 338c2ecf20Sopenharmony_ci u_int16_t vendorid, productid; 348c2ecf20Sopenharmony_ci char name[1]; 358c2ecf20Sopenharmony_ci}; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistruct class { 388c2ecf20Sopenharmony_ci struct class *next; 398c2ecf20Sopenharmony_ci u_int8_t classid; 408c2ecf20Sopenharmony_ci char name[1]; 418c2ecf20Sopenharmony_ci}; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistruct subclass { 448c2ecf20Sopenharmony_ci struct subclass *next; 458c2ecf20Sopenharmony_ci u_int8_t classid, subclassid; 468c2ecf20Sopenharmony_ci char name[1]; 478c2ecf20Sopenharmony_ci}; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistruct protocol { 508c2ecf20Sopenharmony_ci struct protocol *next; 518c2ecf20Sopenharmony_ci u_int8_t classid, subclassid, protocolid; 528c2ecf20Sopenharmony_ci char name[1]; 538c2ecf20Sopenharmony_ci}; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistruct genericstrtable { 568c2ecf20Sopenharmony_ci struct genericstrtable *next; 578c2ecf20Sopenharmony_ci unsigned int num; 588c2ecf20Sopenharmony_ci char name[1]; 598c2ecf20Sopenharmony_ci}; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#define HASH1 0x10 638c2ecf20Sopenharmony_ci#define HASH2 0x02 648c2ecf20Sopenharmony_ci#define HASHSZ 16 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_cistatic unsigned int hashnum(unsigned int num) 678c2ecf20Sopenharmony_ci{ 688c2ecf20Sopenharmony_ci unsigned int mask1 = HASH1 << 27, mask2 = HASH2 << 27; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci for (; mask1 >= HASH1; mask1 >>= 1, mask2 >>= 1) 718c2ecf20Sopenharmony_ci if (num & mask1) 728c2ecf20Sopenharmony_ci num ^= mask2; 738c2ecf20Sopenharmony_ci return num & (HASHSZ-1); 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cistatic struct vendor *vendors[HASHSZ] = { NULL, }; 788c2ecf20Sopenharmony_cistatic struct product *products[HASHSZ] = { NULL, }; 798c2ecf20Sopenharmony_cistatic struct class *classes[HASHSZ] = { NULL, }; 808c2ecf20Sopenharmony_cistatic struct subclass *subclasses[HASHSZ] = { NULL, }; 818c2ecf20Sopenharmony_cistatic struct protocol *protocols[HASHSZ] = { NULL, }; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ciconst char *names_vendor(u_int16_t vendorid) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci struct vendor *v; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci v = vendors[hashnum(vendorid)]; 888c2ecf20Sopenharmony_ci for (; v; v = v->next) 898c2ecf20Sopenharmony_ci if (v->vendorid == vendorid) 908c2ecf20Sopenharmony_ci return v->name; 918c2ecf20Sopenharmony_ci return NULL; 928c2ecf20Sopenharmony_ci} 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ciconst char *names_product(u_int16_t vendorid, u_int16_t productid) 958c2ecf20Sopenharmony_ci{ 968c2ecf20Sopenharmony_ci struct product *p; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci p = products[hashnum((vendorid << 16) | productid)]; 998c2ecf20Sopenharmony_ci for (; p; p = p->next) 1008c2ecf20Sopenharmony_ci if (p->vendorid == vendorid && p->productid == productid) 1018c2ecf20Sopenharmony_ci return p->name; 1028c2ecf20Sopenharmony_ci return NULL; 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ciconst char *names_class(u_int8_t classid) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci struct class *c; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci c = classes[hashnum(classid)]; 1108c2ecf20Sopenharmony_ci for (; c; c = c->next) 1118c2ecf20Sopenharmony_ci if (c->classid == classid) 1128c2ecf20Sopenharmony_ci return c->name; 1138c2ecf20Sopenharmony_ci return NULL; 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ciconst char *names_subclass(u_int8_t classid, u_int8_t subclassid) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci struct subclass *s; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci s = subclasses[hashnum((classid << 8) | subclassid)]; 1218c2ecf20Sopenharmony_ci for (; s; s = s->next) 1228c2ecf20Sopenharmony_ci if (s->classid == classid && s->subclassid == subclassid) 1238c2ecf20Sopenharmony_ci return s->name; 1248c2ecf20Sopenharmony_ci return NULL; 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ciconst char *names_protocol(u_int8_t classid, u_int8_t subclassid, 1288c2ecf20Sopenharmony_ci u_int8_t protocolid) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci struct protocol *p; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci p = protocols[hashnum((classid << 16) | (subclassid << 8) 1338c2ecf20Sopenharmony_ci | protocolid)]; 1348c2ecf20Sopenharmony_ci for (; p; p = p->next) 1358c2ecf20Sopenharmony_ci if (p->classid == classid && p->subclassid == subclassid && 1368c2ecf20Sopenharmony_ci p->protocolid == protocolid) 1378c2ecf20Sopenharmony_ci return p->name; 1388c2ecf20Sopenharmony_ci return NULL; 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci/* add a cleanup function by takahiro */ 1428c2ecf20Sopenharmony_cistruct pool { 1438c2ecf20Sopenharmony_ci struct pool *next; 1448c2ecf20Sopenharmony_ci void *mem; 1458c2ecf20Sopenharmony_ci}; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cistatic struct pool *pool_head; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic void *my_malloc(size_t size) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci struct pool *p; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci p = calloc(1, sizeof(struct pool)); 1548c2ecf20Sopenharmony_ci if (!p) 1558c2ecf20Sopenharmony_ci return NULL; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci p->mem = calloc(1, size); 1588c2ecf20Sopenharmony_ci if (!p->mem) { 1598c2ecf20Sopenharmony_ci free(p); 1608c2ecf20Sopenharmony_ci return NULL; 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci p->next = pool_head; 1648c2ecf20Sopenharmony_ci pool_head = p; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci return p->mem; 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_civoid names_free(void) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci struct pool *pool; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci if (!pool_head) 1748c2ecf20Sopenharmony_ci return; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci for (pool = pool_head; pool != NULL; ) { 1778c2ecf20Sopenharmony_ci struct pool *tmp; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci if (pool->mem) 1808c2ecf20Sopenharmony_ci free(pool->mem); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci tmp = pool; 1838c2ecf20Sopenharmony_ci pool = pool->next; 1848c2ecf20Sopenharmony_ci free(tmp); 1858c2ecf20Sopenharmony_ci } 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic int new_vendor(const char *name, u_int16_t vendorid) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci struct vendor *v; 1918c2ecf20Sopenharmony_ci unsigned int h = hashnum(vendorid); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci v = vendors[h]; 1948c2ecf20Sopenharmony_ci for (; v; v = v->next) 1958c2ecf20Sopenharmony_ci if (v->vendorid == vendorid) 1968c2ecf20Sopenharmony_ci return -1; 1978c2ecf20Sopenharmony_ci v = my_malloc(sizeof(struct vendor) + strlen(name)); 1988c2ecf20Sopenharmony_ci if (!v) 1998c2ecf20Sopenharmony_ci return -1; 2008c2ecf20Sopenharmony_ci strcpy(v->name, name); 2018c2ecf20Sopenharmony_ci v->vendorid = vendorid; 2028c2ecf20Sopenharmony_ci v->next = vendors[h]; 2038c2ecf20Sopenharmony_ci vendors[h] = v; 2048c2ecf20Sopenharmony_ci return 0; 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_cistatic int new_product(const char *name, u_int16_t vendorid, 2088c2ecf20Sopenharmony_ci u_int16_t productid) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci struct product *p; 2118c2ecf20Sopenharmony_ci unsigned int h = hashnum((vendorid << 16) | productid); 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci p = products[h]; 2148c2ecf20Sopenharmony_ci for (; p; p = p->next) 2158c2ecf20Sopenharmony_ci if (p->vendorid == vendorid && p->productid == productid) 2168c2ecf20Sopenharmony_ci return -1; 2178c2ecf20Sopenharmony_ci p = my_malloc(sizeof(struct product) + strlen(name)); 2188c2ecf20Sopenharmony_ci if (!p) 2198c2ecf20Sopenharmony_ci return -1; 2208c2ecf20Sopenharmony_ci strcpy(p->name, name); 2218c2ecf20Sopenharmony_ci p->vendorid = vendorid; 2228c2ecf20Sopenharmony_ci p->productid = productid; 2238c2ecf20Sopenharmony_ci p->next = products[h]; 2248c2ecf20Sopenharmony_ci products[h] = p; 2258c2ecf20Sopenharmony_ci return 0; 2268c2ecf20Sopenharmony_ci} 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_cistatic int new_class(const char *name, u_int8_t classid) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci struct class *c; 2318c2ecf20Sopenharmony_ci unsigned int h = hashnum(classid); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci c = classes[h]; 2348c2ecf20Sopenharmony_ci for (; c; c = c->next) 2358c2ecf20Sopenharmony_ci if (c->classid == classid) 2368c2ecf20Sopenharmony_ci return -1; 2378c2ecf20Sopenharmony_ci c = my_malloc(sizeof(struct class) + strlen(name)); 2388c2ecf20Sopenharmony_ci if (!c) 2398c2ecf20Sopenharmony_ci return -1; 2408c2ecf20Sopenharmony_ci strcpy(c->name, name); 2418c2ecf20Sopenharmony_ci c->classid = classid; 2428c2ecf20Sopenharmony_ci c->next = classes[h]; 2438c2ecf20Sopenharmony_ci classes[h] = c; 2448c2ecf20Sopenharmony_ci return 0; 2458c2ecf20Sopenharmony_ci} 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_cistatic int new_subclass(const char *name, u_int8_t classid, u_int8_t subclassid) 2488c2ecf20Sopenharmony_ci{ 2498c2ecf20Sopenharmony_ci struct subclass *s; 2508c2ecf20Sopenharmony_ci unsigned int h = hashnum((classid << 8) | subclassid); 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci s = subclasses[h]; 2538c2ecf20Sopenharmony_ci for (; s; s = s->next) 2548c2ecf20Sopenharmony_ci if (s->classid == classid && s->subclassid == subclassid) 2558c2ecf20Sopenharmony_ci return -1; 2568c2ecf20Sopenharmony_ci s = my_malloc(sizeof(struct subclass) + strlen(name)); 2578c2ecf20Sopenharmony_ci if (!s) 2588c2ecf20Sopenharmony_ci return -1; 2598c2ecf20Sopenharmony_ci strcpy(s->name, name); 2608c2ecf20Sopenharmony_ci s->classid = classid; 2618c2ecf20Sopenharmony_ci s->subclassid = subclassid; 2628c2ecf20Sopenharmony_ci s->next = subclasses[h]; 2638c2ecf20Sopenharmony_ci subclasses[h] = s; 2648c2ecf20Sopenharmony_ci return 0; 2658c2ecf20Sopenharmony_ci} 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_cistatic int new_protocol(const char *name, u_int8_t classid, u_int8_t subclassid, 2688c2ecf20Sopenharmony_ci u_int8_t protocolid) 2698c2ecf20Sopenharmony_ci{ 2708c2ecf20Sopenharmony_ci struct protocol *p; 2718c2ecf20Sopenharmony_ci unsigned int h = hashnum((classid << 16) | (subclassid << 8) 2728c2ecf20Sopenharmony_ci | protocolid); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci p = protocols[h]; 2758c2ecf20Sopenharmony_ci for (; p; p = p->next) 2768c2ecf20Sopenharmony_ci if (p->classid == classid && p->subclassid == subclassid 2778c2ecf20Sopenharmony_ci && p->protocolid == protocolid) 2788c2ecf20Sopenharmony_ci return -1; 2798c2ecf20Sopenharmony_ci p = my_malloc(sizeof(struct protocol) + strlen(name)); 2808c2ecf20Sopenharmony_ci if (!p) 2818c2ecf20Sopenharmony_ci return -1; 2828c2ecf20Sopenharmony_ci strcpy(p->name, name); 2838c2ecf20Sopenharmony_ci p->classid = classid; 2848c2ecf20Sopenharmony_ci p->subclassid = subclassid; 2858c2ecf20Sopenharmony_ci p->protocolid = protocolid; 2868c2ecf20Sopenharmony_ci p->next = protocols[h]; 2878c2ecf20Sopenharmony_ci protocols[h] = p; 2888c2ecf20Sopenharmony_ci return 0; 2898c2ecf20Sopenharmony_ci} 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_cistatic void parse(FILE *f) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci char buf[512], *cp; 2948c2ecf20Sopenharmony_ci unsigned int linectr = 0; 2958c2ecf20Sopenharmony_ci int lastvendor = -1; 2968c2ecf20Sopenharmony_ci int lastclass = -1; 2978c2ecf20Sopenharmony_ci int lastsubclass = -1; 2988c2ecf20Sopenharmony_ci int lasthut = -1; 2998c2ecf20Sopenharmony_ci int lastlang = -1; 3008c2ecf20Sopenharmony_ci unsigned int u; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci while (fgets(buf, sizeof(buf), f)) { 3038c2ecf20Sopenharmony_ci linectr++; 3048c2ecf20Sopenharmony_ci /* remove line ends */ 3058c2ecf20Sopenharmony_ci cp = strchr(buf, '\r'); 3068c2ecf20Sopenharmony_ci if (cp) 3078c2ecf20Sopenharmony_ci *cp = 0; 3088c2ecf20Sopenharmony_ci cp = strchr(buf, '\n'); 3098c2ecf20Sopenharmony_ci if (cp) 3108c2ecf20Sopenharmony_ci *cp = 0; 3118c2ecf20Sopenharmony_ci if (buf[0] == '#' || !buf[0]) 3128c2ecf20Sopenharmony_ci continue; 3138c2ecf20Sopenharmony_ci cp = buf; 3148c2ecf20Sopenharmony_ci if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' && 3158c2ecf20Sopenharmony_ci buf[3] == 'S' && buf[4] == 'D' && 3168c2ecf20Sopenharmony_ci buf[5] == 'E' && buf[6] == 'S' && /*isspace(buf[7])*/ 3178c2ecf20Sopenharmony_ci buf[7] == ' ') { 3188c2ecf20Sopenharmony_ci continue; 3198c2ecf20Sopenharmony_ci } 3208c2ecf20Sopenharmony_ci if (buf[0] == 'P' && buf[1] == 'H' && 3218c2ecf20Sopenharmony_ci buf[2] == 'Y' && /*isspace(buf[3])*/ buf[3] == ' ') { 3228c2ecf20Sopenharmony_ci continue; 3238c2ecf20Sopenharmony_ci } 3248c2ecf20Sopenharmony_ci if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A' && 3258c2ecf20Sopenharmony_ci buf[3] == 'S' && /*isspace(buf[4])*/ buf[4] == ' ') { 3268c2ecf20Sopenharmony_ci continue; 3278c2ecf20Sopenharmony_ci } 3288c2ecf20Sopenharmony_ci if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') { 3298c2ecf20Sopenharmony_ci lasthut = lastclass = lastvendor = lastsubclass = -1; 3308c2ecf20Sopenharmony_ci /* 3318c2ecf20Sopenharmony_ci * set 1 as pseudo-id to indicate that the parser is 3328c2ecf20Sopenharmony_ci * in a `L' section. 3338c2ecf20Sopenharmony_ci */ 3348c2ecf20Sopenharmony_ci lastlang = 1; 3358c2ecf20Sopenharmony_ci continue; 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci if (buf[0] == 'C' && /*isspace(buf[1])*/ buf[1] == ' ') { 3388c2ecf20Sopenharmony_ci /* class spec */ 3398c2ecf20Sopenharmony_ci cp = buf+2; 3408c2ecf20Sopenharmony_ci while (isspace(*cp)) 3418c2ecf20Sopenharmony_ci cp++; 3428c2ecf20Sopenharmony_ci if (!isxdigit(*cp)) { 3438c2ecf20Sopenharmony_ci err("Invalid class spec at line %u", linectr); 3448c2ecf20Sopenharmony_ci continue; 3458c2ecf20Sopenharmony_ci } 3468c2ecf20Sopenharmony_ci u = strtoul(cp, &cp, 16); 3478c2ecf20Sopenharmony_ci while (isspace(*cp)) 3488c2ecf20Sopenharmony_ci cp++; 3498c2ecf20Sopenharmony_ci if (!*cp) { 3508c2ecf20Sopenharmony_ci err("Invalid class spec at line %u", linectr); 3518c2ecf20Sopenharmony_ci continue; 3528c2ecf20Sopenharmony_ci } 3538c2ecf20Sopenharmony_ci if (new_class(cp, u)) 3548c2ecf20Sopenharmony_ci err("Duplicate class spec at line %u class %04x %s", 3558c2ecf20Sopenharmony_ci linectr, u, cp); 3568c2ecf20Sopenharmony_ci dbg("line %5u class %02x %s", linectr, u, cp); 3578c2ecf20Sopenharmony_ci lasthut = lastlang = lastvendor = lastsubclass = -1; 3588c2ecf20Sopenharmony_ci lastclass = u; 3598c2ecf20Sopenharmony_ci continue; 3608c2ecf20Sopenharmony_ci } 3618c2ecf20Sopenharmony_ci if (buf[0] == 'A' && buf[1] == 'T' && isspace(buf[2])) { 3628c2ecf20Sopenharmony_ci /* audio terminal type spec */ 3638c2ecf20Sopenharmony_ci continue; 3648c2ecf20Sopenharmony_ci } 3658c2ecf20Sopenharmony_ci if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C' 3668c2ecf20Sopenharmony_ci && isspace(buf[3])) { 3678c2ecf20Sopenharmony_ci /* HID Descriptor bCountryCode */ 3688c2ecf20Sopenharmony_ci continue; 3698c2ecf20Sopenharmony_ci } 3708c2ecf20Sopenharmony_ci if (isxdigit(*cp)) { 3718c2ecf20Sopenharmony_ci /* vendor */ 3728c2ecf20Sopenharmony_ci u = strtoul(cp, &cp, 16); 3738c2ecf20Sopenharmony_ci while (isspace(*cp)) 3748c2ecf20Sopenharmony_ci cp++; 3758c2ecf20Sopenharmony_ci if (!*cp) { 3768c2ecf20Sopenharmony_ci err("Invalid vendor spec at line %u", linectr); 3778c2ecf20Sopenharmony_ci continue; 3788c2ecf20Sopenharmony_ci } 3798c2ecf20Sopenharmony_ci if (new_vendor(cp, u)) 3808c2ecf20Sopenharmony_ci err("Duplicate vendor spec at line %u vendor %04x %s", 3818c2ecf20Sopenharmony_ci linectr, u, cp); 3828c2ecf20Sopenharmony_ci dbg("line %5u vendor %04x %s", linectr, u, cp); 3838c2ecf20Sopenharmony_ci lastvendor = u; 3848c2ecf20Sopenharmony_ci lasthut = lastlang = lastclass = lastsubclass = -1; 3858c2ecf20Sopenharmony_ci continue; 3868c2ecf20Sopenharmony_ci } 3878c2ecf20Sopenharmony_ci if (buf[0] == '\t' && isxdigit(buf[1])) { 3888c2ecf20Sopenharmony_ci /* product or subclass spec */ 3898c2ecf20Sopenharmony_ci u = strtoul(buf+1, &cp, 16); 3908c2ecf20Sopenharmony_ci while (isspace(*cp)) 3918c2ecf20Sopenharmony_ci cp++; 3928c2ecf20Sopenharmony_ci if (!*cp) { 3938c2ecf20Sopenharmony_ci err("Invalid product/subclass spec at line %u", 3948c2ecf20Sopenharmony_ci linectr); 3958c2ecf20Sopenharmony_ci continue; 3968c2ecf20Sopenharmony_ci } 3978c2ecf20Sopenharmony_ci if (lastvendor != -1) { 3988c2ecf20Sopenharmony_ci if (new_product(cp, lastvendor, u)) 3998c2ecf20Sopenharmony_ci err("Duplicate product spec at line %u product %04x:%04x %s", 4008c2ecf20Sopenharmony_ci linectr, lastvendor, u, cp); 4018c2ecf20Sopenharmony_ci dbg("line %5u product %04x:%04x %s", linectr, 4028c2ecf20Sopenharmony_ci lastvendor, u, cp); 4038c2ecf20Sopenharmony_ci continue; 4048c2ecf20Sopenharmony_ci } 4058c2ecf20Sopenharmony_ci if (lastclass != -1) { 4068c2ecf20Sopenharmony_ci if (new_subclass(cp, lastclass, u)) 4078c2ecf20Sopenharmony_ci err("Duplicate subclass spec at line %u class %02x:%02x %s", 4088c2ecf20Sopenharmony_ci linectr, lastclass, u, cp); 4098c2ecf20Sopenharmony_ci dbg("line %5u subclass %02x:%02x %s", linectr, 4108c2ecf20Sopenharmony_ci lastclass, u, cp); 4118c2ecf20Sopenharmony_ci lastsubclass = u; 4128c2ecf20Sopenharmony_ci continue; 4138c2ecf20Sopenharmony_ci } 4148c2ecf20Sopenharmony_ci if (lasthut != -1) { 4158c2ecf20Sopenharmony_ci /* do not store hut */ 4168c2ecf20Sopenharmony_ci continue; 4178c2ecf20Sopenharmony_ci } 4188c2ecf20Sopenharmony_ci if (lastlang != -1) { 4198c2ecf20Sopenharmony_ci /* do not store langid */ 4208c2ecf20Sopenharmony_ci continue; 4218c2ecf20Sopenharmony_ci } 4228c2ecf20Sopenharmony_ci err("Product/Subclass spec without prior Vendor/Class spec at line %u", 4238c2ecf20Sopenharmony_ci linectr); 4248c2ecf20Sopenharmony_ci continue; 4258c2ecf20Sopenharmony_ci } 4268c2ecf20Sopenharmony_ci if (buf[0] == '\t' && buf[1] == '\t' && isxdigit(buf[2])) { 4278c2ecf20Sopenharmony_ci /* protocol spec */ 4288c2ecf20Sopenharmony_ci u = strtoul(buf+2, &cp, 16); 4298c2ecf20Sopenharmony_ci while (isspace(*cp)) 4308c2ecf20Sopenharmony_ci cp++; 4318c2ecf20Sopenharmony_ci if (!*cp) { 4328c2ecf20Sopenharmony_ci err("Invalid protocol spec at line %u", 4338c2ecf20Sopenharmony_ci linectr); 4348c2ecf20Sopenharmony_ci continue; 4358c2ecf20Sopenharmony_ci } 4368c2ecf20Sopenharmony_ci if (lastclass != -1 && lastsubclass != -1) { 4378c2ecf20Sopenharmony_ci if (new_protocol(cp, lastclass, lastsubclass, 4388c2ecf20Sopenharmony_ci u)) 4398c2ecf20Sopenharmony_ci err("Duplicate protocol spec at line %u class %02x:%02x:%02x %s", 4408c2ecf20Sopenharmony_ci linectr, lastclass, lastsubclass, 4418c2ecf20Sopenharmony_ci u, cp); 4428c2ecf20Sopenharmony_ci dbg("line %5u protocol %02x:%02x:%02x %s", 4438c2ecf20Sopenharmony_ci linectr, lastclass, lastsubclass, u, cp); 4448c2ecf20Sopenharmony_ci continue; 4458c2ecf20Sopenharmony_ci } 4468c2ecf20Sopenharmony_ci err("Protocol spec without prior Class and Subclass spec at line %u", 4478c2ecf20Sopenharmony_ci linectr); 4488c2ecf20Sopenharmony_ci continue; 4498c2ecf20Sopenharmony_ci } 4508c2ecf20Sopenharmony_ci if (buf[0] == 'H' && buf[1] == 'I' && 4518c2ecf20Sopenharmony_ci buf[2] == 'D' && /*isspace(buf[3])*/ buf[3] == ' ') { 4528c2ecf20Sopenharmony_ci continue; 4538c2ecf20Sopenharmony_ci } 4548c2ecf20Sopenharmony_ci if (buf[0] == 'H' && buf[1] == 'U' && 4558c2ecf20Sopenharmony_ci buf[2] == 'T' && /*isspace(buf[3])*/ buf[3] == ' ') { 4568c2ecf20Sopenharmony_ci lastlang = lastclass = lastvendor = lastsubclass = -1; 4578c2ecf20Sopenharmony_ci /* 4588c2ecf20Sopenharmony_ci * set 1 as pseudo-id to indicate that the parser is 4598c2ecf20Sopenharmony_ci * in a `HUT' section. 4608c2ecf20Sopenharmony_ci */ 4618c2ecf20Sopenharmony_ci lasthut = 1; 4628c2ecf20Sopenharmony_ci continue; 4638c2ecf20Sopenharmony_ci } 4648c2ecf20Sopenharmony_ci if (buf[0] == 'R' && buf[1] == ' ') 4658c2ecf20Sopenharmony_ci continue; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci if (buf[0] == 'V' && buf[1] == 'T') 4688c2ecf20Sopenharmony_ci continue; 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci err("Unknown line at line %u", linectr); 4718c2ecf20Sopenharmony_ci } 4728c2ecf20Sopenharmony_ci} 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ciint names_init(char *n) 4768c2ecf20Sopenharmony_ci{ 4778c2ecf20Sopenharmony_ci FILE *f; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci f = fopen(n, "r"); 4808c2ecf20Sopenharmony_ci if (!f) 4818c2ecf20Sopenharmony_ci return errno; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci parse(f); 4848c2ecf20Sopenharmony_ci fclose(f); 4858c2ecf20Sopenharmony_ci return 0; 4868c2ecf20Sopenharmony_ci} 487