linux/drivers/staging/usbip/userspace/libsrc/names.c
<<
>>
Prefs
   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
  43struct vendor {
  44        struct vendor *next;
  45        u_int16_t vendorid;
  46        char name[1];
  47};
  48
  49struct product {
  50        struct product *next;
  51        u_int16_t vendorid, productid;
  52        char name[1];
  53};
  54
  55struct class {
  56        struct class *next;
  57        u_int8_t classid;
  58        char name[1];
  59};
  60
  61struct subclass {
  62        struct subclass *next;
  63        u_int8_t classid, subclassid;
  64        char name[1];
  65};
  66
  67struct protocol {
  68        struct protocol *next;
  69        u_int8_t classid, subclassid, protocolid;
  70        char name[1];
  71};
  72
  73struct 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
  84static 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
  95static struct vendor *vendors[HASHSZ] = { NULL, };
  96static struct product *products[HASHSZ] = { NULL, };
  97static struct class *classes[HASHSZ] = { NULL, };
  98static struct subclass *subclasses[HASHSZ] = { NULL, };
  99static struct protocol *protocols[HASHSZ] = { NULL, };
 100
 101const 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
 112const 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
 123const 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
 134const 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
 145const 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 */
 160struct pool {
 161        struct pool *next;
 162        void *mem;
 163};
 164
 165static struct pool *pool_head;
 166
 167static 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
 187void 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
 206static 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
 225static 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
 246static 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
 265static 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
 285static 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
 309static 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
 493int 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