ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/linux/tools/usb/usbip/libsrc/names.c b/marvell/linux/tools/usb/usbip/libsrc/names.c
new file mode 100644
index 0000000..aba7f41
--- /dev/null
+++ b/marvell/linux/tools/usb/usbip/libsrc/names.c
@@ -0,0 +1,486 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *      names.c  --  USB name database manipulation routines
+ *
+ *      Copyright (C) 1999, 2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ *	Copyright (C) 2005 Takahiro Hirofuchi
+ *		- names_deinit() is added.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "names.h"
+#include "usbip_common.h"
+
+struct vendor {
+	struct vendor *next;
+	u_int16_t vendorid;
+	char name[1];
+};
+
+struct product {
+	struct product *next;
+	u_int16_t vendorid, productid;
+	char name[1];
+};
+
+struct class {
+	struct class *next;
+	u_int8_t classid;
+	char name[1];
+};
+
+struct subclass {
+	struct subclass *next;
+	u_int8_t classid, subclassid;
+	char name[1];
+};
+
+struct protocol {
+	struct protocol *next;
+	u_int8_t classid, subclassid, protocolid;
+	char name[1];
+};
+
+struct genericstrtable {
+	struct genericstrtable *next;
+	unsigned int num;
+	char name[1];
+};
+
+
+#define HASH1  0x10
+#define HASH2  0x02
+#define HASHSZ 16
+
+static unsigned int hashnum(unsigned int num)
+{
+	unsigned int mask1 = HASH1 << 27, mask2 = HASH2 << 27;
+
+	for (; mask1 >= HASH1; mask1 >>= 1, mask2 >>= 1)
+		if (num & mask1)
+			num ^= mask2;
+	return num & (HASHSZ-1);
+}
+
+
+static struct vendor *vendors[HASHSZ] = { NULL, };
+static struct product *products[HASHSZ] = { NULL, };
+static struct class *classes[HASHSZ] = { NULL, };
+static struct subclass *subclasses[HASHSZ] = { NULL, };
+static struct protocol *protocols[HASHSZ] = { NULL, };
+
+const char *names_vendor(u_int16_t vendorid)
+{
+	struct vendor *v;
+
+	v = vendors[hashnum(vendorid)];
+	for (; v; v = v->next)
+		if (v->vendorid == vendorid)
+			return v->name;
+	return NULL;
+}
+
+const char *names_product(u_int16_t vendorid, u_int16_t productid)
+{
+	struct product *p;
+
+	p = products[hashnum((vendorid << 16) | productid)];
+	for (; p; p = p->next)
+		if (p->vendorid == vendorid && p->productid == productid)
+			return p->name;
+	return NULL;
+}
+
+const char *names_class(u_int8_t classid)
+{
+	struct class *c;
+
+	c = classes[hashnum(classid)];
+	for (; c; c = c->next)
+		if (c->classid == classid)
+			return c->name;
+	return NULL;
+}
+
+const char *names_subclass(u_int8_t classid, u_int8_t subclassid)
+{
+	struct subclass *s;
+
+	s = subclasses[hashnum((classid << 8) | subclassid)];
+	for (; s; s = s->next)
+		if (s->classid == classid && s->subclassid == subclassid)
+			return s->name;
+	return NULL;
+}
+
+const char *names_protocol(u_int8_t classid, u_int8_t subclassid,
+			   u_int8_t protocolid)
+{
+	struct protocol *p;
+
+	p = protocols[hashnum((classid << 16) | (subclassid << 8)
+			      | protocolid)];
+	for (; p; p = p->next)
+		if (p->classid == classid && p->subclassid == subclassid &&
+		    p->protocolid == protocolid)
+			return p->name;
+	return NULL;
+}
+
+/* add a cleanup function by takahiro */
+struct pool {
+	struct pool *next;
+	void *mem;
+};
+
+static struct pool *pool_head;
+
+static void *my_malloc(size_t size)
+{
+	struct pool *p;
+
+	p = calloc(1, sizeof(struct pool));
+	if (!p)
+		return NULL;
+
+	p->mem = calloc(1, size);
+	if (!p->mem) {
+		free(p);
+		return NULL;
+	}
+
+	p->next = pool_head;
+	pool_head = p;
+
+	return p->mem;
+}
+
+void names_free(void)
+{
+	struct pool *pool;
+
+	if (!pool_head)
+		return;
+
+	for (pool = pool_head; pool != NULL; ) {
+		struct pool *tmp;
+
+		if (pool->mem)
+			free(pool->mem);
+
+		tmp = pool;
+		pool = pool->next;
+		free(tmp);
+	}
+}
+
+static int new_vendor(const char *name, u_int16_t vendorid)
+{
+	struct vendor *v;
+	unsigned int h = hashnum(vendorid);
+
+	v = vendors[h];
+	for (; v; v = v->next)
+		if (v->vendorid == vendorid)
+			return -1;
+	v = my_malloc(sizeof(struct vendor) + strlen(name));
+	if (!v)
+		return -1;
+	strcpy(v->name, name);
+	v->vendorid = vendorid;
+	v->next = vendors[h];
+	vendors[h] = v;
+	return 0;
+}
+
+static int new_product(const char *name, u_int16_t vendorid,
+		       u_int16_t productid)
+{
+	struct product *p;
+	unsigned int h = hashnum((vendorid << 16) | productid);
+
+	p = products[h];
+	for (; p; p = p->next)
+		if (p->vendorid == vendorid && p->productid == productid)
+			return -1;
+	p = my_malloc(sizeof(struct product) + strlen(name));
+	if (!p)
+		return -1;
+	strcpy(p->name, name);
+	p->vendorid = vendorid;
+	p->productid = productid;
+	p->next = products[h];
+	products[h] = p;
+	return 0;
+}
+
+static int new_class(const char *name, u_int8_t classid)
+{
+	struct class *c;
+	unsigned int h = hashnum(classid);
+
+	c = classes[h];
+	for (; c; c = c->next)
+		if (c->classid == classid)
+			return -1;
+	c = my_malloc(sizeof(struct class) + strlen(name));
+	if (!c)
+		return -1;
+	strcpy(c->name, name);
+	c->classid = classid;
+	c->next = classes[h];
+	classes[h] = c;
+	return 0;
+}
+
+static int new_subclass(const char *name, u_int8_t classid, u_int8_t subclassid)
+{
+	struct subclass *s;
+	unsigned int h = hashnum((classid << 8) | subclassid);
+
+	s = subclasses[h];
+	for (; s; s = s->next)
+		if (s->classid == classid && s->subclassid == subclassid)
+			return -1;
+	s = my_malloc(sizeof(struct subclass) + strlen(name));
+	if (!s)
+		return -1;
+	strcpy(s->name, name);
+	s->classid = classid;
+	s->subclassid = subclassid;
+	s->next = subclasses[h];
+	subclasses[h] = s;
+	return 0;
+}
+
+static int new_protocol(const char *name, u_int8_t classid, u_int8_t subclassid,
+			u_int8_t protocolid)
+{
+	struct protocol *p;
+	unsigned int h = hashnum((classid << 16) | (subclassid << 8)
+				 | protocolid);
+
+	p = protocols[h];
+	for (; p; p = p->next)
+		if (p->classid == classid && p->subclassid == subclassid
+		    && p->protocolid == protocolid)
+			return -1;
+	p = my_malloc(sizeof(struct protocol) + strlen(name));
+	if (!p)
+		return -1;
+	strcpy(p->name, name);
+	p->classid = classid;
+	p->subclassid = subclassid;
+	p->protocolid = protocolid;
+	p->next = protocols[h];
+	protocols[h] = p;
+	return 0;
+}
+
+static void parse(FILE *f)
+{
+	char buf[512], *cp;
+	unsigned int linectr = 0;
+	int lastvendor = -1;
+	int lastclass = -1;
+	int lastsubclass = -1;
+	int lasthut = -1;
+	int lastlang = -1;
+	unsigned int u;
+
+	while (fgets(buf, sizeof(buf), f)) {
+		linectr++;
+		/* remove line ends */
+		cp = strchr(buf, '\r');
+		if (cp)
+			*cp = 0;
+		cp = strchr(buf, '\n');
+		if (cp)
+			*cp = 0;
+		if (buf[0] == '#' || !buf[0])
+			continue;
+		cp = buf;
+		if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' &&
+		    buf[3] == 'S' && buf[4] == 'D' &&
+		    buf[5] == 'E' && buf[6] == 'S' && /*isspace(buf[7])*/
+		    buf[7] == ' ') {
+			continue;
+		}
+		if (buf[0] == 'P' && buf[1] == 'H' &&
+		    buf[2] == 'Y' && /*isspace(buf[3])*/ buf[3] == ' ') {
+			continue;
+		}
+		if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A' &&
+		    buf[3] == 'S' && /*isspace(buf[4])*/ buf[4] == ' ') {
+			continue;
+		}
+		if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') {
+			lasthut = lastclass = lastvendor = lastsubclass = -1;
+			/*
+			 * set 1 as pseudo-id to indicate that the parser is
+			 * in a `L' section.
+			 */
+			lastlang = 1;
+			continue;
+		}
+		if (buf[0] == 'C' && /*isspace(buf[1])*/ buf[1] == ' ') {
+			/* class spec */
+			cp = buf+2;
+			while (isspace(*cp))
+				cp++;
+			if (!isxdigit(*cp)) {
+				err("Invalid class spec at line %u", linectr);
+				continue;
+			}
+			u = strtoul(cp, &cp, 16);
+			while (isspace(*cp))
+				cp++;
+			if (!*cp) {
+				err("Invalid class spec at line %u", linectr);
+				continue;
+			}
+			if (new_class(cp, u))
+				err("Duplicate class spec at line %u class %04x %s",
+				    linectr, u, cp);
+			dbg("line %5u class %02x %s", linectr, u, cp);
+			lasthut = lastlang = lastvendor = lastsubclass = -1;
+			lastclass = u;
+			continue;
+		}
+		if (buf[0] == 'A' && buf[1] == 'T' && isspace(buf[2])) {
+			/* audio terminal type spec */
+			continue;
+		}
+		if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C'
+		    && isspace(buf[3])) {
+			/* HID Descriptor bCountryCode */
+			continue;
+		}
+		if (isxdigit(*cp)) {
+			/* vendor */
+			u = strtoul(cp, &cp, 16);
+			while (isspace(*cp))
+				cp++;
+			if (!*cp) {
+				err("Invalid vendor spec at line %u", linectr);
+				continue;
+			}
+			if (new_vendor(cp, u))
+				err("Duplicate vendor spec at line %u vendor %04x %s",
+				    linectr, u, cp);
+			dbg("line %5u vendor %04x %s", linectr, u, cp);
+			lastvendor = u;
+			lasthut = lastlang = lastclass = lastsubclass = -1;
+			continue;
+		}
+		if (buf[0] == '\t' && isxdigit(buf[1])) {
+			/* product or subclass spec */
+			u = strtoul(buf+1, &cp, 16);
+			while (isspace(*cp))
+				cp++;
+			if (!*cp) {
+				err("Invalid product/subclass spec at line %u",
+				    linectr);
+				continue;
+			}
+			if (lastvendor != -1) {
+				if (new_product(cp, lastvendor, u))
+					err("Duplicate product spec at line %u product %04x:%04x %s",
+					    linectr, lastvendor, u, cp);
+				dbg("line %5u product %04x:%04x %s", linectr,
+				    lastvendor, u, cp);
+				continue;
+			}
+			if (lastclass != -1) {
+				if (new_subclass(cp, lastclass, u))
+					err("Duplicate subclass spec at line %u class %02x:%02x %s",
+					    linectr, lastclass, u, cp);
+				dbg("line %5u subclass %02x:%02x %s", linectr,
+				    lastclass, u, cp);
+				lastsubclass = u;
+				continue;
+			}
+			if (lasthut != -1) {
+				/* do not store hut */
+				continue;
+			}
+			if (lastlang != -1) {
+				/* do not store langid */
+				continue;
+			}
+			err("Product/Subclass spec without prior Vendor/Class spec at line %u",
+			    linectr);
+			continue;
+		}
+		if (buf[0] == '\t' && buf[1] == '\t' && isxdigit(buf[2])) {
+			/* protocol spec */
+			u = strtoul(buf+2, &cp, 16);
+			while (isspace(*cp))
+				cp++;
+			if (!*cp) {
+				err("Invalid protocol spec at line %u",
+				    linectr);
+				continue;
+			}
+			if (lastclass != -1 && lastsubclass != -1) {
+				if (new_protocol(cp, lastclass, lastsubclass,
+						 u))
+					err("Duplicate protocol spec at line %u class %02x:%02x:%02x %s",
+					    linectr, lastclass, lastsubclass,
+					    u, cp);
+				dbg("line %5u protocol %02x:%02x:%02x %s",
+				    linectr, lastclass, lastsubclass, u, cp);
+				continue;
+			}
+			err("Protocol spec without prior Class and Subclass spec at line %u",
+			    linectr);
+			continue;
+		}
+		if (buf[0] == 'H' && buf[1] == 'I' &&
+		    buf[2] == 'D' && /*isspace(buf[3])*/ buf[3] == ' ') {
+			continue;
+		}
+		if (buf[0] == 'H' && buf[1] == 'U' &&
+		    buf[2] == 'T' && /*isspace(buf[3])*/ buf[3] == ' ') {
+			lastlang = lastclass = lastvendor = lastsubclass = -1;
+			/*
+			 * set 1 as pseudo-id to indicate that the parser is
+			 * in a `HUT' section.
+			 */
+			lasthut = 1;
+			continue;
+		}
+		if (buf[0] == 'R' && buf[1] == ' ')
+			continue;
+
+		if (buf[0] == 'V' && buf[1] == 'T')
+			continue;
+
+		err("Unknown line at line %u", linectr);
+	}
+}
+
+
+int names_init(char *n)
+{
+	FILE *f;
+
+	f = fopen(n, "r");
+	if (!f)
+		return errno;
+
+	parse(f);
+	fclose(f);
+	return 0;
+}