Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/usb/usbip/libsrc/names.c
26295 views
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 ([email protected])
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
}
487
488