1 /* 2 * names.c -- USB name database manipulation routines 3 * 4 * Copyright (C) 1999, 2000 Thomas Sailer (sailer@ife.ee.ethz.ch) 5 * 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. 10 * 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. 15 * 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. 19 * 20 * 21 * 22 * 23 * 24 * Copyright (C) 2005 Takahiro Hirofuchi 25 * - names_deinit() is added. 26 * 27 */ 28 29 #include <sys/types.h> 30 #include <sys/stat.h> 31 #include <fcntl.h> 32 #include <dirent.h> 33 #include <string.h> 34 #include <errno.h> 35 #include <stdlib.h> 36 #include <unistd.h> 37 #include <stdio.h> 38 #include <ctype.h> 39 40 #include "names.h" 41 #include "usbip_common.h" 42 43 struct vendor { 44 struct vendor *next; 45 u_int16_t vendorid; 46 char name[1]; 47 }; 48 49 struct product { 50 struct product *next; 51 u_int16_t vendorid, productid; 52 char name[1]; 53 }; 54 55 struct class { 56 struct class *next; 57 u_int8_t classid; 58 char name[1]; 59 }; 60 61 struct subclass { 62 struct subclass *next; 63 u_int8_t classid, subclassid; 64 char name[1]; 65 }; 66 67 struct protocol { 68 struct protocol *next; 69 u_int8_t classid, subclassid, protocolid; 70 char name[1]; 71 }; 72 73 struct genericstrtable { 74 struct genericstrtable *next; 75 unsigned int num; 76 char name[1]; 77 }; 78 79 80 #define HASH1 0x10 81 #define HASH2 0x02 82 #define HASHSZ 16 83 84 static unsigned int hashnum(unsigned int num) 85 { 86 unsigned int mask1 = HASH1 << 27, mask2 = HASH2 << 27; 87 88 for (; mask1 >= HASH1; mask1 >>= 1, mask2 >>= 1) 89 if (num & mask1) 90 num ^= mask2; 91 return num & (HASHSZ-1); 92 } 93 94 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, }; 100 101 const char *names_vendor(u_int16_t vendorid) 102 { 103 struct vendor *v; 104 105 v = vendors[hashnum(vendorid)]; 106 for (; v; v = v->next) 107 if (v->vendorid == vendorid) 108 return v->name; 109 return NULL; 110 } 111 112 const char *names_product(u_int16_t vendorid, u_int16_t productid) 113 { 114 struct product *p; 115 116 p = products[hashnum((vendorid << 16) | productid)]; 117 for (; p; p = p->next) 118 if (p->vendorid == vendorid && p->productid == productid) 119 return p->name; 120 return NULL; 121 } 122 123 const char *names_class(u_int8_t classid) 124 { 125 struct class *c; 126 127 c = classes[hashnum(classid)]; 128 for (; c; c = c->next) 129 if (c->classid == classid) 130 return c->name; 131 return NULL; 132 } 133 134 const char *names_subclass(u_int8_t classid, u_int8_t subclassid) 135 { 136 struct subclass *s; 137 138 s = subclasses[hashnum((classid << 8) | subclassid)]; 139 for (; s; s = s->next) 140 if (s->classid == classid && s->subclassid == subclassid) 141 return s->name; 142 return NULL; 143 } 144 145 const char *names_protocol(u_int8_t classid, u_int8_t subclassid, 146 u_int8_t protocolid) 147 { 148 struct protocol *p; 149 150 p = protocols[hashnum((classid << 16) | (subclassid << 8) 151 | protocolid)]; 152 for (; p; p = p->next) 153 if (p->classid == classid && p->subclassid == subclassid && 154 p->protocolid == protocolid) 155 return p->name; 156 return NULL; 157 } 158 159 /* add a cleanup function by takahiro */ 160 struct pool { 161 struct pool *next; 162 void *mem; 163 }; 164 165 static struct pool *pool_head; 166 167 static void *my_malloc(size_t size) 168 { 169 struct pool *p; 170 171 p = calloc(1, sizeof(struct pool)); 172 if (!p) 173 return NULL; 174 175 p->mem = calloc(1, size); 176 if (!p->mem) { 177 free(p); 178 return NULL; 179 } 180 181 p->next = pool_head; 182 pool_head = p; 183 184 return p->mem; 185 } 186 187 void names_free(void) 188 { 189 struct pool *pool; 190 191 if (!pool_head) 192 return; 193 194 for (pool = pool_head; pool != NULL; ) { 195 struct pool *tmp; 196 197 if (pool->mem) 198 free(pool->mem); 199 200 tmp = pool; 201 pool = pool->next; 202 free(tmp); 203 } 204 } 205 206 static int new_vendor(const char *name, u_int16_t vendorid) 207 { 208 struct vendor *v; 209 unsigned int h = hashnum(vendorid); 210 211 v = vendors[h]; 212 for (; v; v = v->next) 213 if (v->vendorid == vendorid) 214 return -1; 215 v = my_malloc(sizeof(struct vendor) + strlen(name)); 216 if (!v) 217 return -1; 218 strcpy(v->name, name); 219 v->vendorid = vendorid; 220 v->next = vendors[h]; 221 vendors[h] = v; 222 return 0; 223 } 224 225 static int new_product(const char *name, u_int16_t vendorid, 226 u_int16_t productid) 227 { 228 struct product *p; 229 unsigned int h = hashnum((vendorid << 16) | productid); 230 231 p = products[h]; 232 for (; p; p = p->next) 233 if (p->vendorid == vendorid && p->productid == productid) 234 return -1; 235 p = my_malloc(sizeof(struct product) + strlen(name)); 236 if (!p) 237 return -1; 238 strcpy(p->name, name); 239 p->vendorid = vendorid; 240 p->productid = productid; 241 p->next = products[h]; 242 products[h] = p; 243 return 0; 244 } 245 246 static int new_class(const char *name, u_int8_t classid) 247 { 248 struct class *c; 249 unsigned int h = hashnum(classid); 250 251 c = classes[h]; 252 for (; c; c = c->next) 253 if (c->classid == classid) 254 return -1; 255 c = my_malloc(sizeof(struct class) + strlen(name)); 256 if (!c) 257 return -1; 258 strcpy(c->name, name); 259 c->classid = classid; 260 c->next = classes[h]; 261 classes[h] = c; 262 return 0; 263 } 264 265 static int new_subclass(const char *name, u_int8_t classid, u_int8_t subclassid) 266 { 267 struct subclass *s; 268 unsigned int h = hashnum((classid << 8) | subclassid); 269 270 s = subclasses[h]; 271 for (; s; s = s->next) 272 if (s->classid == classid && s->subclassid == subclassid) 273 return -1; 274 s = my_malloc(sizeof(struct subclass) + strlen(name)); 275 if (!s) 276 return -1; 277 strcpy(s->name, name); 278 s->classid = classid; 279 s->subclassid = subclassid; 280 s->next = subclasses[h]; 281 subclasses[h] = s; 282 return 0; 283 } 284 285 static int new_protocol(const char *name, u_int8_t classid, u_int8_t subclassid, 286 u_int8_t protocolid) 287 { 288 struct protocol *p; 289 unsigned int h = hashnum((classid << 16) | (subclassid << 8) 290 | protocolid); 291 292 p = protocols[h]; 293 for (; p; p = p->next) 294 if (p->classid == classid && p->subclassid == subclassid 295 && p->protocolid == protocolid) 296 return -1; 297 p = my_malloc(sizeof(struct protocol) + strlen(name)); 298 if (!p) 299 return -1; 300 strcpy(p->name, name); 301 p->classid = classid; 302 p->subclassid = subclassid; 303 p->protocolid = protocolid; 304 p->next = protocols[h]; 305 protocols[h] = p; 306 return 0; 307 } 308 309 static void parse(FILE *f) 310 { 311 char buf[512], *cp; 312 unsigned int linectr = 0; 313 int lastvendor = -1; 314 int lastclass = -1; 315 int lastsubclass = -1; 316 int lasthut = -1; 317 int lastlang = -1; 318 unsigned int u; 319 320 while (fgets(buf, sizeof(buf), f)) { 321 linectr++; 322 /* remove line ends */ 323 cp = strchr(buf, '\r'); 324 if (cp) 325 *cp = 0; 326 cp = strchr(buf, '\n'); 327 if (cp) 328 *cp = 0; 329 if (buf[0] == '#' || !buf[0]) 330 continue; 331 cp = buf; 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])*/ 335 buf[7] == ' ') { 336 continue; 337 } 338 if (buf[0] == 'P' && buf[1] == 'H' && 339 buf[2] == 'Y' && /*isspace(buf[3])*/ buf[3] == ' ') { 340 continue; 341 } 342 if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A' && 343 buf[3] == 'S' && /*isspace(buf[4])*/ buf[4] == ' ') { 344 continue; 345 } 346 if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') { 347 lasthut = lastclass = lastvendor = lastsubclass = -1; 348 /* 349 * set 1 as pseudo-id to indicate that the parser is 350 * in a `L' section. 351 */ 352 lastlang = 1; 353 continue; 354 } 355 if (buf[0] == 'C' && /*isspace(buf[1])*/ buf[1] == ' ') { 356 /* class spec */ 357 cp = buf+2; 358 while (isspace(*cp)) 359 cp++; 360 if (!isxdigit(*cp)) { 361 err("Invalid class spec at line %u", linectr); 362 continue; 363 } 364 u = strtoul(cp, &cp, 16); 365 while (isspace(*cp)) 366 cp++; 367 if (!*cp) { 368 err("Invalid class spec at line %u", linectr); 369 continue; 370 } 371 if (new_class(cp, u)) 372 err("Duplicate class spec at line %u class %04x %s", 373 linectr, u, cp); 374 dbg("line %5u class %02x %s", linectr, u, cp); 375 lasthut = lastlang = lastvendor = lastsubclass = -1; 376 lastclass = u; 377 continue; 378 } 379 if (buf[0] == 'A' && buf[1] == 'T' && isspace(buf[2])) { 380 /* audio terminal type spec */ 381 continue; 382 } 383 if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C' 384 && isspace(buf[3])) { 385 /* HID Descriptor bCountryCode */ 386 continue; 387 } 388 if (isxdigit(*cp)) { 389 /* vendor */ 390 u = strtoul(cp, &cp, 16); 391 while (isspace(*cp)) 392 cp++; 393 if (!*cp) { 394 err("Invalid vendor spec at line %u", linectr); 395 continue; 396 } 397 if (new_vendor(cp, u)) 398 err("Duplicate vendor spec at line %u vendor %04x %s", 399 linectr, u, cp); 400 dbg("line %5u vendor %04x %s", linectr, u, cp); 401 lastvendor = u; 402 lasthut = lastlang = lastclass = lastsubclass = -1; 403 continue; 404 } 405 if (buf[0] == '\t' && isxdigit(buf[1])) { 406 /* product or subclass spec */ 407 u = strtoul(buf+1, &cp, 16); 408 while (isspace(*cp)) 409 cp++; 410 if (!*cp) { 411 err("Invalid product/subclass spec at line %u", 412 linectr); 413 continue; 414 } 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, 420 lastvendor, u, cp); 421 continue; 422 } 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, 428 lastclass, u, cp); 429 lastsubclass = u; 430 continue; 431 } 432 if (lasthut != -1) { 433 /* do not store hut */ 434 continue; 435 } 436 if (lastlang != -1) { 437 /* do not store langid */ 438 continue; 439 } 440 err("Product/Subclass spec without prior Vendor/Class spec at line %u", 441 linectr); 442 continue; 443 } 444 if (buf[0] == '\t' && buf[1] == '\t' && isxdigit(buf[2])) { 445 /* protocol spec */ 446 u = strtoul(buf+2, &cp, 16); 447 while (isspace(*cp)) 448 cp++; 449 if (!*cp) { 450 err("Invalid protocol spec at line %u", 451 linectr); 452 continue; 453 } 454 if (lastclass != -1 && lastsubclass != -1) { 455 if (new_protocol(cp, lastclass, lastsubclass, 456 u)) 457 err("Duplicate protocol spec at line %u class %02x:%02x:%02x %s", 458 linectr, lastclass, lastsubclass, 459 u, cp); 460 dbg("line %5u protocol %02x:%02x:%02x %s", 461 linectr, lastclass, lastsubclass, u, cp); 462 continue; 463 } 464 err("Protocol spec without prior Class and Subclass spec at line %u", 465 linectr); 466 continue; 467 } 468 if (buf[0] == 'H' && buf[1] == 'I' && 469 buf[2] == 'D' && /*isspace(buf[3])*/ buf[3] == ' ') { 470 continue; 471 } 472 if (buf[0] == 'H' && buf[1] == 'U' && 473 buf[2] == 'T' && /*isspace(buf[3])*/ buf[3] == ' ') { 474 lastlang = lastclass = lastvendor = lastsubclass = -1; 475 /* 476 * set 1 as pseudo-id to indicate that the parser is 477 * in a `HUT' section. 478 */ 479 lasthut = 1; 480 continue; 481 } 482 if (buf[0] == 'R' && buf[1] == ' ') 483 continue; 484 485 if (buf[0] == 'V' && buf[1] == 'T') 486 continue; 487 488 err("Unknown line at line %u", linectr); 489 } 490 } 491 492 493 int names_init(char *n) 494 { 495 FILE *f; 496 497 f = fopen(n, "r"); 498 if (!f) 499 return errno; 500 501 parse(f); 502 fclose(f); 503 return 0; 504 } 505