2 * names.c -- USB name database manipulation routines
4 * Copyright (C) 1999, 2000 Thomas Sailer (sailer@ife.ee.ethz.ch)
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.
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.
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.
24 * Copyright (C) 2005 Takahiro Hirofuchi
25 * - names_deinit() is added.
29 #include <sys/types.h>
41 #include "usbip_common.h"
51 u_int16_t vendorid
, productid
;
62 struct subclass
*next
;
63 u_int8_t classid
, subclassid
;
68 struct protocol
*next
;
69 u_int8_t classid
, subclassid
, protocolid
;
73 struct genericstrtable
{
74 struct genericstrtable
*next
;
84 static unsigned int hashnum(unsigned int num
)
86 unsigned int mask1
= HASH1
<< 27, mask2
= HASH2
<< 27;
88 for (; mask1
>= HASH1
; mask1
>>= 1, mask2
>>= 1)
91 return num
& (HASHSZ
-1);
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
, };
101 const char *names_vendor(u_int16_t vendorid
)
105 v
= vendors
[hashnum(vendorid
)];
106 for (; v
; v
= v
->next
)
107 if (v
->vendorid
== vendorid
)
112 const char *names_product(u_int16_t vendorid
, u_int16_t productid
)
116 p
= products
[hashnum((vendorid
<< 16) | productid
)];
117 for (; p
; p
= p
->next
)
118 if (p
->vendorid
== vendorid
&& p
->productid
== productid
)
123 const char *names_class(u_int8_t classid
)
127 c
= classes
[hashnum(classid
)];
128 for (; c
; c
= c
->next
)
129 if (c
->classid
== classid
)
134 const char *names_subclass(u_int8_t classid
, u_int8_t subclassid
)
138 s
= subclasses
[hashnum((classid
<< 8) | subclassid
)];
139 for (; s
; s
= s
->next
)
140 if (s
->classid
== classid
&& s
->subclassid
== subclassid
)
145 const char *names_protocol(u_int8_t classid
, u_int8_t subclassid
,
150 p
= protocols
[hashnum((classid
<< 16) | (subclassid
<< 8)
152 for (; p
; p
= p
->next
)
153 if (p
->classid
== classid
&& p
->subclassid
== subclassid
&&
154 p
->protocolid
== protocolid
)
159 /* add a cleanup function by takahiro */
165 static struct pool
*pool_head
;
167 static void *my_malloc(size_t size
)
171 p
= calloc(1, sizeof(struct pool
));
175 p
->mem
= calloc(1, size
);
187 void names_free(void)
194 for (pool
= pool_head
; pool
!= NULL
; ) {
206 static int new_vendor(const char *name
, u_int16_t vendorid
)
209 unsigned int h
= hashnum(vendorid
);
212 for (; v
; v
= v
->next
)
213 if (v
->vendorid
== vendorid
)
215 v
= my_malloc(sizeof(struct vendor
) + strlen(name
));
218 strcpy(v
->name
, name
);
219 v
->vendorid
= vendorid
;
220 v
->next
= vendors
[h
];
225 static int new_product(const char *name
, u_int16_t vendorid
,
229 unsigned int h
= hashnum((vendorid
<< 16) | productid
);
232 for (; p
; p
= p
->next
)
233 if (p
->vendorid
== vendorid
&& p
->productid
== productid
)
235 p
= my_malloc(sizeof(struct product
) + strlen(name
));
238 strcpy(p
->name
, name
);
239 p
->vendorid
= vendorid
;
240 p
->productid
= productid
;
241 p
->next
= products
[h
];
246 static int new_class(const char *name
, u_int8_t classid
)
249 unsigned int h
= hashnum(classid
);
252 for (; c
; c
= c
->next
)
253 if (c
->classid
== classid
)
255 c
= my_malloc(sizeof(struct class) + strlen(name
));
258 strcpy(c
->name
, name
);
259 c
->classid
= classid
;
260 c
->next
= classes
[h
];
265 static int new_subclass(const char *name
, u_int8_t classid
, u_int8_t subclassid
)
268 unsigned int h
= hashnum((classid
<< 8) | subclassid
);
271 for (; s
; s
= s
->next
)
272 if (s
->classid
== classid
&& s
->subclassid
== subclassid
)
274 s
= my_malloc(sizeof(struct subclass
) + strlen(name
));
277 strcpy(s
->name
, name
);
278 s
->classid
= classid
;
279 s
->subclassid
= subclassid
;
280 s
->next
= subclasses
[h
];
285 static int new_protocol(const char *name
, u_int8_t classid
, u_int8_t subclassid
,
289 unsigned int h
= hashnum((classid
<< 16) | (subclassid
<< 8)
293 for (; p
; p
= p
->next
)
294 if (p
->classid
== classid
&& p
->subclassid
== subclassid
295 && p
->protocolid
== protocolid
)
297 p
= my_malloc(sizeof(struct protocol
) + strlen(name
));
300 strcpy(p
->name
, name
);
301 p
->classid
= classid
;
302 p
->subclassid
= subclassid
;
303 p
->protocolid
= protocolid
;
304 p
->next
= protocols
[h
];
309 static void parse(FILE *f
)
312 unsigned int linectr
= 0;
315 int lastsubclass
= -1;
320 while (fgets(buf
, sizeof(buf
), f
)) {
322 /* remove line ends */
323 cp
= strchr(buf
, '\r');
326 cp
= strchr(buf
, '\n');
329 if (buf
[0] == '#' || !buf
[0])
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])*/
338 if (buf
[0] == 'P' && buf
[1] == 'H' &&
339 buf
[2] == 'Y' && /*isspace(buf[3])*/ buf
[3] == ' ') {
342 if (buf
[0] == 'B' && buf
[1] == 'I' && buf
[2] == 'A' &&
343 buf
[3] == 'S' && /*isspace(buf[4])*/ buf
[4] == ' ') {
346 if (buf
[0] == 'L' && /*isspace(buf[1])*/ buf
[1] == ' ') {
347 lasthut
= lastclass
= lastvendor
= lastsubclass
= -1;
349 * set 1 as pseudo-id to indicate that the parser is
355 if (buf
[0] == 'C' && /*isspace(buf[1])*/ buf
[1] == ' ') {
360 if (!isxdigit(*cp
)) {
361 err("Invalid class spec at line %u", linectr
);
364 u
= strtoul(cp
, &cp
, 16);
368 err("Invalid class spec at line %u", linectr
);
371 if (new_class(cp
, u
))
372 err("Duplicate class spec at line %u class %04x %s",
374 dbg("line %5u class %02x %s", linectr
, u
, cp
);
375 lasthut
= lastlang
= lastvendor
= lastsubclass
= -1;
379 if (buf
[0] == 'A' && buf
[1] == 'T' && isspace(buf
[2])) {
380 /* audio terminal type spec */
383 if (buf
[0] == 'H' && buf
[1] == 'C' && buf
[2] == 'C'
384 && isspace(buf
[3])) {
385 /* HID Descriptor bCountryCode */
390 u
= strtoul(cp
, &cp
, 16);
394 err("Invalid vendor spec at line %u", linectr
);
397 if (new_vendor(cp
, u
))
398 err("Duplicate vendor spec at line %u vendor %04x %s",
400 dbg("line %5u vendor %04x %s", linectr
, u
, cp
);
402 lasthut
= lastlang
= lastclass
= lastsubclass
= -1;
405 if (buf
[0] == '\t' && isxdigit(buf
[1])) {
406 /* product or subclass spec */
407 u
= strtoul(buf
+1, &cp
, 16);
411 err("Invalid product/subclass spec at line %u",
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
,
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
,
433 /* do not store hut */
436 if (lastlang
!= -1) {
437 /* do not store langid */
440 err("Product/Subclass spec without prior Vendor/Class spec at line %u",
444 if (buf
[0] == '\t' && buf
[1] == '\t' && isxdigit(buf
[2])) {
446 u
= strtoul(buf
+2, &cp
, 16);
450 err("Invalid protocol spec at line %u",
454 if (lastclass
!= -1 && lastsubclass
!= -1) {
455 if (new_protocol(cp
, lastclass
, lastsubclass
,
457 err("Duplicate protocol spec at line %u class %02x:%02x:%02x %s",
458 linectr
, lastclass
, lastsubclass
,
460 dbg("line %5u protocol %02x:%02x:%02x %s",
461 linectr
, lastclass
, lastsubclass
, u
, cp
);
464 err("Protocol spec without prior Class and Subclass spec at line %u",
468 if (buf
[0] == 'H' && buf
[1] == 'I' &&
469 buf
[2] == 'D' && /*isspace(buf[3])*/ buf
[3] == ' ') {
472 if (buf
[0] == 'H' && buf
[1] == 'U' &&
473 buf
[2] == 'T' && /*isspace(buf[3])*/ buf
[3] == ' ') {
474 lastlang
= lastclass
= lastvendor
= lastsubclass
= -1;
476 * set 1 as pseudo-id to indicate that the parser is
477 * in a `HUT' section.
482 if (buf
[0] == 'R' && buf
[1] == ' ')
485 if (buf
[0] == 'V' && buf
[1] == 'T')
488 err("Unknown line at line %u", linectr
);
493 int names_init(char *n
)