xref: /linux/tools/usb/usbip/libsrc/names.c (revision 93df8a1ed6231727c5db94a80b1a6bd5ee67cec3)
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