ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/linux/tools/usb/usbip/libsrc/Makefile.am b/marvell/linux/tools/usb/usbip/libsrc/Makefile.am
new file mode 100644
index 0000000..dabd2c9
--- /dev/null
+++ b/marvell/linux/tools/usb/usbip/libsrc/Makefile.am
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0
+libusbip_la_CPPFLAGS = -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"'
+libusbip_la_CFLAGS   = @EXTRA_CFLAGS@
+libusbip_la_LDFLAGS  = -version-info @LIBUSBIP_VERSION@
+
+lib_LTLIBRARIES := libusbip.la
+libusbip_la_SOURCES := names.c names.h usbip_host_driver.c usbip_host_driver.h \
+		       usbip_device_driver.c usbip_device_driver.h \
+		       usbip_common.c usbip_common.h usbip_host_common.h \
+		       usbip_host_common.c vhci_driver.c vhci_driver.h \
+		       sysfs_utils.c sysfs_utils.h
diff --git a/marvell/linux/tools/usb/usbip/libsrc/list.h b/marvell/linux/tools/usb/usbip/libsrc/list.h
new file mode 100644
index 0000000..a941671
--- /dev/null
+++ b/marvell/linux/tools/usb/usbip/libsrc/list.h
@@ -0,0 +1,137 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LIST_H
+#define _LIST_H
+
+/* Stripped down implementation of linked list taken
+ * from the Linux Kernel.
+ */
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+	struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+	struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void INIT_LIST_HEAD(struct list_head *list)
+{
+	list->next = list;
+	list->prev = list;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+			      struct list_head *prev,
+			      struct list_head *next)
+{
+	next->prev = new;
+	new->next = next;
+	new->prev = prev;
+	prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+	__list_add(new, head, head->next);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+	next->prev = prev;
+	prev->next = next;
+}
+
+#define POISON_POINTER_DELTA 0
+#define LIST_POISON1  ((void *) 0x00100100 + POISON_POINTER_DELTA)
+#define LIST_POISON2  ((void *) 0x00200200 + POISON_POINTER_DELTA)
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty() on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void __list_del_entry(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+}
+
+static inline void list_del(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+	entry->next = LIST_POISON1;
+	entry->prev = LIST_POISON2;
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:	the &struct list_head pointer.
+ * @type:	the type of the struct this is embedded in.
+ * @member:	the name of the list_head within the struct.
+ */
+#define list_entry(ptr, type, member) \
+	container_of(ptr, type, member)
+/**
+ * list_for_each	-	iterate over a list
+ * @pos:	the &struct list_head to use as a loop cursor.
+ * @head:	the head for your list.
+ */
+#define list_for_each(pos, head) \
+	for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos:	the &struct list_head to use as a loop cursor.
+ * @n:		another &struct list_head to use as temporary storage
+ * @head:	the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+	for (pos = (head)->next, n = pos->next; pos != (head); \
+		pos = n, n = pos->next)
+
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr:	the pointer to the member.
+ * @type:	the type of the container struct this is embedded in.
+ * @member:	the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({			\
+	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
+	(type *)( (char *)__mptr - offsetof(type,member) );})
+
+#endif
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;
+}
diff --git a/marvell/linux/tools/usb/usbip/libsrc/names.h b/marvell/linux/tools/usb/usbip/libsrc/names.h
new file mode 100644
index 0000000..b399582
--- /dev/null
+++ b/marvell/linux/tools/usb/usbip/libsrc/names.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *      names.h  --  USB name database manipulation routines
+ *
+ *      Copyright (C) 1999, 2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ *	Copyright (C) 2005 Takahiro Hirofuchi
+ *	       - names_free() is added.
+ */
+
+#ifndef _NAMES_H
+#define _NAMES_H
+
+#include <sys/types.h>
+
+/* used by usbip_common.c */
+extern const char *names_vendor(u_int16_t vendorid);
+extern const char *names_product(u_int16_t vendorid, u_int16_t productid);
+extern const char *names_class(u_int8_t classid);
+extern const char *names_subclass(u_int8_t classid, u_int8_t subclassid);
+extern const char *names_protocol(u_int8_t classid, u_int8_t subclassid,
+				  u_int8_t protocolid);
+extern int  names_init(char *n);
+extern void names_free(void);
+
+#endif /* _NAMES_H */
diff --git a/marvell/linux/tools/usb/usbip/libsrc/sysfs_utils.c b/marvell/linux/tools/usb/usbip/libsrc/sysfs_utils.c
new file mode 100644
index 0000000..14d5e67
--- /dev/null
+++ b/marvell/linux/tools/usb/usbip/libsrc/sysfs_utils.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "sysfs_utils.h"
+#include "usbip_common.h"
+
+int write_sysfs_attribute(const char *attr_path, const char *new_value,
+			  size_t len)
+{
+	int fd;
+	int length;
+
+	fd = open(attr_path, O_WRONLY);
+	if (fd < 0) {
+		dbg("error opening attribute %s", attr_path);
+		return -1;
+	}
+
+	length = write(fd, new_value, len);
+	if (length < 0) {
+		dbg("error writing to attribute %s", attr_path);
+		close(fd);
+		return -1;
+	}
+
+	close(fd);
+
+	return 0;
+}
diff --git a/marvell/linux/tools/usb/usbip/libsrc/sysfs_utils.h b/marvell/linux/tools/usb/usbip/libsrc/sysfs_utils.h
new file mode 100644
index 0000000..0cd5f17
--- /dev/null
+++ b/marvell/linux/tools/usb/usbip/libsrc/sysfs_utils.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __SYSFS_UTILS_H
+#define __SYSFS_UTILS_H
+
+int write_sysfs_attribute(const char *attr_path, const char *new_value,
+			  size_t len);
+
+#endif
diff --git a/marvell/linux/tools/usb/usbip/libsrc/usbip_common.c b/marvell/linux/tools/usb/usbip/libsrc/usbip_common.c
new file mode 100644
index 0000000..b8d7d48
--- /dev/null
+++ b/marvell/linux/tools/usb/usbip/libsrc/usbip_common.c
@@ -0,0 +1,318 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005-2007 Takahiro Hirofuchi
+ */
+
+#include <libudev.h>
+#include "usbip_common.h"
+#include "names.h"
+
+#undef  PROGNAME
+#define PROGNAME "libusbip"
+
+int usbip_use_syslog;
+int usbip_use_stderr;
+int usbip_use_debug;
+
+extern struct udev *udev_context;
+
+struct speed_string {
+	int num;
+	char *speed;
+	char *desc;
+};
+
+static const struct speed_string speed_strings[] = {
+	{ USB_SPEED_UNKNOWN, "unknown", "Unknown Speed"},
+	{ USB_SPEED_LOW,  "1.5", "Low Speed(1.5Mbps)"  },
+	{ USB_SPEED_FULL, "12",  "Full Speed(12Mbps)" },
+	{ USB_SPEED_HIGH, "480", "High Speed(480Mbps)" },
+	{ USB_SPEED_WIRELESS, "53.3-480", "Wireless"},
+	{ USB_SPEED_SUPER, "5000", "Super Speed(5000Mbps)" },
+	{ 0, NULL, NULL }
+};
+
+struct portst_string {
+	int num;
+	char *desc;
+};
+
+static struct portst_string portst_strings[] = {
+	{ SDEV_ST_AVAILABLE,	"Device Available" },
+	{ SDEV_ST_USED,		"Device in Use" },
+	{ SDEV_ST_ERROR,	"Device Error"},
+	{ VDEV_ST_NULL,		"Port Available"},
+	{ VDEV_ST_NOTASSIGNED,	"Port Initializing"},
+	{ VDEV_ST_USED,		"Port in Use"},
+	{ VDEV_ST_ERROR,	"Port Error"},
+	{ 0, NULL}
+};
+
+const char *usbip_status_string(int32_t status)
+{
+	for (int i = 0; portst_strings[i].desc != NULL; i++)
+		if (portst_strings[i].num == status)
+			return portst_strings[i].desc;
+
+	return "Unknown Status";
+}
+
+const char *usbip_speed_string(int num)
+{
+	for (int i = 0; speed_strings[i].speed != NULL; i++)
+		if (speed_strings[i].num == num)
+			return speed_strings[i].desc;
+
+	return "Unknown Speed";
+}
+
+struct op_common_status_string {
+	int num;
+	char *desc;
+};
+
+static struct op_common_status_string op_common_status_strings[] = {
+	{ ST_OK,	"Request Completed Successfully" },
+	{ ST_NA,	"Request Failed" },
+	{ ST_DEV_BUSY,	"Device busy (exported)" },
+	{ ST_DEV_ERR,	"Device in error state" },
+	{ ST_NODEV,	"Device not found" },
+	{ ST_ERROR,	"Unexpected response" },
+	{ 0, NULL}
+};
+
+const char *usbip_op_common_status_string(int status)
+{
+	for (int i = 0; op_common_status_strings[i].desc != NULL; i++)
+		if (op_common_status_strings[i].num == status)
+			return op_common_status_strings[i].desc;
+
+	return "Unknown Op Common Status";
+}
+
+#define DBG_UDEV_INTEGER(name)\
+	dbg("%-20s = %x", to_string(name), (int) udev->name)
+
+#define DBG_UINF_INTEGER(name)\
+	dbg("%-20s = %x", to_string(name), (int) uinf->name)
+
+void dump_usb_interface(struct usbip_usb_interface *uinf)
+{
+	char buff[100];
+
+	usbip_names_get_class(buff, sizeof(buff),
+			uinf->bInterfaceClass,
+			uinf->bInterfaceSubClass,
+			uinf->bInterfaceProtocol);
+	dbg("%-20s = %s", "Interface(C/SC/P)", buff);
+}
+
+void dump_usb_device(struct usbip_usb_device *udev)
+{
+	char buff[100];
+
+	dbg("%-20s = %s", "path",  udev->path);
+	dbg("%-20s = %s", "busid", udev->busid);
+
+	usbip_names_get_class(buff, sizeof(buff),
+			udev->bDeviceClass,
+			udev->bDeviceSubClass,
+			udev->bDeviceProtocol);
+	dbg("%-20s = %s", "Device(C/SC/P)", buff);
+
+	DBG_UDEV_INTEGER(bcdDevice);
+
+	usbip_names_get_product(buff, sizeof(buff),
+			udev->idVendor,
+			udev->idProduct);
+	dbg("%-20s = %s", "Vendor/Product", buff);
+
+	DBG_UDEV_INTEGER(bNumConfigurations);
+	DBG_UDEV_INTEGER(bNumInterfaces);
+
+	dbg("%-20s = %s", "speed",
+			usbip_speed_string(udev->speed));
+
+	DBG_UDEV_INTEGER(busnum);
+	DBG_UDEV_INTEGER(devnum);
+}
+
+
+int read_attr_value(struct udev_device *dev, const char *name,
+		    const char *format)
+{
+	const char *attr;
+	int num = 0;
+	int ret;
+
+	attr = udev_device_get_sysattr_value(dev, name);
+	if (!attr) {
+		err("udev_device_get_sysattr_value failed");
+		goto err;
+	}
+
+	/* The client chooses the device configuration
+	 * when attaching it so right after being bound
+	 * to usbip-host on the server the device will
+	 * have no configuration.
+	 * Therefore, attributes such as bConfigurationValue
+	 * and bNumInterfaces will not exist and sscanf will
+	 * fail. Check for these cases and don't treat them
+	 * as errors.
+	 */
+
+	ret = sscanf(attr, format, &num);
+	if (ret < 1) {
+		if (strcmp(name, "bConfigurationValue") &&
+				strcmp(name, "bNumInterfaces")) {
+			err("sscanf failed for attribute %s", name);
+			goto err;
+		}
+	}
+
+err:
+
+	return num;
+}
+
+
+int read_attr_speed(struct udev_device *dev)
+{
+	const char *speed;
+
+	speed = udev_device_get_sysattr_value(dev, "speed");
+	if (!speed) {
+		err("udev_device_get_sysattr_value failed");
+		goto err;
+	}
+
+	for (int i = 0; speed_strings[i].speed != NULL; i++) {
+		if (!strcmp(speed, speed_strings[i].speed))
+			return speed_strings[i].num;
+	}
+
+err:
+
+	return USB_SPEED_UNKNOWN;
+}
+
+#define READ_ATTR(object, type, dev, name, format)			      \
+	do {								      \
+		(object)->name = (type) read_attr_value(dev, to_string(name), \
+							format);	      \
+	} while (0)
+
+
+int read_usb_device(struct udev_device *sdev, struct usbip_usb_device *udev)
+{
+	uint32_t busnum, devnum;
+	const char *path, *name;
+
+	READ_ATTR(udev, uint8_t,  sdev, bDeviceClass,		"%02x\n");
+	READ_ATTR(udev, uint8_t,  sdev, bDeviceSubClass,	"%02x\n");
+	READ_ATTR(udev, uint8_t,  sdev, bDeviceProtocol,	"%02x\n");
+
+	READ_ATTR(udev, uint16_t, sdev, idVendor,		"%04x\n");
+	READ_ATTR(udev, uint16_t, sdev, idProduct,		"%04x\n");
+	READ_ATTR(udev, uint16_t, sdev, bcdDevice,		"%04x\n");
+
+	READ_ATTR(udev, uint8_t,  sdev, bConfigurationValue,	"%02x\n");
+	READ_ATTR(udev, uint8_t,  sdev, bNumConfigurations,	"%02x\n");
+	READ_ATTR(udev, uint8_t,  sdev, bNumInterfaces,		"%02x\n");
+
+	READ_ATTR(udev, uint8_t,  sdev, devnum,			"%d\n");
+	udev->speed = read_attr_speed(sdev);
+
+	path = udev_device_get_syspath(sdev);
+	name = udev_device_get_sysname(sdev);
+
+	strncpy(udev->path,  path,  SYSFS_PATH_MAX - 1);
+	udev->path[SYSFS_PATH_MAX - 1] = '\0';
+	strncpy(udev->busid, name, SYSFS_BUS_ID_SIZE - 1);
+	udev->busid[SYSFS_BUS_ID_SIZE - 1] = '\0';
+
+	sscanf(name, "%u-%u", &busnum, &devnum);
+	udev->busnum = busnum;
+
+	return 0;
+}
+
+int read_usb_interface(struct usbip_usb_device *udev, int i,
+		       struct usbip_usb_interface *uinf)
+{
+	char busid[SYSFS_BUS_ID_SIZE];
+	int size;
+	struct udev_device *sif;
+
+	size = snprintf(busid, sizeof(busid), "%s:%d.%d",
+			udev->busid, udev->bConfigurationValue, i);
+	if (size < 0 || (unsigned int)size >= sizeof(busid)) {
+		err("busid length %i >= %lu or < 0", size,
+		    (long unsigned)sizeof(busid));
+		return -1;
+	}
+
+	sif = udev_device_new_from_subsystem_sysname(udev_context, "usb", busid);
+	if (!sif) {
+		err("udev_device_new_from_subsystem_sysname %s failed", busid);
+		return -1;
+	}
+
+	READ_ATTR(uinf, uint8_t,  sif, bInterfaceClass,		"%02x\n");
+	READ_ATTR(uinf, uint8_t,  sif, bInterfaceSubClass,	"%02x\n");
+	READ_ATTR(uinf, uint8_t,  sif, bInterfaceProtocol,	"%02x\n");
+
+	return 0;
+}
+
+int usbip_names_init(char *f)
+{
+	return names_init(f);
+}
+
+void usbip_names_free(void)
+{
+	names_free();
+}
+
+void usbip_names_get_product(char *buff, size_t size, uint16_t vendor,
+			     uint16_t product)
+{
+	const char *prod, *vend;
+
+	prod = names_product(vendor, product);
+	if (!prod)
+		prod = "unknown product";
+
+
+	vend = names_vendor(vendor);
+	if (!vend)
+		vend = "unknown vendor";
+
+	snprintf(buff, size, "%s : %s (%04x:%04x)", vend, prod, vendor, product);
+}
+
+void usbip_names_get_class(char *buff, size_t size, uint8_t class,
+			   uint8_t subclass, uint8_t protocol)
+{
+	const char *c, *s, *p;
+
+	if (class == 0 && subclass == 0 && protocol == 0) {
+		snprintf(buff, size, "(Defined at Interface level) (%02x/%02x/%02x)", class, subclass, protocol);
+		return;
+	}
+
+	p = names_protocol(class, subclass, protocol);
+	if (!p)
+		p = "unknown protocol";
+
+	s = names_subclass(class, subclass);
+	if (!s)
+		s = "unknown subclass";
+
+	c = names_class(class);
+	if (!c)
+		c = "unknown class";
+
+	snprintf(buff, size, "%s / %s / %s (%02x/%02x/%02x)", c, s, p, class, subclass, protocol);
+}
diff --git a/marvell/linux/tools/usb/usbip/libsrc/usbip_common.h b/marvell/linux/tools/usb/usbip/libsrc/usbip_common.h
new file mode 100644
index 0000000..73a367a
--- /dev/null
+++ b/marvell/linux/tools/usb/usbip/libsrc/usbip_common.h
@@ -0,0 +1,152 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2005-2007 Takahiro Hirofuchi
+ */
+
+#ifndef __USBIP_COMMON_H
+#define __USBIP_COMMON_H
+
+#include <libudev.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <syslog.h>
+#include <unistd.h>
+#include <linux/usb/ch9.h>
+#include <linux/usbip.h>
+
+#ifndef USBIDS_FILE
+#define USBIDS_FILE "/usr/share/hwdata/usb.ids"
+#endif
+
+#ifndef VHCI_STATE_PATH
+#define VHCI_STATE_PATH "/var/run/vhci_hcd"
+#endif
+
+#define VUDC_DEVICE_DESCR_FILE "dev_desc"
+
+/* kernel module names */
+#define USBIP_CORE_MOD_NAME	"usbip-core"
+#define USBIP_HOST_DRV_NAME	"usbip-host"
+#define USBIP_DEVICE_DRV_NAME	"usbip-vudc"
+#define USBIP_VHCI_DRV_NAME	"vhci_hcd"
+
+/* sysfs constants */
+#define SYSFS_MNT_PATH         "/sys"
+#define SYSFS_BUS_NAME         "bus"
+#define SYSFS_BUS_TYPE         "usb"
+#define SYSFS_DRIVERS_NAME     "drivers"
+
+#define SYSFS_PATH_MAX		256
+#define SYSFS_BUS_ID_SIZE	32
+
+/* Defines for op_code status in server/client op_common PDUs */
+#define ST_OK	0x00
+#define ST_NA	0x01
+	/* Device requested for import is not available */
+#define ST_DEV_BUSY	0x02
+	/* Device requested for import is in error state */
+#define ST_DEV_ERR	0x03
+#define ST_NODEV	0x04
+#define ST_ERROR	0x05
+
+extern int usbip_use_syslog;
+extern int usbip_use_stderr;
+extern int usbip_use_debug ;
+
+#define PROGNAME "usbip"
+
+#define pr_fmt(fmt)	"%s: %s: " fmt "\n", PROGNAME
+#define dbg_fmt(fmt)	pr_fmt("%s:%d:[%s] " fmt), "debug",	\
+		        __FILE__, __LINE__, __func__
+
+#define err(fmt, args...)						\
+	do {								\
+		if (usbip_use_syslog) {					\
+			syslog(LOG_ERR, pr_fmt(fmt), "error", ##args);	\
+		}							\
+		if (usbip_use_stderr) {					\
+			fprintf(stderr, pr_fmt(fmt), "error", ##args);	\
+		}							\
+	} while (0)
+
+#define info(fmt, args...)						\
+	do {								\
+		if (usbip_use_syslog) {					\
+			syslog(LOG_INFO, pr_fmt(fmt), "info", ##args);	\
+		}							\
+		if (usbip_use_stderr) {					\
+			fprintf(stderr, pr_fmt(fmt), "info", ##args);	\
+		}							\
+	} while (0)
+
+#define dbg(fmt, args...)						\
+	do {								\
+	if (usbip_use_debug) {						\
+		if (usbip_use_syslog) {					\
+			syslog(LOG_DEBUG, dbg_fmt(fmt), ##args);	\
+		}							\
+		if (usbip_use_stderr) {					\
+			fprintf(stderr, dbg_fmt(fmt), ##args);		\
+		}							\
+	}								\
+	} while (0)
+
+#define BUG()						\
+	do {						\
+		err("sorry, it's a bug!");		\
+		abort();				\
+	} while (0)
+
+struct usbip_usb_interface {
+	uint8_t bInterfaceClass;
+	uint8_t bInterfaceSubClass;
+	uint8_t bInterfaceProtocol;
+	uint8_t padding;	/* alignment */
+} __attribute__((packed));
+
+struct usbip_usb_device {
+	char path[SYSFS_PATH_MAX];
+	char busid[SYSFS_BUS_ID_SIZE];
+
+	uint32_t busnum;
+	uint32_t devnum;
+	uint32_t speed;
+
+	uint16_t idVendor;
+	uint16_t idProduct;
+	uint16_t bcdDevice;
+
+	uint8_t bDeviceClass;
+	uint8_t bDeviceSubClass;
+	uint8_t bDeviceProtocol;
+	uint8_t bConfigurationValue;
+	uint8_t bNumConfigurations;
+	uint8_t bNumInterfaces;
+} __attribute__((packed));
+
+#define to_string(s)	#s
+
+void dump_usb_interface(struct usbip_usb_interface *);
+void dump_usb_device(struct usbip_usb_device *);
+int read_usb_device(struct udev_device *sdev, struct usbip_usb_device *udev);
+int read_attr_value(struct udev_device *dev, const char *name,
+		    const char *format);
+int read_usb_interface(struct usbip_usb_device *udev, int i,
+		       struct usbip_usb_interface *uinf);
+
+const char *usbip_speed_string(int num);
+const char *usbip_status_string(int32_t status);
+const char *usbip_op_common_status_string(int status);
+
+int usbip_names_init(char *);
+void usbip_names_free(void);
+void usbip_names_get_product(char *buff, size_t size, uint16_t vendor,
+			     uint16_t product);
+void usbip_names_get_class(char *buff, size_t size, uint8_t class,
+			   uint8_t subclass, uint8_t protocol);
+
+#endif /* __USBIP_COMMON_H */
diff --git a/marvell/linux/tools/usb/usbip/libsrc/usbip_device_driver.c b/marvell/linux/tools/usb/usbip/libsrc/usbip_device_driver.c
new file mode 100644
index 0000000..927a151
--- /dev/null
+++ b/marvell/linux/tools/usb/usbip/libsrc/usbip_device_driver.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2015 Karol Kosik <karo9@interia.eu>
+ *		 2015 Samsung Electronics
+ * Author:	 Igor Kotrasinski <i.kotrasinsk@samsung.com>
+ *
+ * Based on tools/usb/usbip/libsrc/usbip_host_driver.c, which is:
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ */
+
+#include <fcntl.h>
+#include <string.h>
+#include <linux/usb/ch9.h>
+
+#include <unistd.h>
+
+#include "usbip_host_common.h"
+#include "usbip_device_driver.h"
+
+#undef  PROGNAME
+#define PROGNAME "libusbip"
+
+#define copy_descr_attr16(dev, descr, attr)			\
+		((dev)->attr = le16toh((descr)->attr))		\
+
+#define copy_descr_attr(dev, descr, attr)			\
+		((dev)->attr = (descr)->attr)			\
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+static struct {
+	enum usb_device_speed speed;
+	const char *name;
+} speed_names[] = {
+	{
+		.speed = USB_SPEED_UNKNOWN,
+		.name = "UNKNOWN",
+	},
+	{
+		.speed = USB_SPEED_LOW,
+		.name = "low-speed",
+	},
+	{
+		.speed = USB_SPEED_FULL,
+		.name = "full-speed",
+	},
+	{
+		.speed = USB_SPEED_HIGH,
+		.name = "high-speed",
+	},
+	{
+		.speed = USB_SPEED_WIRELESS,
+		.name = "wireless",
+	},
+	{
+		.speed = USB_SPEED_SUPER,
+		.name = "super-speed",
+	},
+};
+
+static
+int read_usb_vudc_device(struct udev_device *sdev, struct usbip_usb_device *dev)
+{
+	const char *path, *name;
+	char filepath[SYSFS_PATH_MAX];
+	struct usb_device_descriptor descr;
+	unsigned int i;
+	FILE *fd = NULL;
+	struct udev_device *plat;
+	const char *speed;
+	size_t ret;
+
+	plat = udev_device_get_parent(sdev);
+	path = udev_device_get_syspath(plat);
+	snprintf(filepath, SYSFS_PATH_MAX, "%s/%s",
+		 path, VUDC_DEVICE_DESCR_FILE);
+	fd = fopen(filepath, "r");
+	if (!fd)
+		return -1;
+	ret = fread((char *) &descr, sizeof(descr), 1, fd);
+	if (ret != 1) {
+		err("Cannot read vudc device descr file: %s", strerror(errno));
+		goto err;
+	}
+	fclose(fd);
+
+	copy_descr_attr(dev, &descr, bDeviceClass);
+	copy_descr_attr(dev, &descr, bDeviceSubClass);
+	copy_descr_attr(dev, &descr, bDeviceProtocol);
+	copy_descr_attr(dev, &descr, bNumConfigurations);
+	copy_descr_attr16(dev, &descr, idVendor);
+	copy_descr_attr16(dev, &descr, idProduct);
+	copy_descr_attr16(dev, &descr, bcdDevice);
+
+	strncpy(dev->path, path, SYSFS_PATH_MAX - 1);
+	dev->path[SYSFS_PATH_MAX - 1] = '\0';
+
+	dev->speed = USB_SPEED_UNKNOWN;
+	speed = udev_device_get_sysattr_value(sdev, "current_speed");
+	if (speed) {
+		for (i = 0; i < ARRAY_SIZE(speed_names); i++) {
+			if (!strcmp(speed_names[i].name, speed)) {
+				dev->speed = speed_names[i].speed;
+				break;
+			}
+		}
+	}
+
+	/* Only used for user output, little sense to output them in general */
+	dev->bNumInterfaces = 0;
+	dev->bConfigurationValue = 0;
+	dev->busnum = 0;
+
+	name = udev_device_get_sysname(plat);
+	strncpy(dev->busid, name, SYSFS_BUS_ID_SIZE - 1);
+	dev->busid[SYSFS_BUS_ID_SIZE - 1] = '\0';
+	return 0;
+err:
+	fclose(fd);
+	return -1;
+}
+
+static int is_my_device(struct udev_device *dev)
+{
+	const char *driver;
+
+	driver = udev_device_get_property_value(dev, "USB_UDC_NAME");
+	return driver != NULL && !strcmp(driver, USBIP_DEVICE_DRV_NAME);
+}
+
+static int usbip_device_driver_open(struct usbip_host_driver *hdriver)
+{
+	int ret;
+
+	hdriver->ndevs = 0;
+	INIT_LIST_HEAD(&hdriver->edev_list);
+
+	ret = usbip_generic_driver_open(hdriver);
+	if (ret)
+		err("please load " USBIP_CORE_MOD_NAME ".ko and "
+		    USBIP_DEVICE_DRV_NAME ".ko!");
+
+	return ret;
+}
+
+struct usbip_host_driver device_driver = {
+	.edev_list = LIST_HEAD_INIT(device_driver.edev_list),
+	.udev_subsystem = "udc",
+	.ops = {
+		.open = usbip_device_driver_open,
+		.close = usbip_generic_driver_close,
+		.refresh_device_list = usbip_generic_refresh_device_list,
+		.get_device = usbip_generic_get_device,
+		.read_device = read_usb_vudc_device,
+		.is_my_device = is_my_device,
+	},
+};
diff --git a/marvell/linux/tools/usb/usbip/libsrc/usbip_device_driver.h b/marvell/linux/tools/usb/usbip/libsrc/usbip_device_driver.h
new file mode 100644
index 0000000..1ce0bbd
--- /dev/null
+++ b/marvell/linux/tools/usb/usbip/libsrc/usbip_device_driver.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2015 Karol Kosik <karo9@interia.eu>
+ *		 2015 Samsung Electronics
+ * Author:	 Igor Kotrasinski <i.kotrasinsk@samsung.com>
+ *
+ * Based on tools/usb/usbip/libsrc/usbip_host_driver.c, which is:
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ */
+
+#ifndef __USBIP_DEVICE_DRIVER_H
+#define __USBIP_DEVICE_DRIVER_H
+
+#include <stdint.h>
+#include "usbip_common.h"
+#include "usbip_host_common.h"
+#include "list.h"
+
+extern struct usbip_host_driver device_driver;
+
+#endif /* __USBIP_DEVICE_DRIVER_H */
diff --git a/marvell/linux/tools/usb/usbip/libsrc/usbip_host_common.c b/marvell/linux/tools/usb/usbip/libsrc/usbip_host_common.c
new file mode 100644
index 0000000..ca78aa3
--- /dev/null
+++ b/marvell/linux/tools/usb/usbip/libsrc/usbip_host_common.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2015-2016 Samsung Electronics
+ *               Igor Kotrasinski <i.kotrasinsk@samsung.com>
+ *               Krzysztof Opasiak <k.opasiak@samsung.com>
+ *
+ * Refactored from usbip_host_driver.c, which is:
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <libudev.h>
+
+#include "usbip_common.h"
+#include "usbip_host_common.h"
+#include "list.h"
+#include "sysfs_utils.h"
+
+extern struct udev *udev_context;
+
+static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
+{
+	char status_attr_path[SYSFS_PATH_MAX];
+	int size;
+	int fd;
+	int length;
+	char status[2] = { 0 };
+	int value = 0;
+
+	size = snprintf(status_attr_path, sizeof(status_attr_path),
+			"%s/usbip_status", udev->path);
+	if (size < 0 || (unsigned int)size >= sizeof(status_attr_path)) {
+		err("usbip_status path length %i >= %lu or < 0", size,
+		    (long unsigned)sizeof(status_attr_path));
+		return -1;
+	}
+
+
+	fd = open(status_attr_path, O_RDONLY);
+	if (fd < 0) {
+		err("error opening attribute %s", status_attr_path);
+		return -1;
+	}
+
+	length = read(fd, status, 1);
+	if (length < 0) {
+		err("error reading attribute %s", status_attr_path);
+		close(fd);
+		return -1;
+	}
+
+	value = atoi(status);
+	close(fd);
+	return value;
+}
+
+static
+struct usbip_exported_device *usbip_exported_device_new(
+		struct usbip_host_driver *hdriver, const char *sdevpath)
+{
+	struct usbip_exported_device *edev = NULL;
+	struct usbip_exported_device *edev_old;
+	size_t size;
+	int i;
+
+	edev = calloc(1, sizeof(struct usbip_exported_device));
+
+	edev->sudev =
+		udev_device_new_from_syspath(udev_context, sdevpath);
+	if (!edev->sudev) {
+		err("udev_device_new_from_syspath: %s", sdevpath);
+		goto err;
+	}
+
+	if (hdriver->ops.read_device(edev->sudev, &edev->udev) < 0)
+		goto err;
+
+	edev->status = read_attr_usbip_status(&edev->udev);
+	if (edev->status < 0)
+		goto err;
+
+	/* reallocate buffer to include usb interface data */
+	size = sizeof(struct usbip_exported_device) +
+		edev->udev.bNumInterfaces * sizeof(struct usbip_usb_interface);
+
+	edev_old = edev;
+	edev = realloc(edev, size);
+	if (!edev) {
+		edev = edev_old;
+		dbg("realloc failed");
+		goto err;
+	}
+
+	for (i = 0; i < edev->udev.bNumInterfaces; i++) {
+		/* vudc does not support reading interfaces */
+		if (!hdriver->ops.read_interface)
+			break;
+		hdriver->ops.read_interface(&edev->udev, i, &edev->uinf[i]);
+	}
+
+	return edev;
+err:
+	if (edev->sudev)
+		udev_device_unref(edev->sudev);
+	if (edev)
+		free(edev);
+
+	return NULL;
+}
+
+static int refresh_exported_devices(struct usbip_host_driver *hdriver)
+{
+	struct usbip_exported_device *edev;
+	struct udev_enumerate *enumerate;
+	struct udev_list_entry *devices, *dev_list_entry;
+	struct udev_device *dev;
+	const char *path;
+
+	enumerate = udev_enumerate_new(udev_context);
+	udev_enumerate_add_match_subsystem(enumerate, hdriver->udev_subsystem);
+	udev_enumerate_scan_devices(enumerate);
+
+	devices = udev_enumerate_get_list_entry(enumerate);
+
+	udev_list_entry_foreach(dev_list_entry, devices) {
+		path = udev_list_entry_get_name(dev_list_entry);
+		dev = udev_device_new_from_syspath(udev_context,
+						   path);
+		if (dev == NULL)
+			continue;
+
+		/* Check whether device uses usbip driver. */
+		if (hdriver->ops.is_my_device(dev)) {
+			edev = usbip_exported_device_new(hdriver, path);
+			if (!edev) {
+				dbg("usbip_exported_device_new failed");
+				continue;
+			}
+
+			list_add(&edev->node, &hdriver->edev_list);
+			hdriver->ndevs++;
+		}
+	}
+
+	return 0;
+}
+
+static void usbip_exported_device_destroy(struct list_head *devs)
+{
+	struct list_head *i, *tmp;
+	struct usbip_exported_device *edev;
+
+	list_for_each_safe(i, tmp, devs) {
+		edev = list_entry(i, struct usbip_exported_device, node);
+		list_del(i);
+		free(edev);
+	}
+}
+
+int usbip_generic_driver_open(struct usbip_host_driver *hdriver)
+{
+	int rc;
+
+	udev_context = udev_new();
+	if (!udev_context) {
+		err("udev_new failed");
+		return -1;
+	}
+
+	rc = refresh_exported_devices(hdriver);
+	if (rc < 0)
+		goto err;
+	return 0;
+err:
+	udev_unref(udev_context);
+	return -1;
+}
+
+void usbip_generic_driver_close(struct usbip_host_driver *hdriver)
+{
+	if (!hdriver)
+		return;
+
+	usbip_exported_device_destroy(&hdriver->edev_list);
+
+	udev_unref(udev_context);
+}
+
+int usbip_generic_refresh_device_list(struct usbip_host_driver *hdriver)
+{
+	int rc;
+
+	usbip_exported_device_destroy(&hdriver->edev_list);
+
+	hdriver->ndevs = 0;
+	INIT_LIST_HEAD(&hdriver->edev_list);
+
+	rc = refresh_exported_devices(hdriver);
+	if (rc < 0)
+		return -1;
+
+	return 0;
+}
+
+int usbip_export_device(struct usbip_exported_device *edev, int sockfd)
+{
+	char attr_name[] = "usbip_sockfd";
+	char sockfd_attr_path[SYSFS_PATH_MAX];
+	int size;
+	char sockfd_buff[30];
+	int ret;
+
+	if (edev->status != SDEV_ST_AVAILABLE) {
+		dbg("device not available: %s", edev->udev.busid);
+		switch (edev->status) {
+		case SDEV_ST_ERROR:
+			dbg("status SDEV_ST_ERROR");
+			ret = ST_DEV_ERR;
+			break;
+		case SDEV_ST_USED:
+			dbg("status SDEV_ST_USED");
+			ret = ST_DEV_BUSY;
+			break;
+		default:
+			dbg("status unknown: 0x%x", edev->status);
+			ret = -1;
+		}
+		return ret;
+	}
+
+	/* only the first interface is true */
+	size = snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s",
+			edev->udev.path, attr_name);
+	if (size < 0 || (unsigned int)size >= sizeof(sockfd_attr_path)) {
+		err("exported device path length %i >= %lu or < 0", size,
+		    (long unsigned)sizeof(sockfd_attr_path));
+		return -1;
+	}
+
+	size = snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd);
+	if (size < 0 || (unsigned int)size >= sizeof(sockfd_buff)) {
+		err("socket length %i >= %lu or < 0", size,
+		    (long unsigned)sizeof(sockfd_buff));
+		return -1;
+	}
+
+	ret = write_sysfs_attribute(sockfd_attr_path, sockfd_buff,
+				    strlen(sockfd_buff));
+	if (ret < 0) {
+		err("write_sysfs_attribute failed: sockfd %s to %s",
+		    sockfd_buff, sockfd_attr_path);
+		return ret;
+	}
+
+	info("connect: %s", edev->udev.busid);
+
+	return ret;
+}
+
+struct usbip_exported_device *usbip_generic_get_device(
+		struct usbip_host_driver *hdriver, int num)
+{
+	struct list_head *i;
+	struct usbip_exported_device *edev;
+	int cnt = 0;
+
+	list_for_each(i, &hdriver->edev_list) {
+		edev = list_entry(i, struct usbip_exported_device, node);
+		if (num == cnt)
+			return edev;
+		cnt++;
+	}
+
+	return NULL;
+}
diff --git a/marvell/linux/tools/usb/usbip/libsrc/usbip_host_common.h b/marvell/linux/tools/usb/usbip/libsrc/usbip_host_common.h
new file mode 100644
index 0000000..f46967c
--- /dev/null
+++ b/marvell/linux/tools/usb/usbip/libsrc/usbip_host_common.h
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2015-2016 Samsung Electronics
+ *               Igor Kotrasinski <i.kotrasinsk@samsung.com>
+ *               Krzysztof Opasiak <k.opasiak@samsung.com>
+ *
+ * Refactored from usbip_host_driver.c, which is:
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ */
+
+#ifndef __USBIP_HOST_COMMON_H
+#define __USBIP_HOST_COMMON_H
+
+#include <stdint.h>
+#include <libudev.h>
+#include <errno.h>
+#include "list.h"
+#include "usbip_common.h"
+#include "sysfs_utils.h"
+
+struct usbip_host_driver;
+
+struct usbip_host_driver_ops {
+	int (*open)(struct usbip_host_driver *hdriver);
+	void (*close)(struct usbip_host_driver *hdriver);
+	int (*refresh_device_list)(struct usbip_host_driver *hdriver);
+	struct usbip_exported_device * (*get_device)(
+		struct usbip_host_driver *hdriver, int num);
+
+	int (*read_device)(struct udev_device *sdev,
+			   struct usbip_usb_device *dev);
+	int (*read_interface)(struct usbip_usb_device *udev, int i,
+			      struct usbip_usb_interface *uinf);
+	int (*is_my_device)(struct udev_device *udev);
+};
+
+struct usbip_host_driver {
+	int ndevs;
+	/* list of exported device */
+	struct list_head edev_list;
+	const char *udev_subsystem;
+	struct usbip_host_driver_ops ops;
+};
+
+struct usbip_exported_device {
+	struct udev_device *sudev;
+	int32_t status;
+	struct usbip_usb_device udev;
+	struct list_head node;
+	struct usbip_usb_interface uinf[];
+};
+
+/* External API to access the driver */
+static inline int usbip_driver_open(struct usbip_host_driver *hdriver)
+{
+	if (!hdriver->ops.open)
+		return -EOPNOTSUPP;
+	return hdriver->ops.open(hdriver);
+}
+
+static inline void usbip_driver_close(struct usbip_host_driver *hdriver)
+{
+	if (!hdriver->ops.close)
+		return;
+	hdriver->ops.close(hdriver);
+}
+
+static inline int usbip_refresh_device_list(struct usbip_host_driver *hdriver)
+{
+	if (!hdriver->ops.refresh_device_list)
+		return -EOPNOTSUPP;
+	return hdriver->ops.refresh_device_list(hdriver);
+}
+
+static inline struct usbip_exported_device *
+usbip_get_device(struct usbip_host_driver *hdriver, int num)
+{
+	if (!hdriver->ops.get_device)
+		return NULL;
+	return hdriver->ops.get_device(hdriver, num);
+}
+
+/* Helper functions for implementing driver backend */
+int usbip_generic_driver_open(struct usbip_host_driver *hdriver);
+void usbip_generic_driver_close(struct usbip_host_driver *hdriver);
+int usbip_generic_refresh_device_list(struct usbip_host_driver *hdriver);
+int usbip_export_device(struct usbip_exported_device *edev, int sockfd);
+struct usbip_exported_device *usbip_generic_get_device(
+		struct usbip_host_driver *hdriver, int num);
+
+#endif /* __USBIP_HOST_COMMON_H */
diff --git a/marvell/linux/tools/usb/usbip/libsrc/usbip_host_driver.c b/marvell/linux/tools/usb/usbip/libsrc/usbip_host_driver.c
new file mode 100644
index 0000000..573e73e
--- /dev/null
+++ b/marvell/linux/tools/usb/usbip/libsrc/usbip_host_driver.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ * Copyright (C) 2015-2016 Samsung Electronics
+ *               Igor Kotrasinski <i.kotrasinsk@samsung.com>
+ *               Krzysztof Opasiak <k.opasiak@samsung.com>
+ */
+
+#include <unistd.h>
+#include <libudev.h>
+
+#include "usbip_host_common.h"
+#include "usbip_host_driver.h"
+
+#undef  PROGNAME
+#define PROGNAME "libusbip"
+
+static int is_my_device(struct udev_device *dev)
+{
+	const char *driver;
+
+	driver = udev_device_get_driver(dev);
+	return driver != NULL && !strcmp(driver, USBIP_HOST_DRV_NAME);
+}
+
+static int usbip_host_driver_open(struct usbip_host_driver *hdriver)
+{
+	int ret;
+
+	hdriver->ndevs = 0;
+	INIT_LIST_HEAD(&hdriver->edev_list);
+
+	ret = usbip_generic_driver_open(hdriver);
+	if (ret)
+		err("please load " USBIP_CORE_MOD_NAME ".ko and "
+		    USBIP_HOST_DRV_NAME ".ko!");
+	return ret;
+}
+
+struct usbip_host_driver host_driver = {
+	.edev_list = LIST_HEAD_INIT(host_driver.edev_list),
+	.udev_subsystem = "usb",
+	.ops = {
+		.open = usbip_host_driver_open,
+		.close = usbip_generic_driver_close,
+		.refresh_device_list = usbip_generic_refresh_device_list,
+		.get_device = usbip_generic_get_device,
+		.read_device = read_usb_device,
+		.read_interface = read_usb_interface,
+		.is_my_device = is_my_device,
+	},
+};
diff --git a/marvell/linux/tools/usb/usbip/libsrc/usbip_host_driver.h b/marvell/linux/tools/usb/usbip/libsrc/usbip_host_driver.h
new file mode 100644
index 0000000..6ba996c
--- /dev/null
+++ b/marvell/linux/tools/usb/usbip/libsrc/usbip_host_driver.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ * Copyright (C) 2015-2016 Samsung Electronics
+ *               Igor Kotrasinski <i.kotrasinsk@samsung.com>
+ *               Krzysztof Opasiak <k.opasiak@samsung.com>
+ */
+
+#ifndef __USBIP_HOST_DRIVER_H
+#define __USBIP_HOST_DRIVER_H
+
+#include <stdint.h>
+#include "usbip_common.h"
+#include "list.h"
+#include "usbip_host_common.h"
+
+extern struct usbip_host_driver host_driver;
+
+#endif /* __USBIP_HOST_DRIVER_H */
diff --git a/marvell/linux/tools/usb/usbip/libsrc/vhci_driver.c b/marvell/linux/tools/usb/usbip/libsrc/vhci_driver.c
new file mode 100644
index 0000000..8159fd9
--- /dev/null
+++ b/marvell/linux/tools/usb/usbip/libsrc/vhci_driver.c
@@ -0,0 +1,467 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005-2007 Takahiro Hirofuchi
+ */
+
+#include "usbip_common.h"
+#include "vhci_driver.h"
+#include <limits.h>
+#include <netdb.h>
+#include <libudev.h>
+#include <dirent.h>
+#include "sysfs_utils.h"
+
+#undef  PROGNAME
+#define PROGNAME "libusbip"
+
+struct usbip_vhci_driver *vhci_driver;
+struct udev *udev_context;
+
+static struct usbip_imported_device *
+imported_device_init(struct usbip_imported_device *idev, char *busid)
+{
+	struct udev_device *sudev;
+
+	sudev = udev_device_new_from_subsystem_sysname(udev_context,
+						       "usb", busid);
+	if (!sudev) {
+		dbg("udev_device_new_from_subsystem_sysname failed: %s", busid);
+		goto err;
+	}
+	read_usb_device(sudev, &idev->udev);
+	udev_device_unref(sudev);
+
+	return idev;
+
+err:
+	return NULL;
+}
+
+static int parse_status(const char *value)
+{
+	int ret = 0;
+	char *c;
+
+	/* skip a header line */
+	c = strchr(value, '\n');
+	if (!c)
+		return -1;
+	c++;
+
+	while (*c != '\0') {
+		int port, status, speed, devid;
+		int sockfd;
+		char lbusid[SYSFS_BUS_ID_SIZE];
+		struct usbip_imported_device *idev;
+		char hub[3];
+
+		ret = sscanf(c, "%2s  %d %d %d %x %u %31s\n",
+				hub, &port, &status, &speed,
+				&devid, &sockfd, lbusid);
+
+		if (ret < 5) {
+			dbg("sscanf failed: %d", ret);
+			BUG();
+		}
+
+		dbg("hub %s port %d status %d speed %d devid %x",
+				hub, port, status, speed, devid);
+		dbg("sockfd %u lbusid %s", sockfd, lbusid);
+
+		/* if a device is connected, look at it */
+		idev = &vhci_driver->idev[port];
+		memset(idev, 0, sizeof(*idev));
+
+		if (strncmp("hs", hub, 2) == 0)
+			idev->hub = HUB_SPEED_HIGH;
+		else /* strncmp("ss", hub, 2) == 0 */
+			idev->hub = HUB_SPEED_SUPER;
+
+		idev->port	= port;
+		idev->status	= status;
+
+		idev->devid	= devid;
+
+		idev->busnum	= (devid >> 16);
+		idev->devnum	= (devid & 0x0000ffff);
+
+		if (idev->status != VDEV_ST_NULL
+		    && idev->status != VDEV_ST_NOTASSIGNED) {
+			idev = imported_device_init(idev, lbusid);
+			if (!idev) {
+				dbg("imported_device_init failed");
+				return -1;
+			}
+		}
+
+		/* go to the next line */
+		c = strchr(c, '\n');
+		if (!c)
+			break;
+		c++;
+	}
+
+	dbg("exit");
+
+	return 0;
+}
+
+#define MAX_STATUS_NAME 18
+
+static int refresh_imported_device_list(void)
+{
+	const char *attr_status;
+	char status[MAX_STATUS_NAME+1] = "status";
+	int i, ret;
+
+	for (i = 0; i < vhci_driver->ncontrollers; i++) {
+		if (i > 0)
+			snprintf(status, sizeof(status), "status.%d", i);
+
+		attr_status = udev_device_get_sysattr_value(vhci_driver->hc_device,
+							    status);
+		if (!attr_status) {
+			err("udev_device_get_sysattr_value failed");
+			return -1;
+		}
+
+		dbg("controller %d", i);
+
+		ret = parse_status(attr_status);
+		if (ret != 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int get_nports(struct udev_device *hc_device)
+{
+	const char *attr_nports;
+
+	attr_nports = udev_device_get_sysattr_value(hc_device, "nports");
+	if (!attr_nports) {
+		err("udev_device_get_sysattr_value nports failed");
+		return -1;
+	}
+
+	return (int)strtoul(attr_nports, NULL, 10);
+}
+
+static int vhci_hcd_filter(const struct dirent *dirent)
+{
+	return !strncmp(dirent->d_name, "vhci_hcd.", 9);
+}
+
+static int get_ncontrollers(void)
+{
+	struct dirent **namelist;
+	struct udev_device *platform;
+	int n;
+
+	platform = udev_device_get_parent(vhci_driver->hc_device);
+	if (platform == NULL)
+		return -1;
+
+	n = scandir(udev_device_get_syspath(platform), &namelist, vhci_hcd_filter, NULL);
+	if (n < 0)
+		err("scandir failed");
+	else {
+		for (int i = 0; i < n; i++)
+			free(namelist[i]);
+		free(namelist);
+	}
+
+	return n;
+}
+
+/*
+ * Read the given port's record.
+ *
+ * To avoid buffer overflow we will read the entire line and
+ * validate each part's size. The initial buffer is padded by 4 to
+ * accommodate the 2 spaces, 1 newline and an additional character
+ * which is needed to properly validate the 3rd part without it being
+ * truncated to an acceptable length.
+ */
+static int read_record(int rhport, char *host, unsigned long host_len,
+		char *port, unsigned long port_len, char *busid)
+{
+	int part;
+	FILE *file;
+	char path[PATH_MAX+1];
+	char *buffer, *start, *end;
+	char delim[] = {' ', ' ', '\n'};
+	int max_len[] = {(int)host_len, (int)port_len, SYSFS_BUS_ID_SIZE};
+	size_t buffer_len = host_len + port_len + SYSFS_BUS_ID_SIZE + 4;
+
+	buffer = malloc(buffer_len);
+	if (!buffer)
+		return -1;
+
+	snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport);
+
+	file = fopen(path, "r");
+	if (!file) {
+		err("fopen");
+		free(buffer);
+		return -1;
+	}
+
+	if (fgets(buffer, buffer_len, file) == NULL) {
+		err("fgets");
+		free(buffer);
+		fclose(file);
+		return -1;
+	}
+	fclose(file);
+
+	/* validate the length of each of the 3 parts */
+	start = buffer;
+	for (part = 0; part < 3; part++) {
+		end = strchr(start, delim[part]);
+		if (end == NULL || (end - start) > max_len[part]) {
+			free(buffer);
+			return -1;
+		}
+		start = end + 1;
+	}
+
+	if (sscanf(buffer, "%s %s %s\n", host, port, busid) != 3) {
+		err("sscanf");
+		free(buffer);
+		return -1;
+	}
+
+	free(buffer);
+
+	return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int usbip_vhci_driver_open(void)
+{
+	int nports;
+	struct udev_device *hc_device;
+
+	udev_context = udev_new();
+	if (!udev_context) {
+		err("udev_new failed");
+		return -1;
+	}
+
+	/* will be freed in usbip_driver_close() */
+	hc_device =
+		udev_device_new_from_subsystem_sysname(udev_context,
+						       USBIP_VHCI_BUS_TYPE,
+						       USBIP_VHCI_DEVICE_NAME);
+	if (!hc_device) {
+		err("udev_device_new_from_subsystem_sysname failed");
+		goto err;
+	}
+
+	nports = get_nports(hc_device);
+	if (nports <= 0) {
+		err("no available ports");
+		goto err;
+	}
+	dbg("available ports: %d", nports);
+
+	vhci_driver = calloc(1, sizeof(struct usbip_vhci_driver) +
+			nports * sizeof(struct usbip_imported_device));
+	if (!vhci_driver) {
+		err("vhci_driver allocation failed");
+		goto err;
+	}
+
+	vhci_driver->nports = nports;
+	vhci_driver->hc_device = hc_device;
+	vhci_driver->ncontrollers = get_ncontrollers();
+	dbg("available controllers: %d", vhci_driver->ncontrollers);
+
+	if (vhci_driver->ncontrollers <=0) {
+		err("no available usb controllers");
+		goto err;
+	}
+
+	if (refresh_imported_device_list())
+		goto err;
+
+	return 0;
+
+err:
+	udev_device_unref(hc_device);
+
+	if (vhci_driver)
+		free(vhci_driver);
+
+	vhci_driver = NULL;
+
+	udev_unref(udev_context);
+
+	return -1;
+}
+
+
+void usbip_vhci_driver_close(void)
+{
+	if (!vhci_driver)
+		return;
+
+	udev_device_unref(vhci_driver->hc_device);
+
+	free(vhci_driver);
+
+	vhci_driver = NULL;
+
+	udev_unref(udev_context);
+}
+
+
+int usbip_vhci_refresh_device_list(void)
+{
+
+	if (refresh_imported_device_list())
+		goto err;
+
+	return 0;
+err:
+	dbg("failed to refresh device list");
+	return -1;
+}
+
+
+int usbip_vhci_get_free_port(uint32_t speed)
+{
+	for (int i = 0; i < vhci_driver->nports; i++) {
+
+		switch (speed) {
+		case	USB_SPEED_SUPER:
+			if (vhci_driver->idev[i].hub != HUB_SPEED_SUPER)
+				continue;
+		break;
+		default:
+			if (vhci_driver->idev[i].hub != HUB_SPEED_HIGH)
+				continue;
+		break;
+		}
+
+		if (vhci_driver->idev[i].status == VDEV_ST_NULL)
+			return vhci_driver->idev[i].port;
+	}
+
+	return -1;
+}
+
+int usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid,
+		uint32_t speed) {
+	char buff[200]; /* what size should be ? */
+	char attach_attr_path[SYSFS_PATH_MAX];
+	char attr_attach[] = "attach";
+	const char *path;
+	int ret;
+
+	snprintf(buff, sizeof(buff), "%u %d %u %u",
+			port, sockfd, devid, speed);
+	dbg("writing: %s", buff);
+
+	path = udev_device_get_syspath(vhci_driver->hc_device);
+	snprintf(attach_attr_path, sizeof(attach_attr_path), "%s/%s",
+		 path, attr_attach);
+	dbg("attach attribute path: %s", attach_attr_path);
+
+	ret = write_sysfs_attribute(attach_attr_path, buff, strlen(buff));
+	if (ret < 0) {
+		dbg("write_sysfs_attribute failed");
+		return -1;
+	}
+
+	dbg("attached port: %d", port);
+
+	return 0;
+}
+
+static unsigned long get_devid(uint8_t busnum, uint8_t devnum)
+{
+	return (busnum << 16) | devnum;
+}
+
+/* will be removed */
+int usbip_vhci_attach_device(uint8_t port, int sockfd, uint8_t busnum,
+		uint8_t devnum, uint32_t speed)
+{
+	int devid = get_devid(busnum, devnum);
+
+	return usbip_vhci_attach_device2(port, sockfd, devid, speed);
+}
+
+int usbip_vhci_detach_device(uint8_t port)
+{
+	char detach_attr_path[SYSFS_PATH_MAX];
+	char attr_detach[] = "detach";
+	char buff[200]; /* what size should be ? */
+	const char *path;
+	int ret;
+
+	snprintf(buff, sizeof(buff), "%u", port);
+	dbg("writing: %s", buff);
+
+	path = udev_device_get_syspath(vhci_driver->hc_device);
+	snprintf(detach_attr_path, sizeof(detach_attr_path), "%s/%s",
+		 path, attr_detach);
+	dbg("detach attribute path: %s", detach_attr_path);
+
+	ret = write_sysfs_attribute(detach_attr_path, buff, strlen(buff));
+	if (ret < 0) {
+		dbg("write_sysfs_attribute failed");
+		return -1;
+	}
+
+	dbg("detached port: %d", port);
+
+	return 0;
+}
+
+int usbip_vhci_imported_device_dump(struct usbip_imported_device *idev)
+{
+	char product_name[100];
+	char host[NI_MAXHOST] = "unknown host";
+	char serv[NI_MAXSERV] = "unknown port";
+	char remote_busid[SYSFS_BUS_ID_SIZE];
+	int ret;
+	int read_record_error = 0;
+
+	if (idev->status == VDEV_ST_NULL || idev->status == VDEV_ST_NOTASSIGNED)
+		return 0;
+
+	ret = read_record(idev->port, host, sizeof(host), serv, sizeof(serv),
+			  remote_busid);
+	if (ret) {
+		err("read_record");
+		read_record_error = 1;
+	}
+
+	printf("Port %02d: <%s> at %s\n", idev->port,
+	       usbip_status_string(idev->status),
+	       usbip_speed_string(idev->udev.speed));
+
+	usbip_names_get_product(product_name, sizeof(product_name),
+				idev->udev.idVendor, idev->udev.idProduct);
+
+	printf("       %s\n",  product_name);
+
+	if (!read_record_error) {
+		printf("%10s -> usbip://%s:%s/%s\n", idev->udev.busid,
+		       host, serv, remote_busid);
+		printf("%10s -> remote bus/dev %03d/%03d\n", " ",
+		       idev->busnum, idev->devnum);
+	} else {
+		printf("%10s -> unknown host, remote port and remote busid\n",
+		       idev->udev.busid);
+		printf("%10s -> remote bus/dev %03d/%03d\n", " ",
+		       idev->busnum, idev->devnum);
+	}
+
+	return 0;
+}
diff --git a/marvell/linux/tools/usb/usbip/libsrc/vhci_driver.h b/marvell/linux/tools/usb/usbip/libsrc/vhci_driver.h
new file mode 100644
index 0000000..6c9aca2
--- /dev/null
+++ b/marvell/linux/tools/usb/usbip/libsrc/vhci_driver.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2005-2007 Takahiro Hirofuchi
+ */
+
+#ifndef __VHCI_DRIVER_H
+#define __VHCI_DRIVER_H
+
+#include <libudev.h>
+#include <stdint.h>
+
+#include "usbip_common.h"
+
+#define USBIP_VHCI_BUS_TYPE "platform"
+#define USBIP_VHCI_DEVICE_NAME "vhci_hcd.0"
+
+enum hub_speed {
+	HUB_SPEED_HIGH = 0,
+	HUB_SPEED_SUPER,
+};
+
+struct usbip_imported_device {
+	enum hub_speed hub;
+	uint8_t port;
+	uint32_t status;
+
+	uint32_t devid;
+
+	uint8_t busnum;
+	uint8_t devnum;
+
+	/* usbip_class_device list */
+	struct usbip_usb_device udev;
+};
+
+struct usbip_vhci_driver {
+
+	/* /sys/devices/platform/vhci_hcd */
+	struct udev_device *hc_device;
+
+	int ncontrollers;
+	int nports;
+	struct usbip_imported_device idev[];
+};
+
+
+extern struct usbip_vhci_driver *vhci_driver;
+
+int usbip_vhci_driver_open(void);
+void usbip_vhci_driver_close(void);
+
+int  usbip_vhci_refresh_device_list(void);
+
+
+int usbip_vhci_get_free_port(uint32_t speed);
+int usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid,
+		uint32_t speed);
+
+/* will be removed */
+int usbip_vhci_attach_device(uint8_t port, int sockfd, uint8_t busnum,
+		uint8_t devnum, uint32_t speed);
+
+int usbip_vhci_detach_device(uint8_t port);
+
+int usbip_vhci_imported_device_dump(struct usbip_imported_device *idev);
+
+#endif /* __VHCI_DRIVER_H */