Merge tag 'pci-v3.15-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaa...
[deliverable/linux.git] / drivers / staging / usbip / userspace / libsrc / names.c
CommitLineData
0945b4fe
TH
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 *
b2e02284
KK
21 *
22 *
23 *
cbb86718
KK
24 * Copyright (C) 2005 Takahiro Hirofuchi
25 * - names_deinit() is added.
b2e02284 26 *
0945b4fe
TH
27 */
28
0945b4fe
TH
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
0945b4fe 40#include "names.h"
b2e02284 41#include "usbip_common.h"
0945b4fe
TH
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
0945b4fe 73struct genericstrtable {
cbb86718
KK
74 struct genericstrtable *next;
75 unsigned int num;
76 char name[1];
0945b4fe
TH
77};
78
0945b4fe
TH
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
0945b4fe
TH
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, };
0945b4fe
TH
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
9db91e1b
KK
145const char *names_protocol(u_int8_t classid, u_int8_t subclassid,
146 u_int8_t protocolid)
0945b4fe
TH
147{
148 struct protocol *p;
149
9db91e1b
KK
150 p = protocols[hashnum((classid << 16) | (subclassid << 8)
151 | protocolid)];
0945b4fe 152 for (; p; p = p->next)
9db91e1b
KK
153 if (p->classid == classid && p->subclassid == subclassid &&
154 p->protocolid == protocolid)
0945b4fe
TH
155 return p->name;
156 return NULL;
157}
158
0945b4fe 159/* add a cleanup function by takahiro */
0945b4fe
TH
160struct pool {
161 struct pool *next;
162 void *mem;
163};
164
5af7746f 165static struct pool *pool_head;
0945b4fe
TH
166
167static void *my_malloc(size_t size)
168{
169 struct pool *p;
170
171 p = calloc(1, sizeof(struct pool));
2a7470d9 172 if (!p)
0945b4fe 173 return NULL;
0945b4fe
TH
174
175 p->mem = calloc(1, size);
2a7470d9
HS
176 if (!p->mem) {
177 free(p);
0945b4fe 178 return NULL;
2a7470d9 179 }
0945b4fe
TH
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
0945b4fe
TH
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
9db91e1b
KK
225static int new_product(const char *name, u_int16_t vendorid,
226 u_int16_t productid)
0945b4fe
TH
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
9db91e1b
KK
285static int new_protocol(const char *name, u_int8_t classid, u_int8_t subclassid,
286 u_int8_t protocolid)
0945b4fe
TH
287{
288 struct protocol *p;
9db91e1b
KK
289 unsigned int h = hashnum((classid << 16) | (subclassid << 8)
290 | protocolid);
0945b4fe
TH
291
292 p = protocols[h];
293 for (; p; p = p->next)
9db91e1b
KK
294 if (p->classid == classid && p->subclassid == subclassid
295 && p->protocolid == protocolid)
0945b4fe
TH
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
0945b4fe
TH
309static void parse(FILE *f)
310{
311 char buf[512], *cp;
312 unsigned int linectr = 0;
9db91e1b
KK
313 int lastvendor = -1;
314 int lastclass = -1;
315 int lastsubclass = -1;
316 int lasthut = -1;
317 int lastlang = -1;
0945b4fe
TH
318 unsigned int u;
319
320 while (fgets(buf, sizeof(buf), f)) {
321 linectr++;
322 /* remove line ends */
69f45263 323 cp = strchr(buf, '\r');
6f19a2b1 324 if (cp)
0945b4fe 325 *cp = 0;
69f45263 326 cp = strchr(buf, '\n');
6f19a2b1 327 if (cp)
0945b4fe
TH
328 *cp = 0;
329 if (buf[0] == '#' || !buf[0])
330 continue;
331 cp = buf;
b2e02284
KK
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] == ' ') {
cbb86718 336 continue;
cbb86718 337 }
b2e02284
KK
338 if (buf[0] == 'P' && buf[1] == 'H' &&
339 buf[2] == 'Y' && /*isspace(buf[3])*/ buf[3] == ' ') {
cbb86718 340 continue;
cbb86718 341 }
b2e02284
KK
342 if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A' &&
343 buf[3] == 'S' && /*isspace(buf[4])*/ buf[4] == ' ') {
cbb86718 344 continue;
cbb86718
KK
345 }
346 if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') {
cbb86718 347 lasthut = lastclass = lastvendor = lastsubclass = -1;
b2e02284
KK
348 /*
349 * set 1 as pseudo-id to indicate that the parser is
350 * in a `L' section.
351 */
352 lastlang = 1;
cbb86718
KK
353 continue;
354 }
0945b4fe
TH
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)) {
b2e02284 361 err("Invalid class spec at line %u", linectr);
0945b4fe
TH
362 continue;
363 }
364 u = strtoul(cp, &cp, 16);
365 while (isspace(*cp))
366 cp++;
367 if (!*cp) {
b2e02284 368 err("Invalid class spec at line %u", linectr);
0945b4fe
TH
369 continue;
370 }
371 if (new_class(cp, u))
b2e02284
KK
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);
0945b4fe
TH
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 */
0945b4fe
TH
381 continue;
382 }
9db91e1b
KK
383 if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C'
384 && isspace(buf[3])) {
0945b4fe 385 /* HID Descriptor bCountryCode */
cbb86718 386 continue;
0945b4fe
TH
387 }
388 if (isxdigit(*cp)) {
389 /* vendor */
390 u = strtoul(cp, &cp, 16);
391 while (isspace(*cp))
392 cp++;
393 if (!*cp) {
b2e02284 394 err("Invalid vendor spec at line %u", linectr);
0945b4fe
TH
395 continue;
396 }
397 if (new_vendor(cp, u))
b2e02284
KK
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);
0945b4fe
TH
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) {
b2e02284
KK
411 err("Invalid product/subclass spec at line %u",
412 linectr);
0945b4fe
TH
413 continue;
414 }
415 if (lastvendor != -1) {
416 if (new_product(cp, lastvendor, u))
b2e02284
KK
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);
0945b4fe
TH
421 continue;
422 }
423 if (lastclass != -1) {
424 if (new_subclass(cp, lastclass, u))
b2e02284
KK
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);
0945b4fe
TH
429 lastsubclass = u;
430 continue;
431 }
432 if (lasthut != -1) {
b2e02284 433 /* do not store hut */
0945b4fe
TH
434 continue;
435 }
436 if (lastlang != -1) {
b2e02284 437 /* do not store langid */
cbb86718
KK
438 continue;
439 }
b2e02284
KK
440 err("Product/Subclass spec without prior Vendor/Class spec at line %u",
441 linectr);
0945b4fe
TH
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) {
b2e02284
KK
450 err("Invalid protocol spec at line %u",
451 linectr);
0945b4fe
TH
452 continue;
453 }
454 if (lastclass != -1 && lastsubclass != -1) {
b2e02284
KK
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);
0945b4fe
TH
462 continue;
463 }
b2e02284
KK
464 err("Protocol spec without prior Class and Subclass spec at line %u",
465 linectr);
0945b4fe
TH
466 continue;
467 }
b2e02284
KK
468 if (buf[0] == 'H' && buf[1] == 'I' &&
469 buf[2] == 'D' && /*isspace(buf[3])*/ buf[3] == ' ') {
cbb86718 470 continue;
0945b4fe 471 }
b2e02284
KK
472 if (buf[0] == 'H' && buf[1] == 'U' &&
473 buf[2] == 'T' && /*isspace(buf[3])*/ buf[3] == ' ') {
0945b4fe 474 lastlang = lastclass = lastvendor = lastsubclass = -1;
b2e02284
KK
475 /*
476 * set 1 as pseudo-id to indicate that the parser is
477 * in a `HUT' section.
478 */
479 lasthut = 1;
cbb86718 480 continue;
cbb86718 481 }
b2e02284 482 if (buf[0] == 'R' && buf[1] == ' ')
cbb86718
KK
483 continue;
484
b2e02284 485 if (buf[0] == 'V' && buf[1] == 'T')
0945b4fe 486 continue;
b2e02284
KK
487
488 err("Unknown line at line %u", linectr);
0945b4fe
TH
489 }
490}
491
0945b4fe
TH
492
493int names_init(char *n)
494{
495 FILE *f;
496
6f19a2b1
KK
497 f = fopen(n, "r");
498 if (!f)
0945b4fe 499 return errno;
6f19a2b1 500
0945b4fe
TH
501 parse(f);
502 fclose(f);
503 return 0;
504}
This page took 0.284976 seconds and 5 git commands to generate.