root/tools/usb/usbip/libsrc/names.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hashnum
  2. names_vendor
  3. names_product
  4. names_class
  5. names_subclass
  6. names_protocol
  7. my_malloc
  8. names_free
  9. new_vendor
  10. new_product
  11. new_class
  12. new_subclass
  13. new_protocol
  14. parse
  15. names_init

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

/* [<][>][^][v][top][bottom][index][help] */