lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:	Wed, 22 Jun 2011 11:34:08 +0300
From:	Tatyana Brokhman <tlinder@...eaurora.org>
To:	balbi@...com
Cc:	linux-usb@...r.kernel.org, linux-arm-msm@...r.kernel.org,
	ablay@...eaurora.org, Tatyana Brokhman <tlinder@...eaurora.org>,
	linux-kernel@...r.kernel.org (open list)
Subject: [RFC/PATCH/RESEND 1/3] usb unittests framework: test files

This patch includes the tests that should be compiled with the
GoogleTest framework.

Signed-off-by: Tatyana Brokhman <tlinder@...eaurora.org>

---
 tools/usb/unittests/make/Makefile          |  132 ++
 tools/usb/unittests/make/autoconfig.sh     |  118 ++
 tools/usb/unittests/usb/UASP_CMD_tests.cc  | 2140 ++++++++++++++++++++++++++++
 tools/usb/unittests/usb/UASP_TM_tests.cc   | 1207 ++++++++++++++++
 tools/usb/unittests/usb/UASP_tests.h       |  434 ++++++
 tools/usb/unittests/usb/composite_tests.cc | 1646 +++++++++++++++++++++
 tools/usb/unittests/usb/composite_tests.h  |   65 +
 tools/usb/unittests/usb/g_serial_tests.cc  |  198 +++
 tools/usb/unittests/usb/g_serial_tests.h   |   68 +
 tools/usb/unittests/usb/hs_expected_desc.h |  164 +++
 tools/usb/unittests/usb/libusb_utils.cc    |  358 +++++
 tools/usb/unittests/usb/libusb_utils.h     |  149 ++
 tools/usb/unittests/usb/ss_expected_desc.h |  291 ++++
 tools/usb/unittests/usb/streams_tests.cc   |  243 ++++
 tools/usb/unittests/usb/streams_tests.h    |   51 +
 tools/usb/unittests/usb/usb_devel_mode.cc  |  185 +++
 tools/usb/unittests/usb/usb_devel_mode.h   |   50 +
 tools/usb/unittests/usb/usb_tests.cc       |  651 +++++++++
 tools/usb/unittests/usb/usb_tests.h        |  146 ++
 tools/usb/unittests/usb/usb_tests_main.cc  |   83 ++
 tools/usb/unittests/usb/ut_config.h        |   89 ++
 21 files changed, 8468 insertions(+), 0 deletions(-)
 create mode 100644 tools/usb/unittests/make/Makefile
 create mode 100644 tools/usb/unittests/make/autoconfig.sh
 create mode 100644 tools/usb/unittests/usb/UASP_CMD_tests.cc
 create mode 100644 tools/usb/unittests/usb/UASP_TM_tests.cc
 create mode 100644 tools/usb/unittests/usb/UASP_tests.h
 create mode 100644 tools/usb/unittests/usb/composite_tests.cc
 create mode 100644 tools/usb/unittests/usb/composite_tests.h
 create mode 100644 tools/usb/unittests/usb/g_serial_tests.cc
 create mode 100644 tools/usb/unittests/usb/g_serial_tests.h
 create mode 100644 tools/usb/unittests/usb/hs_expected_desc.h
 create mode 100644 tools/usb/unittests/usb/libusb_utils.cc
 create mode 100644 tools/usb/unittests/usb/libusb_utils.h
 create mode 100644 tools/usb/unittests/usb/ss_expected_desc.h
 create mode 100644 tools/usb/unittests/usb/streams_tests.cc
 create mode 100644 tools/usb/unittests/usb/streams_tests.h
 create mode 100644 tools/usb/unittests/usb/usb_devel_mode.cc
 create mode 100644 tools/usb/unittests/usb/usb_devel_mode.h
 create mode 100644 tools/usb/unittests/usb/usb_tests.cc
 create mode 100644 tools/usb/unittests/usb/usb_tests.h
 create mode 100644 tools/usb/unittests/usb/usb_tests_main.cc
 create mode 100644 tools/usb/unittests/usb/ut_config.h

diff --git a/tools/usb/unittests/make/Makefile b/tools/usb/unittests/make/Makefile
new file mode 100644
index 0000000..3f4986e
--- /dev/null
+++ b/tools/usb/unittests/make/Makefile
@@ -0,0 +1,132 @@
+# A Makefile for building Google Test and USB30 tests.
+#
+# SYNOPSIS:
+#
+#   make [all]  - makes everything.
+#   make TARGET - makes the given target.
+#   make clean  - removes all files generated by make.
+#
+# Befor building the code the folowing env. variables needs to be set:
+# GTEST - Pointer to the root of Google Tests
+# KERNEL - Pointer to the Kernel code the test are about to be ran on
+#
+
+# Points to the root of Google Test, relative to where this file is.
+GTEST_DIR = $(GTEST)
+
+# Where to find usb tests code.
+USER_DIR = ../usb
+
+# Where to find kernel code.
+KERNEL_DIR = $(KERNEL)
+
+USB_INC_DIR = $(KERNEL_DIR)/include/linux/usb
+
+LINUX_INC_DIR = $(KERNEL_DIR)/arch/x86/include/asm
+
+# Flags passed to the preprocessor.
+CPPFLAGS += -I$(GTEST_DIR) -I$(GTEST_DIR)/include -I$(LIBUSB_INC)
+CPPFLAGS += -I$(KERNEL_DIR)/include
+#CPPFLAGS += -I$(KERNEL_DIR)/arch/x86/include
+
+# Flags passed to the C++ compiler.
+CXXFLAGS += -g -Wall -Wextra -m32
+
+LIBUSB_LIB = $(LIBUSB)/lib
+LFLAGS = -L/usr/lib32 -lstdc++ -L$(LIBUSB_LIB) -lusb-1.0 -lpthread
+
+# All tests produced by this Makefile.  Remember to add new tests you
+# created to the list.
+TESTS = usb_tests
+
+
+# All Google Test headers.  Usually you shouldn't change this
+# definition.
+GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
+                $(GTEST_DIR)/include/gtest/internal/*.h
+
+
+KERNEL_HEADERS = $(USB_INC_DIR)/*.h
+
+
+LIBUSB_INC = $(LIBUSB)/include/libusb-1.0
+LIBUSB_HEADERS = $(LIBUSB_INC)/libusb.h
+
+# House-keeping build targets.
+
+all : $(TESTS)
+
+clean :
+	rm -f $(TESTS) gtest.a gtest_main.a *.o
+
+# Builds gtest.a and gtest_main.a.
+
+# Usually you shouldn't tweak such internal variables, indicated by a
+# trailing _.
+GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)
+
+# For simplicity and to avoid depending on Google Test's
+# implementation details, the dependencies specified below are
+# conservative and not optimized.  This is fine as Google Test
+# compiles fast and for ordinary users its source rarely changes.
+gtest-all.o : $(GTEST_SRCS_)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(GTEST_DIR)/src/gtest-all.cc
+
+gtest_main.o : $(GTEST_SRCS_)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(GTEST_DIR)/src/gtest_main.cc
+
+gtest.a : gtest-all.o
+	$(AR) $(ARFLAGS) $@ $^
+
+gtest_main.a : gtest-all.o gtest_main.o
+	$(AR) $(ARFLAGS) $@ $^
+
+# Builds a sample test.  A test should link with either gtest.a or
+# gtest_main.a, depending on whether it defines its own main()
+# function.
+
+libusb_utils.o : $(USER_DIR)/libusb_utils.cc \
+                     $(USER_DIR)/libusb_utils.h $(KERNEL_HEADERS) \
+                     $(GTEST_HEADERS) $(LIBUSB_HEADERS)
+		$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/libusb_utils.cc
+
+composite_tests.o : $(USER_DIR)/composite_tests.cc \
+                     $(USER_DIR)/composite_tests.h $(KERNEL_HEADERS) \
+                     $(GTEST_HEADERS) $(LIBUSB_HEADERS)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/composite_tests.cc
+
+g_serial_tests.o : $(USER_DIR)/g_serial_tests.cc \
+                     $(USER_DIR)/g_serial_tests.h $(KERNEL_HEADERS) \
+                     $(GTEST_HEADERS)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/g_serial_tests.cc
+
+streams_tests.o : $(USER_DIR)/streams_tests.cc \
+                     $(USER_DIR)/streams_tests.h $(KERNEL_HEADERS) \
+                     $(GTEST_HEADERS)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/streams_tests.cc
+
+UASP_CMD_tests.o : $(USER_DIR)/UASP_CMD_tests.cc \
+                     $(USER_DIR)/UASP_tests.h $(KERNEL_HEADERS) \
+                     $(GTEST_HEADERS)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/UASP_CMD_tests.cc
+
+
+UASP_TM_tests.o : $(USER_DIR)/UASP_TM_tests.cc \
+                     $(USER_DIR)/UASP_tests.h $(KERNEL_HEADERS) \
+                     $(GTEST_HEADERS)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/UASP_TM_tests.cc
+
+usb_tests.o : $(USER_DIR)/usb_tests.cc $(GTEST_HEADERS)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/usb_tests.cc
+
+usb_tests_main.o : $(USER_DIR)/usb_tests_main.cc $(GTEST_HEADERS)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/usb_tests_main.cc
+
+usb_devel_mode.o : $(USER_DIR)/usb_devel_mode.cc $(GTEST_HEADERS)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/usb_devel_mode.cc
+
+usb_tests : g_serial_tests.o usb_tests.o usb_tests_main.o gtest.a \
+    composite_tests.o libusb_utils.o usb_devel_mode.o UASP_CMD_tests.o \
+    UASP_TM_tests.o streams_tests.o
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LFLAGS) $^ -o $@
+
diff --git a/tools/usb/unittests/make/autoconfig.sh b/tools/usb/unittests/make/autoconfig.sh
new file mode 100644
index 0000000..b8e90ff
--- /dev/null
+++ b/tools/usb/unittests/make/autoconfig.sh
@@ -0,0 +1,118 @@
+#!/bin/bash
+# A Script to configure the kernel .config file
+
+cat .config | sed -e 's/# CONFIG_BLK_DEV_INITRD is not set/CONFIG_BLK_DEV_INITRD=y/' > .config.new
+cp .config.new .config
+cat .config | sed -e 's/# CONFIG_EXT2_FS is not set/CONFIG_EXT2_FS=y\
+# CONFIG_EXT2_FS_XATTR is not set\
+# CONFIG_EXT2_FS_XIP is not set/' > .config.new
+cp .config.new .config
+cat .config | sed -e 's/# CONFIG_DEBUG_INFO is not set/CONFIG_DEBUG_INFO=y/' > .config.new
+cp .config.new .config
+cat .config | sed -e 's/# CONFIG_USB_GADGET is not set/CONFIG_USB_GADGET=m\
+CONFIG_USB_GADGET_DEBUG=y\
+CONFIG_USB_GADGET_DEBUG_FILES=y\
+CONFIG_USB_GADGET_DEBUG_FS=y\
+CONFIG_USB_GADGET_DEBUG_MODULE_LOAD=y\
+CONFIG_USB_GADGET_VBUS_DRAW=2\
+CONFIG_USB_GADGET_SELECTED=y\
+CONFIG_USB_GADGET_DUMMY_HCD=y\
+CONFIG_USB_DUMMY_HCD=m\
+CONFIG_USB_GADGET_DUALSPEED=y\
+CONFIG_USB_ZERO=m\
+CONFIG_USB_AUDIO=m\
+CONFIG_USB_ETH=m\
+CONFIG_USB_ETH_RNDIS=y\
+CONFIG_USB_ETH_EEM=y\
+CONFIG_USB_GADGETFS=m\
+CONFIG_USB_FILE_STORAGE=m\
+CONFIG_USB_FILE_STORAGE_TEST=y\
+CONFIG_USB_MASS_STORAGE=m\
+CONFIG_USB_G_SERIAL=m\
+CONFIG_USB_MIDI_GADGET=m\
+CONFIG_USB_G_PRINTER=m\
+CONFIG_USB_CDC_COMPOSITE=m\
+CONFIG_USB_G_MULTI=m\
+CONFIG_USB_G_MULTI_RNDIS=y\
+CONFIG_USB_G_MULTI_CDC=y\
+# CONFIG_USB_GADGET_AT91 is not set\
+# CONFIG_USB_GADGET_ATMEL_USBA is not set\
+# CONFIG_USB_GADGET_FSL_USB2 is not set\
+# CONFIG_USB_GADGET_LH7A40X is not set\
+# CONFIG_USB_GADGET_OMAP is not set\
+# CONFIG_USB_GADGET_PXA25X is not set\
+# CONFIG_USB_GADGET_R8A66597 is not set\
+# CONFIG_USB_GADGET_PXA27X is not set\
+# CONFIG_USB_GADGET_S3C_HSOTG is not set\
+# CONFIG_USB_GADGET_IMX is not set\
+# CONFIG_USB_GADGET_S3C2410 is not set\
+# CONFIG_USB_GADGET_M66592 is not set\
+# CONFIG_USB_GADGET_AMD5536UDC is not set\
+# CONFIG_USB_GADGET_FSL_QE is not set\
+# CONFIG_USB_GADGET_CI13XXX is not set\
+# CONFIG_USB_GADGET_NET2280 is not set\
+# CONFIG_USB_GADGET_GOKU is not set\
+# CONFIG_USB_GADGET_LANGWELL is not set/' > .config.new
+cp .config.new .config
+
+cat .config | sed -e 's/# CONFIG_USB_ACM is not set/CONFIG_USB_ACM=y/' > .config.new
+cp .config.new .config
+cat .config | sed -e 's/# CONFIG_USB_STORAGE_DEBUG is not set/CONFIG_USB_STORAGE_DEBUG=y/' > .config.new
+cp .config.new .config
+cat .config | sed -e 's/# CONFIG_USB_SERIAL is not set/CONFIG_USB_SERIAL=y\
+CONFIG_USB_SERIAL_CONSOLE=y\
+# CONFIG_USB_EZUSB is not set\
+CONFIG_USB_SERIAL_GENERIC=y\
+# CONFIG_USB_SERIAL_AIRCABLE is not set\
+# CONFIG_USB_SERIAL_ARK3116 is not set\
+# CONFIG_USB_SERIAL_BELKIN is not set\
+# CONFIG_USB_SERIAL_CH341 is not set\
+# CONFIG_USB_SERIAL_WHITEHEAT is not set\
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set\
+# CONFIG_USB_SERIAL_CP210X is not set\
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set\
+# CONFIG_USB_SERIAL_EMPEG is not set\
+# CONFIG_USB_SERIAL_FTDI_SIO is not set\
+# CONFIG_USB_SERIAL_FUNSOFT is not set\
+# CONFIG_USB_SERIAL_VISOR is not set\
+# CONFIG_USB_SERIAL_IPAQ is not set\
+# CONFIG_USB_SERIAL_IR is not set\
+# CONFIG_USB_SERIAL_EDGEPORT is not set\
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set\
+# CONFIG_USB_SERIAL_GARMIN is not set\
+# CONFIG_USB_SERIAL_IPW is not set\
+# CONFIG_USB_SERIAL_IUU is not set\
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set\
+# CONFIG_USB_SERIAL_KEYSPAN is not set\
+# CONFIG_USB_SERIAL_KLSI is not set\
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set\
+# CONFIG_USB_SERIAL_MCT_U232 is not set\
+# CONFIG_USB_SERIAL_MOS7720 is not set\
+# CONFIG_USB_SERIAL_MOS7840 is not set\
+# CONFIG_USB_SERIAL_MOTOROLA is not set\
+# CONFIG_USB_SERIAL_NAVMAN is not set\
+# CONFIG_USB_SERIAL_PL2303 is not set\
+# CONFIG_USB_SERIAL_OTI6858 is not set\
+# CONFIG_USB_SERIAL_QCAUX is not set\
+# CONFIG_USB_SERIAL_QUALCOMM is not set\
+# CONFIG_USB_SERIAL_SPCP8X5 is not set\
+# CONFIG_USB_SERIAL_HP4X is not set\
+# CONFIG_USB_SERIAL_SAFE is not set\
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set\
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set\
+# CONFIG_USB_SERIAL_SYMBOL is not set\
+# CONFIG_USB_SERIAL_TI is not set\
+# CONFIG_USB_SERIAL_CYBERJACK is not set\
+# CONFIG_USB_SERIAL_XIRCOM is not set\
+# CONFIG_USB_SERIAL_OPTION is not set\
+# CONFIG_USB_SERIAL_OMNINET is not set\
+# CONFIG_USB_SERIAL_OPTICON is not set\
+# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set\
+# CONFIG_USB_SERIAL_DEBUG is not set/' > .config.new
+cp .config.new .config
+
+cat .config | sed -e 's/# CONFIG_USB_XHCI_HCD is not set/CONFIG_USB_XHCI_HCD=y\
+CONFIG_USB_XHCI_HCD_DEBUGGING=y/' > .config.new
+cp .config.new .config
+
+echo "DONE! Configured: CONFIG_USB_DUMMY_HCD=y"
\ No newline at end of file
diff --git a/tools/usb/unittests/usb/UASP_CMD_tests.cc b/tools/usb/unittests/usb/UASP_CMD_tests.cc
new file mode 100644
index 0000000..066219e
--- /dev/null
+++ b/tools/usb/unittests/usb/UASP_CMD_tests.cc
@@ -0,0 +1,2140 @@
+/*
+ * UASP_CMD_tests.cc - The tests in this file test the UASP COMMAND IUs
+ * handling. This file implements test to be run on a UASP supporting device.
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include "UASP_tests.h"
+#include "usb_tests.h"
+#include "usb_devel_mode.h"
+
+unsigned char reference_buf[1024] =
+"reference       reference       reference       reference    -\n"
+"reference       reference       reference       reference    -\n"
+"reference       reference       reference       reference    -\n"
+"reference       reference       reference       reference    -\n"
+"reference       reference       reference       reference    -\n"
+"reference       reference       reference       reference    -\n"
+"reference       reference       reference       reference    -\n"
+"reference       reference       reference       reference    -\n"
+"reference       reference       reference       reference    -\n"
+"reference       reference       reference       reference    -\n"
+"reference       reference       reference       reference    -\n"
+"reference       reference       reference       reference    -\n"
+"reference       reference       reference       reference    -\n"
+"reference       reference       reference       reference    -\n"
+"reference       reference       reference       reference    -\n"
+"reference       reference       reference       reference    0\n";
+
+
+/*
+ * verify_sense_iu() - prints and verifies the received sense_iu structure
+ * @buf: pointer to the sense_iu to print
+ * @length: size of the buf param
+ *
+ * Returns 0 if the status =  STATUS_GOOD
+ *         1 if the sense data is SS_OVERLAPPED_COMMANDS_ATTEMPTED
+ *         -1 otherwise
+ */
+static int verify_sense_iu(unsigned char *buf, int length)
+{
+	struct sense_iu *status_iu = (struct sense_iu *)buf;
+	unsigned long sense_data;
+	int rc = 0;
+
+	if (length != sizeof(struct sense_iu)) {
+		printf("verify_sense_iu(): length (%d) != status_iu size (%d)\n",
+		       length, sizeof(struct sense_iu));
+		return -1;
+	}
+
+	if (status_iu->iu_id != IU_ID_SENSE) {
+		printf("verify_sense_iu(): status_iu->iu_id != IU_ID_SENSE\n");
+		return -1;
+	}
+
+	switch (status_iu->status) {
+	case STATUS_GOOD:
+		printf("	Status received = STATUS_GOOD\n");
+		break;
+	case STATUS_CHECK_CONDITION:
+		printf("	Status received = STATUS_CHECK_CONDITION");
+		break;
+	case STATUS_CONDITION_MET:
+		printf("	Status received = STATUS_CONDITION_MET");
+		break;
+	case STATUS_BUSY:
+		printf("	Status received = STATUS_BUSY");
+		break;
+	case STATUS_RESERVATION_CONFLICT:
+		printf("	Status received = STATUS_RESERVATION_CONFLICT");
+		break;
+	case STATUS_TASK_SET_FULL:
+		printf("	Status received = STATUS_TASK_SET_FULL");
+		break;
+	case STATUS_ACA_ACTIVE:
+		printf("	Status received = STATUS_ACA_ACTIVE");
+		break;
+	case STATUS_TASK_ABORTED:
+		printf("	Status received = STATUS_TASK_ABORTED");
+		break;
+	default:
+		printf("	ERROR: Unknown status code!");
+	}
+	if (status_iu->status) {
+		/* Print the SENSE data*/
+		rc = -1;
+		sense_data = status_iu->sense_data[0] << 16 |
+				status_iu->sense_data[1] << 8 |
+				status_iu->sense_data[2];
+		switch (sense_data) {
+		case SS_COMMUNICATION_FAILURE:
+			printf("	SENSE DATA = SS_COMMUNICATION_FAILURE\n");
+			break;
+		case SS_INVALID_COMMAND:
+			printf("	SENSE DATA = SS_INVALID_COMMAND\n");
+			break;
+		case SS_INVALID_FIELD_IN_CDB:
+			printf("	SENSE DATA = SS_INVALID_FIELD_IN_CDB\n");
+			break;
+		case SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE:
+			printf("	SENSE DATA = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE\n");
+			break;
+		case SS_LOGICAL_UNIT_NOT_SUPPORTED:
+			printf("	SENSE DATA = SS_LOGICAL_UNIT_NOT_SUPPORTED\n");
+			break;
+		case SS_MEDIUM_NOT_PRESENT:
+			printf("	SENSE DATA = SS_MEDIUM_NOT_PRESENT\n");
+			break;
+		case SS_MEDIUM_REMOVAL_PREVENTED:
+			printf("	SENSE DATA = SS_MEDIUM_REMOVAL_PREVENTED\n");
+			break;
+		case SS_NOT_READY_TO_READY_TRANSITION:
+			rc = 0;
+			printf("	SENSE DATA = SS_NOT_READY_TO_READY_TRANSITION\n");
+			break;
+		case SS_RESET_OCCURRED:
+			printf("	SENSE DATA = SS_RESET_OCCURRED\n");
+			break;
+		case SS_SAVING_PARAMETERS_NOT_SUPPORTED:
+			printf("	SENSE DATA = SS_SAVING_PARAMETERS_NOT_SUPPORTED\n");
+			break;
+		case SS_UNRECOVERED_READ_ERROR:
+			printf("	SENSE DATA = SS_UNRECOVERED_READ_ERROR\n");
+			break;
+		case SS_WRITE_ERROR:
+			printf("	SENSE DATA = SS_WRITE_ERROR\n");
+			break;
+		case SS_WRITE_PROTECTED:
+			printf("	SENSE DATA = SS_WRITE_PROTECTED\n");
+			break;
+		case SS_OVERLAPPED_COMMANDS_ATTEMPTED:
+			printf("	SENSE DATA = SS_OVERLAPPED_COMMANDS_ATTEMPTED\n");
+			return 1;
+		default:
+			printf("	ERROR: Unrecognized sense data!\n");
+		}
+		printf(" (Press Enter to continue...)");
+		(void)getchar();
+	}
+	return rc;
+}
+
+/**
+ * print_cmdiu() - print the received command iu
+ * @cmdiu: pointer to the cmd_iu to print
+ *
+ */
+static void print_cmdiu(struct cmd_iu *cmdiu)
+{
+	printf("\ncmdiu->iu_id [%d] = %02x, \n"
+	       "cmdiu->reserved [%d] = %02x, \n"
+	       "cmdiu->ipt_tag [%d] = %d, \n"
+	       "cmdiu->forth_byte [%d] = %02x, \n"
+	       "cmdiu->reserved5 [%d] = %02x, \n"
+	       "cmdiu->length [%d] = %02x, \n"
+	       "cmdiu->reserved7 [%d] = %02x, \n"
+	       "cmdiu->lun[8] = \n"
+	       "%02x %02x %02x %02x %02x %02x %02x %02x\n"
+	       "cmdiu->cdb[16] = \n"
+	       "%02x %02x %02x %02x %02x %02x %02x %02x\n"
+	       "%02x %02x %02x %02x %02x %02x %02x %02x\n",
+	       sizeof(cmdiu->iu_id), cmdiu->iu_id,
+	       sizeof(cmdiu->reserved), cmdiu->reserved,
+	       sizeof(cmdiu->tag), cmdiu->tag,
+	       sizeof(cmdiu->b), cmdiu->b,
+	       sizeof(cmdiu->reserved5), cmdiu->reserved5,
+	       sizeof(cmdiu->length), cmdiu->length,
+	       sizeof(cmdiu->reserved7), cmdiu->reserved7,
+	       cmdiu->lun[0], cmdiu->lun[1], cmdiu->lun[2], cmdiu->lun[3],
+	       cmdiu->lun[4], cmdiu->lun[5], cmdiu->lun[6], cmdiu->lun[7],
+	       cmdiu->cdb[0], cmdiu->cdb[1], cmdiu->cdb[2], cmdiu->cdb[3],
+	       cmdiu->cdb[4], cmdiu->cdb[5], cmdiu->cdb[6], cmdiu->cdb[7],
+	       cmdiu->cdb[8], cmdiu->cdb[9], cmdiu->cdb[10], cmdiu->cdb[11],
+	       cmdiu->cdb[12], cmdiu->cdb[13], cmdiu->cdb[14], cmdiu->cdb[15]);
+}
+
+/**
+ * fill_cmd_iu() - Fills the command iu structure with given values
+ * @iu: pointer to the cmd_iu structure to fill
+ * @cdb_opcode: OpCode of the CDB to send
+ * @lun: LUN number
+ * @add_length: additional_length field of the CDB
+ *
+ */
+void fill_cmd_iu(struct cmd_iu *iu, u8 cdb_opcode, u8 lun, u8 add_length)
+{
+	memset((void *)iu, 0 ,sizeof(struct cmd_iu));
+	iu->iu_id = 0x01; /* Command iu*/
+	iu->reserved = 0;
+	iu->tag = get_next_ip_tag();
+	memset(&iu->b,0,sizeof(iu->b));
+	iu->reserved5 = 0;
+	iu->length = 6;
+
+	memset(iu->lun, 0, 8);
+	iu->lun[0] = lun; /* Workaround: Right now @init we set lun_id[0] = i */
+	iu->cdb[0] = cdb_opcode;
+	iu->cdb[1] = 0;
+	iu->cdb[2] = 0;
+	iu->cdb[3] = 0;
+	iu->cdb[4] = add_length;
+	iu->cdb[5] = 0;
+}
+
+/**
+ * receive_read_iu() - Reads a READ IU from the device.
+ * @udev: handle of the libusb device
+ * @sts: pointer to the status endpoint descriptor
+ *
+ * Used when opperating in HS mode for DATA IN commands. In SS
+ * mode replaced by ERDY.
+ *
+ * Return 0 on success, -1 otherwise
+ */
+static int receive_read_iu(struct libusb_device_handle *udev,
+				   struct libusb_endpoint_descriptor *sts,
+				   u16 tag)
+{
+	unsigned char buf[1024];
+	int transferred;
+	int ret;
+
+	if (!udev || !sts)
+		return -1;
+
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   UASP_SIZEOF_RW_READY_IU,
+				   &transferred, 2000);
+
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		return -1;
+	}
+	/* Verify the tag */
+	if (((struct rw_ready_iu*)buf)->tag != tag ||
+		((struct rw_ready_iu*)buf)->iu_id != IU_ID_READ_READY) {
+		printf("	ERROR: Received Incorrect IU!!!"
+			   " (iu_id = %d, tag = %d, expected_tag = %d)\n\n",
+			   ((struct rw_ready_iu*)buf)->iu_id,
+			   ((struct rw_ready_iu*)buf)->tag, tag);
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * exec_send_mode_sense10() - Test the MODE_SENSE10 SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * This function sends the MODE_SENSE10 SCSI command to the device and verifies
+ * the correct reply from it.
+ * It consists of several tests (according to the fields of the
+ * MODE_SENSE10 CDB) :
+ * - First test case:
+ *	   page code = 0x08 (cashing)
+ * 	   pc = 0 (page control = return current values)
+ * - Second test case:
+ *	   page code = 0x08 (cashing)
+ *	   pc = 01 (page control = return changable values)
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_send_mode_sense10(struct libusb_device *dev)
+{
+	struct cmd_iu modes_iu;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *bulkin, *sts;
+	uint8_t buf[1024];
+	int transferred;
+	int ret = -1;
+
+	/*
+	 * First test case:
+	 * page code = 0x08 (cashing)
+	 * pc = 0 (page control = return current values)
+	 *
+	 * Expected reply:
+	 * buf[0-1] - len -2 = 18 = 0x00, 0x12
+	 * buf[3] = (curlun->lun->ro ? 0x80 : 0x00) = 0x00
+	 * buf[8] = 0x08  Page code
+	 * buf[9] = 0x0a  Page length
+	 * buf[10] = 0x04 Write cache enable, Read cache not disabled,
+	 *				 No cache retention priorities
+	 * buf[12]-buf[13] = 0xffff Don't disable prefetch
+	 * buf[14-15] = 0x00 Minimum prefetch = 0
+	 * buf[16-19] =0xffff, 0xffff Maximum prefetch ceiling
+	 * reply length = 20
+	 */
+	uint8_t expected_buf_t1[20] = {0x00, 0x12, 0x00, 0x00,
+				       0x00, 0x00, 0x00, 0x00,
+				       0x08, 0x0a, 0x04, 0x00,
+				       0xff, 0xff, 0x00, 0x00,
+				       0xff, 0xff, 0xff, 0xff};
+	/*
+	 * Second test case:
+	 * page code = 0x08 (cashing)
+	 * pc = 01 (page control = return changable values)
+	 *
+	 * expected reply:
+	 * buf[0-1] - len -2 = 18 = 0x00, 0x12
+	 * buf[3] = (curlun->lun->ro ? 0x80 : 0x00); = 0x00
+	 * buf[8] = 0x08  Page code
+	 * buf[9] = 0x0a  Page length
+	 * buf[10-19] = 0x00
+	 * reply length = 20
+	 */
+	uint8_t expected_buf_t2[20] = {0x00, 0x12, 0x00, 0x00,
+				       0x00, 0x00, 0x00, 0x00,
+				       0x08, 0x0a, 0x00, 0x00,
+				       0x00, 0x00, 0x00, 0x00,
+				       0x00, 0x00, 0x00, 0x00};
+
+	if (!dev)
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_send_mode_sense10_done;
+	}
+
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	bulkin = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_DATA_IN);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+
+
+	if (!cmd_ep || !bulkin || !sts) {
+		printf("Didn't find endpoints!\n");
+		goto exec_send_mode_sense10_done;
+	}
+	memset(buf, 0, 1024);
+
+	fill_cmd_iu(&modes_iu, 0x5a, UASP_LUN_NUM, 0x10);
+
+	/* First test case: */
+	/* Fill aditional cdb fields */
+	modes_iu.cdb[2] = 0x08; /* page code = cashing, pc = 0 */
+	printf("First test case: page code = 0x08 (cashing)\n"
+	       "		 pc = 0 (page controll = return current "
+	       "values)\n");
+
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&modes_iu, CMDIU_SIZE,
+				   &transferred, 2000);
+
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_send_mode_sense10_done;
+	}
+
+	memset(buf, 0, 1024);
+
+	/* If we're working in HS mode we should receive a READ READY IU */
+	if (get_dev_speed() < USB_SPEED_SUPER &&
+		receive_read_iu(udev, sts, modes_iu.tag))
+			goto exec_send_mode_sense10_done;
+
+	printf("waiting for reply:...\n");
+	ret = libusb_bulk_transfer(udev, bulkin->bEndpointAddress,
+				   buf, 20, &transferred, 2000);
+
+	if (memcmp(buf, expected_buf_t1, 20))
+		printf("	ERROR ocured! Received incorrect reply!\n"
+		       "	buf = %02x, %02x, %02x, %02x, %02x, %02x, %02x,"
+		       " %02x,\n"
+		       "	      %02x, %02x, %02x, %02x, %02x, %02x, %02x,"
+		       " %02x\n", buf[0], buf[1], buf[2], buf[3], buf[4],
+		       buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11],
+		       buf[12], buf[13], buf[14], buf[15]);
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_send_mode_sense10_done;
+	}
+	ret = verify_sense_iu(buf, transferred);
+	if (ret)
+		goto exec_send_mode_sense10_done;
+
+	/* Second test case: */
+	/* Fill aditional cdb fields */
+	modes_iu.cdb[2] = 0x48; /* page code = cashing, pc = 1 */
+	printf("Second test case: page code = 0x08 (cashing)\n"
+	       "		 pc = 1 (page controll = return changble "
+	       "values)\n");
+
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&modes_iu, CMDIU_SIZE,
+				   &transferred, 2000);
+
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_send_mode_sense10_done;
+	}
+
+	memset(buf, 0, 1024);
+
+	/* If we're working in HS mode we should receive a READ READY IU */
+	if (get_dev_speed() < USB_SPEED_SUPER &&
+		receive_read_iu(udev, sts, modes_iu.tag))
+			goto exec_send_mode_sense10_done;
+
+	printf("waiting for reply:...\n");
+	ret = libusb_bulk_transfer(udev, bulkin->bEndpointAddress,
+				   buf, 20, &transferred, 2000);
+
+	if (memcmp(buf, expected_buf_t2, 20))
+		printf("	ERROR ocured! Received incorrect reply!\n"
+		       "	buf = %02x, %02x, %02x, %02x, %02x, %02x, %02x,"
+		       " %02x,\n"
+		       "	      %02x, %02x, %02x, %02x, %02x, %02x, %02x,"
+		       " %02x\n", buf[0], buf[1], buf[2], buf[3], buf[4],
+		       buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11],
+		       buf[12], buf[13], buf[14], buf[15]);
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret)
+		printf("libusb_bulk_transfer error = %d\n",ret);
+	else
+		ret = verify_sense_iu(buf, transferred);
+
+exec_send_mode_sense10_done:
+	libusb_close(udev);
+	return ret;
+}
+
+/**
+ * exec_send_mode_sense() - Test the MODE_SENSE(6) SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * This function sends the MODE_SENSE(6) SCSI command to the device and
+ * verifies the correct reply from it.
+ * It consists of several tests (according to the fields of the MODE_SENSE CDB):
+ * - First test case:
+ *	   page code = 0x08 (cashing)
+ * 	   pc = 0 (page control = return current values)
+ * - Second test case:
+ *	   page code = 0x08 (cashing)
+ *	   pc = 01 (page control = return changable values)
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_send_mode_sense(struct libusb_device *dev)
+{
+	struct cmd_iu modes_iu;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *bulkin, *sts;
+	uint8_t buf[1024];
+	int transferred;
+	int ret = -1;
+
+	/*
+	 * First test case:
+	 * page code = 0x08 (cashing)
+	 * pc = 0 (page control = return current values)
+	 *
+	 * Expected reply:
+	 * buf[0] - len -1 = 15
+	 * buf[2] = (curlun->lun->ro ? 0x80 : 0x00); = 0x00
+	 * buf[4] = 0x08  Page code
+	 * buf[5] = 0x0a  Page length
+	 * buf[6] = 0x04 Write cache enable, Read cache not disabled,
+	 *				 No cache retention priorities
+	 * buf[8]-buf[9] = 0xffff Don't disable prefetch
+	 * buf[10-11] = 0x00 Minimum prefetch = 0
+	 * buf[12-15] =0xffff, 0xffff Maximum prefetch ceiling
+	 * reply length = 16
+	 */
+	uint8_t expected_buf_t1[16] = {0x0f, 0x00, 0x00, 0x00,
+				       0x08, 0x0a, 0x04, 0x00,
+				       0xff, 0xff, 0x00, 0x00,
+				       0xff, 0xff, 0xff, 0xff};
+	/*
+	 * Second test case:
+	 * page code = 0x08 (cashing)
+	 * pc = 01 (page control = return changable values)
+	 *
+	 * Expected reply:
+	 * buf[0] - len -1 = 15
+	 * buf[2] = (curlun->lun->ro ? 0x80 : 0x00); = 0x00
+	 * buf[4] = 0x08  Page code
+	 * buf[5] = 0x0a  Page length
+	 * buf[6-15] = 0x00
+	 * reply length = 16
+	 */
+	uint8_t expected_buf_t2[16] = {0x0f, 0x00, 0x00, 0x00,
+				       0x08, 0x0a, 0x00, 0x00,
+				       0x00, 0x00, 0x00, 0x00,
+				       0x00, 0x00, 0x00, 0x00};
+
+	if (!dev)
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_send_mode_sense_done;
+	}
+
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	bulkin = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_DATA_IN);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+
+
+	if (!cmd_ep || !bulkin || !sts) {
+		printf("Didn't find endpoints!\n");
+		goto exec_send_mode_sense_done;
+	}
+	memset(buf, 0, 1024);
+
+	fill_cmd_iu(&modes_iu, 0x1a, UASP_LUN_NUM, 0x10);
+
+	/* First test case: */
+	/* Fill aditional cdb fields */
+	modes_iu.cdb[2] = 0x08; /* page code = cashing, pc = 0 */
+	printf("First test case: page code = 0x08 (cashing)\n"
+	       "		 pc = 0 (page controll = return current "
+	       "values)\n");
+
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&modes_iu, CMDIU_SIZE,
+				   &transferred, 2000);
+
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_send_mode_sense_done;
+	}
+
+	memset(buf, 0, 1024);
+
+	/* If we're working in HS mode we should receive a READ READY IU */
+	if (get_dev_speed() < USB_SPEED_SUPER &&
+		receive_read_iu(udev, sts, modes_iu.tag))
+			goto exec_send_mode_sense_done;
+
+	printf("waiting for reply:...\n");
+	ret = libusb_bulk_transfer(udev, bulkin->bEndpointAddress,
+				   buf, 16, &transferred, 2000);
+
+	if (memcmp(buf, expected_buf_t1, 16))
+		printf("	ERROR ocured! Received incorrect reply!\n"
+		       "	buf = %02x, %02x, %02x, %02x, %02x, %02x, %02x,"
+		       " %02x,\n"
+		       "	      %02x, %02x, %02x, %02x, %02x, %02x, %02x,"
+		       " %02x\n", buf[0], buf[1], buf[2], buf[3], buf[4],
+		       buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11],
+		       buf[12], buf[13], buf[14], buf[15]);
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_send_mode_sense_done;
+	}
+	ret = verify_sense_iu(buf, transferred);
+	if (ret)
+		goto exec_send_mode_sense_done;
+
+	/* Second test case: */
+	/* Fill aditional cdb fields */
+	modes_iu.cdb[2] = 0x48; /* page code = cashing, pc = 1 */
+	printf("Second test case: page code = 0x08 (cashing)\n"
+	       "		 pc = 1 (page controll = return changble "
+	       "values)\n");
+
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&modes_iu, CMDIU_SIZE,
+				   &transferred, 2000);
+
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_send_mode_sense_done;
+	}
+
+	memset(buf, 0, 1024);
+	/* If we're working in HS mode we should receive a READ READY IU */
+	if (get_dev_speed() < USB_SPEED_SUPER &&
+		receive_read_iu(udev, sts, modes_iu.tag))
+			goto exec_send_mode_sense_done;
+
+	printf("waiting for reply:...\n");
+	ret = libusb_bulk_transfer(udev, bulkin->bEndpointAddress,
+				   buf, 16, &transferred, 2000);
+
+	if (memcmp(buf, expected_buf_t2, 16))
+		printf("	ERROR ocured! Received incorrect reply!\n"
+		       "	buf = %02x, %02x, %02x, %02x, %02x, %02x, %02x,"
+		       " %02x,\n"
+		       "	      %02x, %02x, %02x, %02x, %02x, %02x, %02x,"
+		       " %02x\n", buf[0], buf[1], buf[2], buf[3], buf[4],
+		       buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11],
+		       buf[12], buf[13], buf[14], buf[15]);
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret)
+		printf("libusb_bulk_transfer error = %d\n",ret);
+	else
+		ret = verify_sense_iu(buf, transferred);
+
+exec_send_mode_sense_done:
+	libusb_close(udev);
+	return ret;
+}
+
+/**
+ * exec_send_prevent_allow_removal() - Test the PREVENT_ALLOW_MEDIA_REMOVAL
+ * SCSI command
+ * @dev:pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_send_prevent_allow_removal(struct libusb_device *dev)
+{
+	struct cmd_iu prev_allow_iu;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *sts;
+	uint8_t buf[1024];
+	int transferred;
+	int ret = -1;
+
+	if (!dev)
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_send_prevent_allow_removal_done;
+	}
+
+	memset(buf, 0, 1024);
+
+	fill_cmd_iu(&prev_allow_iu, 0x1e, UASP_LUN_NUM, 0);
+	/* Update the prevent field */
+	prev_allow_iu.cdb[4] = 0x01;
+
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+	if (!cmd_ep || !sts) {
+		printf("Didn't find endpoints!\n");
+		goto exec_send_prevent_allow_removal_done;
+	}
+
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&prev_allow_iu, CMDIU_SIZE,
+				   &transferred, 2000);
+
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_send_prevent_allow_removal_done;
+	}
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret)
+		printf("libusb_bulk_transfer error = %d\n",ret);
+	else
+		ret = verify_sense_iu(buf, transferred);
+
+	if (ret)
+		goto exec_send_prevent_allow_removal_done;
+
+	/*Restore the prevent_allow -> allow medium removal */
+	printf("Restoring to 'allow medium removal'...\n");
+	prev_allow_iu.cdb[4] = 0x00;
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&prev_allow_iu, CMDIU_SIZE,
+				   &transferred, 2000);
+
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_send_prevent_allow_removal_done;
+	}
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret)
+		printf("libusb_bulk_transfer error = %d\n",ret);
+	else
+		ret = verify_sense_iu(buf, transferred);
+
+exec_send_prevent_allow_removal_done:
+	libusb_close(udev);
+	return ret;
+}
+
+/**
+ * exec_send_read_capacity() - Test the READ_CAPACITY SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * This function sends the READ_CAPACITY SCSI command to the device and
+ * verifies the correct reply from it.
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_send_read_capacity(struct libusb_device *dev)
+{
+	struct cmd_iu readc_iu;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *bulkin, *sts;
+	uint8_t buf[1024];
+	int transferred;
+	int ret = -1;
+
+	unsigned long lba, block_length ;
+
+	if (!dev)
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_send_read_capacity_done;
+	}
+
+	memset(buf, 0, 1024);
+
+	fill_cmd_iu(&readc_iu, 0x25, UASP_LUN_NUM, 0);
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	bulkin = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_DATA_IN);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+
+	if (!cmd_ep || !bulkin || !sts) {
+		printf("Didn't find endpoints!\n");
+		goto exec_send_read_capacity_done;
+	}
+
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&readc_iu, CMDIU_SIZE,
+				   &transferred, 2000);
+
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_send_read_capacity_done;
+	}
+
+	/* If we're working in HS mode we should receive a READ READY IU */
+	if (get_dev_speed() < USB_SPEED_SUPER &&
+		receive_read_iu(udev, sts, readc_iu.tag))
+			goto exec_send_read_capacity_done;
+
+	printf("waiting for reply:...\n");
+	ret = libusb_bulk_transfer(udev, bulkin->bEndpointAddress,
+				   buf, 8, &transferred, 2000);
+	lba = IUGETDW(&buf[0]);
+	block_length = IUGETDW(&buf[4]);
+	printf("reply received:\n"
+	       "	LBA = %d,	Block Length = %d\n",
+	       (int)lba, (int)block_length);
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret)
+		printf("libusb_bulk_transfer error = %d\n",ret);
+	else
+		ret = verify_sense_iu(buf, transferred);
+
+exec_send_read_capacity_done:
+	libusb_close(udev);
+	return ret;
+}
+
+/**
+ * exec_send_inquiry() - Test the INQUIRY SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * This function sends the INQUIRY SCSI command to the device and verifies the
+ * correct reply from it.
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_send_inquiry(struct libusb_device *dev)
+{
+	struct cmd_iu inq_iu;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *bulkin, *sts;
+	unsigned char buf[1024];
+	int transferred;
+	int ret = -1;
+
+	char vendor_id[9];
+	char prod_id[17];
+	int *prod_level;
+
+	if (!dev)
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_send_inquiry_done;
+	}
+
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	bulkin = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_DATA_IN);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+
+	if (!cmd_ep || !bulkin || !sts) {
+		printf("Didn't find endpoints!\n");
+		goto exec_send_inquiry_done;
+	}
+
+	memset(buf, 0, 1024);
+	fill_cmd_iu(&inq_iu, 0x12, UASP_LUN_NUM, 0x24);
+
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&inq_iu, CMDIU_SIZE,
+				   &transferred, 2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_send_inquiry_done;
+	}
+
+	/* If we're working in HS mode we should receive a READ READY IU */
+	if (get_dev_speed() < USB_SPEED_SUPER &&
+		receive_read_iu(udev,sts,inq_iu.tag))
+			goto exec_send_inquiry_done;
+
+	printf("waiting for reply:...\n");
+	ret = libusb_bulk_transfer(udev, bulkin->bEndpointAddress,
+				   buf, CMDIU_SIZE, &transferred, 2000);
+
+	printf("reply received: size = %d, ret=%d\n", transferred, ret);
+	memcpy(vendor_id,&(buf[8]),sizeof(vendor_id));
+	memcpy(prod_id,&(buf[16]),sizeof(prod_id));
+	prod_level = (int*)&(buf[32]);
+	printf("     Vendor identification (ASCII)[8-15]: %s\n"
+	      "     Product identification (ASCII)[16-31]: %s\n"
+	      "     Product revision level[32-35]: %x\n", &buf[8], prod_id,
+		*prod_level);
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret)
+		printf("libusb_bulk_transfer error = %d\n",ret);
+	else
+		ret = verify_sense_iu(buf, transferred);
+
+exec_send_inquiry_done:
+	libusb_close(udev);
+    return ret;
+}
+
+
+/**
+ * exec_send_request_sense() - Test the REQUEST_SENCE command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * This function sends the REQUEST_SENCE SCSI command to the device and
+ * verifies the correct reply from it.
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_send_request_sense(struct libusb_device *dev)
+{
+	struct cmd_iu sense_iu;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *bulkin, *sts;
+	unsigned char buf[1024];
+	int transferred;
+
+	int ret = -1;
+
+	if (!dev)
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_send_request_sense_done;
+	}
+
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	bulkin = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_DATA_IN);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+
+	if (!cmd_ep || !bulkin || !sts) {
+		printf("Didn't find Command BULK OUT endpoint!\n");
+		goto exec_send_request_sense_done;
+	}
+
+	memset(buf, 0, 1024);
+	fill_cmd_iu(&sense_iu, 0x03, UASP_LUN_NUM, 0x18);
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&sense_iu, CMDIU_SIZE,
+				   &transferred, 2000);
+
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_send_request_sense_done;
+	}
+
+	/* If we're working in HS mode we should receive a READ READY IU */
+	if (get_dev_speed() < USB_SPEED_SUPER &&
+		receive_read_iu(udev, sts, sense_iu.tag))
+			goto exec_send_request_sense_done;
+
+	printf("waiting for reply:...\n");
+	ret = libusb_bulk_transfer(udev, bulkin->bEndpointAddress,
+				   buf, 18, &transferred, 2000);
+
+	printf("Reply received: size = %d, ret=%d\n", transferred, ret);
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret)
+		printf("libusb_bulk_transfer error = %d\n",ret);
+	else
+		ret = verify_sense_iu(buf, transferred);
+
+exec_send_request_sense_done:
+	libusb_close(udev);
+    return ret;
+}
+
+/**
+ * exec_test_unit_ready() - Test the TEST_UNIT_READY command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_unit_ready(struct libusb_device *dev)
+{
+	struct cmd_iu unit_ready_iu;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *sts;
+	unsigned char buf[1024];
+	int transferred;
+	int ret = -1;
+
+	if (!dev)
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_test_unit_ready_done;
+	}
+
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+
+	if (!cmd_ep || !sts) {
+		printf("Didn't find endpoints!\n");
+		goto exec_test_unit_ready_done;
+	}
+
+	memset(buf, 0, 1024);
+	fill_cmd_iu(&unit_ready_iu, 0x00, UASP_LUN_NUM, 0);
+
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&unit_ready_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_unit_ready_done;
+	}
+
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret)
+		printf("libusb_bulk_transfer error = %d\n", ret);
+	else
+		ret = verify_sense_iu(buf, transferred);
+
+exec_test_unit_ready_done:
+	libusb_close(udev);
+    return ret;
+}
+
+/**
+ * test_write() - Tests the SCSI WRITE command
+ * @dev: pointer to the libusb device to run the test on
+ * @write_iu: pointer to the cmdiu to send
+ * @data_size: size of the data to write
+ * @data_buf: the data buffer to write
+ *
+ * This function is used to test the WRITE6, WRITE10 and WRITE12 SCSI commands.
+ *
+ * Return 0 on success, -1 otherwise
+ * TODO: add write verification
+ */
+static int test_write(struct libusb_device *dev,
+			  struct cmd_iu write_iu,
+			  int data_size,
+			  unsigned char *data_buf)
+{
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *bulkout, *bulkin, *sts;
+	unsigned char buf[1024];
+	unsigned char *read_to_buf;
+
+	int transferred;
+	int ret = -1;
+
+	if (!dev)
+		return -1;
+
+	read_to_buf = (unsigned char *)malloc(data_size);
+	if (!read_to_buf) {
+		printf("	ERROR: cound't allocate memory!\n");
+		return ret;
+	}
+	/*
+	 * Prior to a write command we need to send test_unit_ready command to
+	 * verify that the device is ready for data transfer
+	 */
+	ret = exec_test_unit_ready(dev);
+	if (ret) {
+		printf("TEST_UNIT_READY failed\n");
+		goto exec_test_write_done;
+	}
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_test_write_done;
+	}
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	bulkout = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_DATA_OUT);
+	bulkin = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_DATA_IN);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+	if (!cmd_ep || !bulkout || !bulkin || !sts) {
+		printf("Didn't find endpoints!\n");
+		goto exec_test_write_done;
+	}
+
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&write_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_write_done;
+	}
+
+	/* If we're working in HS mode we should receive a WRITE READY IU */
+	if (get_dev_speed() < USB_SPEED_SUPER) {
+		memset(buf, 0, sizeof(buf));
+		ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+					   UASP_SIZEOF_RW_READY_IU,
+					   &transferred, 2000);
+
+		if (ret) {
+			printf("libusb_bulk_transfer error = %d\n",ret);
+			goto exec_test_write_done;
+		}
+		/* Verify the tag */
+		if (((struct rw_ready_iu*)buf)->tag != write_iu.tag ||
+		    ((struct rw_ready_iu*)buf)->iu_id != IU_ID_WRITE_READY) {
+			printf("	ERROR: Received Incorrect IU!!!"
+			       " (iu_id = %d, tag = %d, expected_tag = %d)\n\n",
+			       ((struct rw_ready_iu*)buf)->iu_id,
+			       ((struct rw_ready_iu*)buf)->tag, write_iu.tag);
+			goto exec_test_write_done;
+		}
+	}
+
+	printf("	Sending Data:...\n");
+	ret = libusb_bulk_transfer(udev, bulkout->bEndpointAddress,
+				   data_buf, data_size, &transferred, 2000);
+
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_write_done;
+	}
+	printf("data sent: transferred = %d, data_size = %d\n",
+	       transferred, data_size);
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_write_done;
+	}
+	ret = verify_sense_iu(buf, transferred);
+
+exec_test_write_done:
+	free(read_to_buf);
+	libusb_close(udev);
+    return ret;
+}
+
+/**
+ * test_read() - Tests the SCSI READ command
+ * @dev: pointer to the libusb device to run the test on
+ * @write_iu: pointer to the cmdiu to send
+ * @data_size: size of the data to read
+ *
+ * This function is used to test the READ6, READ10 and READ12 SCSI commands.
+ *
+ * Return 0 on success, -1 otherwise
+ */
+static int test_read(struct libusb_device *dev,
+			  struct cmd_iu read_iu,
+			  int data_size)
+{
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *bulkin, *sts;
+	unsigned char buf[1024];
+	int transferred;
+	int ret = -1;
+
+	if (!dev)
+		return -1;
+
+	/*
+	 * Prior to a read command we need to send test_unit_ready command to
+	 * verify that the device is ready for data transfer
+	 */
+	ret = exec_test_unit_ready(dev);
+	if (ret) {
+		printf("TEST_UNIT_READY failed\n");
+		goto exec_test_read_done;
+	}
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_test_read_done;
+	}
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	bulkin = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_DATA_IN);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+	if (!cmd_ep || !bulkin || !sts) {
+		printf("Didn't find endpoints!\n");
+		goto exec_test_read_done;
+	}
+
+	memset(buf, 0, sizeof(buf));
+
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&read_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_read_done;
+	}
+
+	/* If we're working in HS mode we should receive a READ READY IU */
+	if (get_dev_speed() < USB_SPEED_SUPER &&
+		receive_read_iu(udev, sts, read_iu.tag))
+			goto exec_test_read_done;
+
+	printf("waiting for data...\n");
+	ret = libusb_bulk_transfer(udev, bulkin->bEndpointAddress,
+				   buf, data_size, &transferred, 2000);
+
+	printf("Reply received: size = %d, ret=%d\n", transferred, ret);
+	if (transferred != sizeof(reference_buf))
+		printf("\n	ERROR: Received less data then expected (%d)\n",
+		      sizeof(reference_buf));
+	else
+		if (memcmp(buf, reference_buf, sizeof(reference_buf)))
+			printf("	Receieved not-expected data:\n%s\n",
+			       buf);
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret)
+		printf("libusb_bulk_transfer error = %d\n",ret);
+	else
+		ret = verify_sense_iu(buf, transferred);
+
+exec_test_read_done:
+	libusb_close(udev);
+    return ret;
+}
+
+int reset_data_file(struct libusb_device *dev)
+{
+	unsigned char buf[1024];
+	struct cmd_iu write_iu;
+	int i = 0;
+
+	printf("	Reseting data file...\n");
+	/* Fill the data buffer*/
+	for (i = 0; i < 1024; i++) {
+		if (!(i % 100))
+			buf[i] = 0x0a;
+		else
+			buf[i] = 0x41;
+	}
+	fill_cmd_iu(&write_iu, 0x0a, UASP_LUN_NUM, 0);
+	write_iu.cdb[4] = 0x02; /* write 2 blocks (of 512 bytes) */
+	return test_write(dev, write_iu, 1024, buf);
+}
+
+/**
+ * exec_test_read6() - Test the READ6 SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_read6(struct libusb_device *dev)
+{
+	struct cmd_iu read6_iu;
+	struct cmd_iu write_iu;
+
+	int rc = 0;
+
+	/* Write the reference_buf to the file prior to reading */
+	fill_cmd_iu(&write_iu, 0x0a, UASP_LUN_NUM, 0);
+	write_iu.cdb[4] = 0x02; /* write 2 blocks (of 512 bytes) */
+	rc = test_write(dev, write_iu, sizeof(reference_buf), reference_buf);
+	if (rc) {
+		printf("Failed to write reference buffer\n");
+		return rc;
+	}
+
+	/* Start reading from block 0, LBA = 0  */
+	fill_cmd_iu(&read6_iu, 0x08, UASP_LUN_NUM, 0);
+	read6_iu.cdb[4] = 0x02; /* read 2 blocks (of 512 bytes) */
+
+	rc = test_read(dev, read6_iu, 1024);
+	if (reset_data_file(dev))
+		printf("	Failed Reseting data fail!\n");
+	return rc;
+}
+
+/**
+ * exec_test_read10() - Test the READ10 SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_read10(struct libusb_device *dev)
+{
+	struct cmd_iu read10_iu;
+	struct cmd_iu write_iu;
+	int rc = 0;
+
+	/* Write the reference_buf to the file prior to reading */
+	fill_cmd_iu(&write_iu, 0x0a, UASP_LUN_NUM, 0);
+	write_iu.cdb[4] = 0x02; /* write 2 blocks (of 512 bytes) */
+	rc = test_write(dev, write_iu, sizeof(reference_buf), reference_buf);
+	if (rc) {
+		printf("Failed to write reference buffer\n");
+		return rc;
+	}
+
+	/* Start reading from block 0, LBA = 0  */
+	fill_cmd_iu(&read10_iu, 0x28, UASP_LUN_NUM, 0);
+	read10_iu.cdb[8] = 0x02; /* read 2 blocks (of 512 bytes) */
+
+	rc = test_read(dev, read10_iu, 1024);
+	if (reset_data_file(dev))
+		printf("	Failed Reseting data fail!\n");
+	return rc;
+}
+
+/**
+ * exec_test_read12() - Test the READ12 SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_read12(struct libusb_device *dev)
+{
+	struct cmd_iu read12_iu;
+	struct cmd_iu write_iu;
+	int rc = 0;
+
+	/* Write the reference_buf to the file prior to reading */
+	fill_cmd_iu(&write_iu, 0x0a, UASP_LUN_NUM, 0);
+	write_iu.cdb[4] = 0x02; /* write 2 blocks (of 512 bytes) */
+	rc = test_write(dev, write_iu, sizeof(reference_buf), reference_buf);
+	if (rc) {
+		printf("Failed to write reference buffer\n");
+		return rc;
+	}
+
+	/* Start reading from block 0, LBA = 0  */
+	fill_cmd_iu(&read12_iu, 0xa8, UASP_LUN_NUM, 0);
+	read12_iu.cdb[9] = 0x02; /* read 2 blocks (of 512 bytes) */
+
+	rc = test_read(dev, read12_iu, 1024);
+	if (reset_data_file(dev))
+		printf("	Failed Reseting data fail!\n");
+	return rc;
+}
+
+/**
+ * exec_test_write6() - Test the WRITE6 SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_write6(struct libusb_device *dev)
+{
+	struct cmd_iu write6_iu;
+	unsigned char buf[1024];
+	int i, rc;
+
+	/* Fill the data buffer*/
+	for (i = 0; i < 1024; i++) {
+		if (!(i % 100))
+			buf[i] = 0x0a;
+		else
+			buf[i] = 0x41;
+	}
+
+	/* Start reading from block 0, LBA = 0  */
+	fill_cmd_iu(&write6_iu, 0x0a, UASP_LUN_NUM, 0);
+	write6_iu.cdb[4] = 0x02; /* read 2 blocks (of 512 bytes) */
+
+	rc = test_write(dev, write6_iu, 1024, buf);
+	if (reset_data_file(dev))
+		printf("	Failed Reseting data fail!\n");
+	return rc;
+}
+
+
+/**
+ * exec_test_write10() - Test the WRITE10 SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_write10(struct libusb_device *dev)
+{
+	struct cmd_iu write10_iu;
+	unsigned char buf[1024];
+	int i, rc;
+
+	/* Fill the data buffer*/
+	for (i = 0; i < 1024; i++) {
+		if (!(i % 100))
+			buf[i] = 0x0a;
+		else
+			buf[i] = 0x42;
+	}
+
+	/* Start reading from block 0, LBA = 0  */
+	fill_cmd_iu(&write10_iu, 0x2a, UASP_LUN_NUM, 0);
+	write10_iu.cdb[8] = 0x02; /* read 2 blocks (of 512 bytes) */
+
+	rc = test_write(dev, write10_iu, 1024, buf);
+	if (reset_data_file(dev))
+		printf("	Failed Reseting data fail!\n");
+	return rc;
+}
+
+
+/**
+ * exec_test_write12() - Test the WRITE12 SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_write12(struct libusb_device *dev)
+{
+	struct cmd_iu write12_iu;
+	unsigned char buf[1024];
+	int i, rc;
+
+	/* Fill the data buffer*/
+	for (i = 0; i < 1024; i++) {
+		if (!(i % 100))
+			buf[i] = 0x0a;
+		else
+			buf[i] = 0x43;
+	}
+
+	/* Start reading from block 0, LBA = 0  */
+	fill_cmd_iu(&write12_iu, 0xaa, UASP_LUN_NUM, 0);
+	write12_iu.cdb[9] = 0x02; /* read 2 blocks (of 512 bytes) */
+
+	rc = test_write(dev, write12_iu, 1024, buf);
+	if (reset_data_file(dev))
+		printf("	Failed Reseting data fail!\n");
+	return rc;
+}
+
+/**
+ * exec_test_write_huge() - Test the WRITE10 SCSI command with alot of data
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_write_huge(struct libusb_device *dev)
+{
+	struct cmd_iu write10_iu;
+	unsigned char buf[31744];
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *bulkout, *bulkin, *sts;
+
+	int transferred, i;
+	int ret = -1;
+
+	if (!dev)
+		return -1;
+
+	/*
+	 * Prior to a write command we need to send test_unit_ready command to
+	 * verify that the device is ready for data transfer
+	 */
+	ret = exec_test_unit_ready(dev);
+	if (ret) {
+		printf("TEST_UNIT_READY failed\n");
+		goto exec_test_write_huge_done;
+	}
+
+	/* Fill the data buffer*/
+	for (i = 0; i < 31744; i++) {
+		if (!(i % 100))
+			buf[i] = 0x0a;
+		else
+			buf[i] = 0x42;
+	}
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_test_write_huge_done;
+	}
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	bulkout = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_DATA_OUT);
+	bulkin = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_DATA_IN);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+	if (!cmd_ep || !bulkout || !bulkin || !sts) {
+		printf("Didn't find endpoints!\n");
+		goto exec_test_write_huge_done;
+	}
+
+	/* Start writing from block 0, LBA = 0  */
+	fill_cmd_iu(&write10_iu, 0x2a, UASP_LUN_NUM, 0);
+	/* write 62 blocks (of 512 bytes) = 31744 bytes*/
+	write10_iu.cdb[8] = 0x3e;
+
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&write10_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_write_huge_done;
+	}
+
+		/* If we're working in HS mode we should receive a WRITE READY IU */
+	if (get_dev_speed() < USB_SPEED_SUPER) {
+		memset(buf, 0, sizeof(buf));
+		ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+					   UASP_SIZEOF_RW_READY_IU,
+					   &transferred, 2000);
+
+		if (ret) {
+			printf("libusb_bulk_transfer error = %d\n",ret);
+			goto exec_test_write_huge_done;
+		}
+		/* Verify the tag */
+		if (((struct rw_ready_iu*)buf)->tag != write10_iu.tag ||
+		    ((struct rw_ready_iu*)buf)->iu_id != IU_ID_WRITE_READY) {
+			printf("	ERROR: Received Incorrect IU!!!"
+			       " (iu_id = %d, tag = %d, expected_tag = %d)\n\n",
+			       ((struct rw_ready_iu*)buf)->iu_id,
+			       ((struct rw_ready_iu*)buf)->tag, write10_iu.tag);
+			goto exec_test_write_huge_done;
+		}
+	}
+
+	printf("	Sending Data:...\n");
+	ret = libusb_bulk_transfer(udev, bulkout->bEndpointAddress,
+				   buf, 31744, &transferred, 0);
+
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_write_huge_done;
+	}
+
+	printf("data sent: transferred = %d\n", transferred);
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_write_huge_done;
+	}
+	ret = verify_sense_iu(buf, transferred);
+
+	if (ret)
+		goto exec_test_write_huge_done;
+
+	ret = 0;
+exec_test_write_huge_done:
+	libusb_close(udev);
+	if (reset_data_file(dev))
+		printf("	Failed Reseting data fail!\n");
+	return ret;
+}
+
+/**
+ * exec_test_read_format_capacities() - Test the READ FORMAT CAPACITIES
+ * SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_read_format_capacities(struct libusb_device *dev)
+{
+	struct cmd_iu form_cap_iu;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *bulkin, *sts;
+	unsigned char buf[1024];
+	unsigned char expected_buf[12] = {0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+					  0x07, 0xa1, 0x02, 0x00, 0x02, 0x00};
+	int transferred;
+	int ret = -1;
+
+	if (!dev)
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_test_read_format_capacities_done;
+	}
+
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	bulkin = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_DATA_IN);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+
+	if (!cmd_ep || !bulkin || !sts) {
+		printf("Didn't find endpoints!\n");
+		goto exec_test_read_format_capacities_done;
+	}
+
+	memset(buf, 0, 1024);
+	fill_cmd_iu(&form_cap_iu, 0x23, UASP_LUN_NUM, 0);
+
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&form_cap_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_read_format_capacities_done;
+	}
+
+	/* If we're working in HS mode we should receive a READ READY IU */
+	if (get_dev_speed() < USB_SPEED_SUPER &&
+		receive_read_iu(udev, sts, form_cap_iu.tag))
+			goto exec_test_read_format_capacities_done;
+
+	printf("waiting for reply:...\n");
+	ret = libusb_bulk_transfer(udev, bulkin->bEndpointAddress,
+				   buf, 12, &transferred, 2000);
+
+	if (memcmp(expected_buf, buf, 12)) {
+		printf("Received incorrect reply:\n"
+			"	buf = %02x, %02x, %02x, %02x, %02x, %02x,\n"
+			"	      %02x, %02x, %02x, %02x, %02x, %02x\n",
+			       buf[0], buf[1], buf[2], buf[3], buf[4],
+			       buf[5], buf[6], buf[7], buf[8], buf[9],
+			       buf[10], buf[11]);
+	} else
+		printf("Received expected data\n");
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret){
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_read_format_capacities_done;
+	}
+	ret = verify_sense_iu(buf, transferred);
+	if (ret)
+		goto exec_test_read_format_capacities_done;
+	ret = 0;
+exec_test_read_format_capacities_done:
+	libusb_close(udev);
+    return ret;
+}
+
+/**
+ * exec_test_start_stop() - Test the TEST_START_STOP_UNIT command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ *
+ * TODO: this test isn't full. It doesn't check that the unit was indeed
+ * started/ejected etc. It just verifies the completion status.
+ */
+int exec_test_start_stop(struct libusb_device *dev)
+{
+	struct cmd_iu start_stop_iu, sense_iu;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *bulkin, *sts;
+	unsigned char buf[1024];
+	int transferred;
+	int ret = -1;
+
+	if (!dev)
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_test_start_stop_done;
+	}
+
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	bulkin = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_DATA_IN);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+
+	if (!cmd_ep || !sts || !bulkin) {
+		printf("Didn't find endpoints!\n");
+		goto exec_test_start_stop_done;
+	}
+
+	memset(buf, 0, 1024);
+	fill_cmd_iu(&start_stop_iu, 0x1b, UASP_LUN_NUM, 0);
+
+	/* First test case (LoEj,Start) = 00 (stop motor) */
+	printf("	First test case (LoEj,Start) = 00 (stop motor)\n");
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&start_stop_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_start_stop_done;
+	}
+
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret){
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_start_stop_done;
+	}
+	ret = verify_sense_iu(buf, transferred);
+	if (ret)
+		goto exec_test_start_stop_done;
+
+	/* Second test case (LoEj,Start) = 01 (start motor) */
+	printf("	Second test case (LoEj,Start) = 01 (start motor)\n");
+	start_stop_iu.cdb[4] = 0x01;
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&start_stop_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_start_stop_done;
+	}
+
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_start_stop_done;
+	}
+	ret = verify_sense_iu(buf, transferred);
+	if (ret)
+		goto exec_test_start_stop_done;
+
+	/* Third test case (LoEj,Start) = 10 (Eject media) */
+	printf("	Third test case (LoEj,Start) = 10 (Eject media)\n");
+	start_stop_iu.cdb[4] = 0x02;
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&start_stop_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_start_stop_done;
+	}
+
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret){
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_start_stop_done;
+	}
+	ret = verify_sense_iu(buf, transferred);
+	if (ret)
+		goto exec_test_start_stop_done;
+
+	/*
+	 * After the media is ejected the lun is closed. We need to re-open
+	 * it manualy in order to be able to continue working with it
+	 */
+	ret = usb_tests_write_gadget_sysfs_file_str((char *)"lun0/file",
+					(char *)"/root/back_storage_file.txt");
+	if (ret) {
+		printf("Write to device_attr(file) failed %d \n",ret);
+		goto exec_test_start_stop_done;
+	}
+
+	/* After the LUN was re-opened, issue a REQUEST SENSE first */
+	printf("Issue REQUEST SENSE...\n");
+	fill_cmd_iu(&sense_iu, 0x03, UASP_LUN_NUM, 0x18);
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&sense_iu, CMDIU_SIZE,
+				   &transferred, 2000);
+
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_start_stop_done;
+	}
+
+	/* If we're working in HS mode we should receive a READ READY IU */
+	if (get_dev_speed() < USB_SPEED_SUPER &&
+		receive_read_iu(udev, sts, sense_iu.tag))
+			goto exec_test_start_stop_done;
+
+	ret = libusb_bulk_transfer(udev, bulkin->bEndpointAddress,
+				   buf, 18, &transferred, 2000);
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret)
+		printf("libusb_bulk_transfer error = %d\n",ret);
+	else
+		ret = verify_sense_iu(buf, transferred);
+	if (ret)
+		goto exec_test_start_stop_done;
+
+	/* Forth test case (LoEj,Start) = 11 (LOAD media) */
+	printf("	Forth test case (LoEj,Start) = 11 (LOAD media)\n");
+	start_stop_iu.cdb[4] = 0x03;
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&start_stop_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_start_stop_done;
+	}
+
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret){
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_start_stop_done;
+	}
+	ret = verify_sense_iu(buf, transferred);
+	if (ret)
+		goto exec_test_start_stop_done;
+
+	ret = 0;
+exec_test_start_stop_done:
+	libusb_close(udev);
+    return ret;
+}
+
+/**
+ * exec_test_verify() - Test the VERIFY command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_verify(struct libusb_device *dev)
+{
+	struct cmd_iu verify_iu;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *sts;
+	unsigned char buf[1024];
+	int transferred;
+	int ret = -1;
+
+	if (!dev)
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_test_verify_done;
+	}
+
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+
+	if (!cmd_ep || !sts) {
+		printf("Didn't find endpoints!\n");
+		goto exec_test_verify_done;
+	}
+
+	/* First write data to the device to verify it */
+	if (exec_test_write6(dev)) {
+		printf("	ERROR: write (prior to verify) failed!\n");
+		goto exec_test_verify_done;
+	}
+
+	memset(buf, 0, 1024);
+	fill_cmd_iu(&verify_iu, 0x2f, UASP_LUN_NUM, 0);
+
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&verify_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_verify_done;
+	}
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_verify_done;
+	}
+	ret = verify_sense_iu(buf,transferred);
+	if (ret)
+		goto exec_test_verify_done;
+
+	ret = 0;
+exec_test_verify_done:
+	libusb_close(udev);
+	return ret;
+}
+
+/**
+ * exec_test_synchronize_cache() - Test the SYNCHRONIZE CACHE
+ * command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_synchronize_cache(struct libusb_device *dev)
+{
+	struct cmd_iu sync_iu;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *sts;
+	unsigned char buf[1024];
+	int transferred;
+	int ret = -1;
+
+	if (!dev)
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_test_sync_cache_done;
+	}
+
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+
+	if (!cmd_ep || !sts) {
+		printf("Didn't find endpoints!\n");
+		goto exec_test_sync_cache_done;
+	}
+
+	memset(buf, 0, 1024);
+	fill_cmd_iu(&sync_iu, 0x35, UASP_LUN_NUM, 0);
+	/* Update CDB fields */
+	sync_iu.cdb[8] = 2;
+
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&sync_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_sync_cache_done;
+	}
+
+	printf("	Reading status:...\n");
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+				   SENSEIU_SIZE, &transferred, 2000);
+
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_sync_cache_done;
+	}
+	ret = verify_sense_iu(buf,transferred);
+	if (ret)
+		goto exec_test_sync_cache_done;
+
+	ret = 0;
+exec_test_sync_cache_done:
+	libusb_close(udev);
+	return ret;
+}
+
+/**
+ * exec_test_cmd_overlapped_tag() - Verifies correct behavior in
+ * case of CMD overlapped tag attempted
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_cmd_overlapped_tag(struct libusb_device *dev)
+{
+	struct cmd_iu unit_ready_iu, tag_error_cmd;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *sts;
+	unsigned char buf[1024];
+	int transferred;
+	int ret = -1;
+
+	if (!dev)
+		return -1;
+
+	/* After a reset occured check the unit attention */
+	if (exec_send_request_sense(dev))
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_test_cmd_overlapped_tag_done;
+	}
+
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+	if (!cmd_ep || !sts) {
+		printf("Didn't find endpoints!\n");
+		goto exec_test_cmd_overlapped_tag_done;
+	}
+
+	/* Issue command for the overlapped tag condition */
+	fill_cmd_iu(&unit_ready_iu, 0x00, UASP_LUN_NUM, 0x00);
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&unit_ready_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_cmd_overlapped_tag_done;
+	}
+
+	printf("Issued TEST UNIT TEADY command...\n");
+
+	/* Now issue a CMD with the same tag */
+	fill_cmd_iu(&tag_error_cmd, 0x00, UASP_LUN_NUM, 0x00);
+	tag_error_cmd.tag = unit_ready_iu.tag;
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&tag_error_cmd,
+				   CMDIU_SIZE, &transferred, 2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_cmd_overlapped_tag_done;
+	}
+
+	printf("Issued a CMD with the same tag...\n");
+	/* read status */
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000);
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_cmd_overlapped_tag_done;
+	} else
+		ret = verify_sense_iu(buf,transferred);
+
+	if (ret != 1)
+		goto exec_test_cmd_overlapped_tag_done;
+
+	/* Verify that no additional data is about to be received */
+	if (!libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000)) {
+		printf("	ERROR: REceived additional data on "
+		       "status ep!\n");
+		ret = -1;
+		goto exec_test_cmd_overlapped_tag_done;
+	}
+
+	ret = 0;
+exec_test_cmd_overlapped_tag_done:
+	libusb_close(udev);
+	/* If test sucseded, verify that the device is functional */
+	if (!ret && exec_send_request_sense(dev)) {
+		printf("	ERROR: After overlapped tag the device is not"
+		       "functional!!!\n");
+		ret = -1;
+	}
+	return ret;
+}
diff --git a/tools/usb/unittests/usb/UASP_TM_tests.cc b/tools/usb/unittests/usb/UASP_TM_tests.cc
new file mode 100644
index 0000000..ab360ca
--- /dev/null
+++ b/tools/usb/unittests/usb/UASP_TM_tests.cc
@@ -0,0 +1,1207 @@
+/*
+ * UASP_TM_tests.cc - The tests in this file test the UASP TASK MANAGEMENT IUs
+ * handling. This file implements test to be run on a UASP supporting device.
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include "UASP_tests.h"
+#include "usb_tests.h"
+#include "usb_devel_mode.h"
+
+struct command_status{
+	u8 code; /* for cmdiu this is CDB OpCode. For tmiu this is tm func */
+	u16 tag;
+	int is_cmdiu;
+	int expected_comp_sts;
+	int stat_received;
+};
+
+#define MAX_ACTIVE_COMMANDS 100
+static struct command_status active_cmd_arr[MAX_ACTIVE_COMMANDS];
+static int num_act_cmd = 0;
+
+static void reset_active_cmd_arr()
+{
+	int i=0;
+	for (i = 0; i < MAX_ACTIVE_COMMANDS; i++) {
+		active_cmd_arr[i].code = 0;
+		active_cmd_arr[i].tag = 0;
+		active_cmd_arr[i].is_cmdiu = 0;
+		active_cmd_arr[i].expected_comp_sts = -1;
+	}
+	num_act_cmd = 0;
+}
+
+static void add_cmd_to_arr(u8 code,
+			   u16 tag,
+			   int is_cmdiu,
+			   int expected_comp_sts)
+{
+	active_cmd_arr[num_act_cmd].code = code;
+	active_cmd_arr[num_act_cmd].tag = tag;
+	active_cmd_arr[num_act_cmd].is_cmdiu = is_cmdiu;
+	active_cmd_arr[num_act_cmd].expected_comp_sts = expected_comp_sts;
+	active_cmd_arr[num_act_cmd++].stat_received = 0;
+}
+
+static int find_cmd_in_arr(u16 tag){
+	int i;
+	for (i = 0; i < num_act_cmd; i++)
+		if (active_cmd_arr[i].tag == tag)
+			return i;
+	return -1;
+}
+
+static int analize_received_status(unsigned char *buf)
+{
+	struct sense_iu *sense;
+	struct response_iu *response;
+	u16 tag;
+	int is_cmdiu;
+	int cmd_index;
+	int status;
+
+	if (buf[0] == 0x03) {
+		sense = (struct sense_iu*)buf;
+		tag = sense->tag;
+		is_cmdiu = 1;
+		status = sense->status;
+	} else if (buf[0] == 0x04){
+		response = (struct response_iu *)buf;
+		tag = response->tag;
+		is_cmdiu = 0;
+		status = response->status;
+	} else {
+		printf("	ERROR: Unknoun packet received!"
+		       " (IU ID = %d)\n", buf[0]);
+		return -1;
+	}
+
+	cmd_index = find_cmd_in_arr(tag);
+	if (cmd_index == -1) {
+		printf("	ERROR: command with such iptag "
+		       "wasn't issued!\n");
+		return -1;
+	}
+	if (active_cmd_arr[cmd_index].stat_received) {
+		printf("	ERROR: Received comp status for same"
+		       " commad twise!\n");
+		return -1;
+	}
+	if (is_cmdiu && !active_cmd_arr[cmd_index].is_cmdiu) {
+		printf("	ERROR: received SENSE IU for TM IU\n");
+		return -1;
+	}
+	if (active_cmd_arr[cmd_index].expected_comp_sts != status) {
+		printf("	ERROR! Completion status isn't as "
+		       "expected!\n"
+		       "	Expected %02x	Received %02x\n",
+		       active_cmd_arr[cmd_index].expected_comp_sts, status);
+		return -1;
+	}
+	printf("	Received status for command code = %02x\n",
+	       active_cmd_arr[cmd_index].code);
+	active_cmd_arr[cmd_index].stat_received = 1;
+	return 0;
+}
+
+/**
+ * fill_tm_iu() - Fills the command iu structure with given values
+ * @iu: pointer to the tm_iu structure to fill
+ * @tm_function: TM function type to fill
+ * @lun: LUN number
+ *
+ */
+void fill_tm_iu(struct tm_iu *iu, u8 tm_function, u8 lun)
+{
+	memset((void *)iu, 0 ,sizeof(struct tm_iu));
+	iu->iu_id = 0x05; /* task management iu*/
+	iu->reserved1 = 0;
+	iu->tag = get_next_ip_tag();
+	iu->tm_function = tm_function;
+	iu->reserved5 = 0;
+	/* Reserved for all tm_functions but ABORT_TASK and QUERY_TASK */
+	iu->task_tag = 0;
+	memset(iu->lun, 0, 8);
+	iu->lun[0] = lun; /* Workaround: Right now @init we set lun_id[0] = i */
+}
+
+/**
+ * exec_test_tm_reset_lun() - Test the LOGICAL LUN RESET TM
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_tm_reset_lun(struct libusb_device *dev)
+{
+	struct tm_iu reset_lun_iu;
+	struct cmd_iu write_iu, read_iu;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *sts;
+	unsigned char buf[1024];
+	int transferred;
+	int ret = -1;
+
+	if (!dev)
+		return -1;
+
+	/* After a reset occured check the unit attention */
+	if (exec_send_request_sense(dev))
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_test_tm_reset_lun_done;
+	}
+
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+	if (!cmd_ep || !sts) {
+		printf("Didn't find endpoints!\n");
+		goto exec_test_tm_reset_lun_done;
+	}
+
+	reset_active_cmd_arr();
+
+	/* Issue 2 commands to be canceled later on by the LUN_RESET TM */
+	fill_cmd_iu(&write_iu, 0x0a, UASP_LUN_NUM, 0);
+	write_iu.cdb[4] = 0x02; /* write 2 blocks (of 512 bytes) */
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&write_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_tm_reset_lun_done;
+	}
+
+	/* No status is expected for this command */
+	add_cmd_to_arr(write_iu.cdb[0], write_iu.tag, 1, -1);
+
+	fill_cmd_iu(&read_iu, 0x08, UASP_LUN_NUM, 0);
+	read_iu.cdb[4] = 0x02; /* read 2 blocks (of 512 bytes) */
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&read_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_tm_reset_lun_done;
+	}
+
+	/* No status is expected for this command */
+	add_cmd_to_arr(read_iu.cdb[0], read_iu.tag, 1, -1);
+
+	/* Now issue the LUN_RESET TM */
+	fill_tm_iu(&reset_lun_iu, 0x08, UASP_LUN_NUM);
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&reset_lun_iu, TMIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_tm_reset_lun_done;
+	}
+
+
+	add_cmd_to_arr(reset_lun_iu.tm_function, reset_lun_iu.tag, 0,
+		       RESPONSE_TM_FUNCTION_COMPLETE);
+
+	/* read status */
+	memset(buf, 0, sizeof(buf));
+	/*
+	 * We read data according to SENSE_U size since it's bigger
+	 * than RESPONSE IU
+	 */
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000);
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_tm_reset_lun_done;
+	} else
+		ret = analize_received_status(buf);
+
+	if (ret)
+		goto exec_test_tm_reset_lun_done;
+
+	/* Verify that no additional data is about to be received */
+	if (!libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000)) {
+		printf("	ERROR: REceived additional data on "
+		       "status ep!\n");
+		ret = -1;
+		goto exec_test_tm_reset_lun_done;
+	}
+	ret = 0;
+exec_test_tm_reset_lun_done:
+	reset_active_cmd_arr();
+	libusb_close(udev);
+	return ret;
+}
+
+/**
+ * exec_test_tm_abort_task() - Test the ABORT_TASK TM
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_tm_abort_task(struct libusb_device *dev)
+{
+	struct tm_iu abort_cmd_iu;
+	struct cmd_iu write_iu;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *sts;
+	unsigned char buf[1024];
+	int transferred;
+	int ret = -1;
+
+	if (!dev)
+		return -1;
+
+	/* After a reset occured check the unit attention */
+	if (exec_send_request_sense(dev))
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_test_tm_abort_task_done;
+	}
+
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+	if (!cmd_ep || !sts) {
+		printf("Didn't find endpoints!\n");
+		goto exec_test_tm_abort_task_done;
+	}
+
+	reset_active_cmd_arr();
+
+	/* Issue a command to be canceled later on by the ABORT_TASK TM */
+	fill_cmd_iu(&write_iu, 0x0a, UASP_LUN_NUM, 0);
+	write_iu.cdb[4] = 0x02; /* write 2 blocks (of 512 bytes) */
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&write_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_tm_abort_task_done;
+	}
+
+	/* No status is expected for this command */
+	add_cmd_to_arr(write_iu.cdb[0], write_iu.tag, 1, -1);
+
+	/* Now issue the ABORT TASK TM */
+	fill_tm_iu(&abort_cmd_iu, 0x01, UASP_LUN_NUM);
+	abort_cmd_iu.task_tag = write_iu.tag;
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&abort_cmd_iu, TMIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_tm_abort_task_done;
+	}
+
+
+	add_cmd_to_arr(abort_cmd_iu.tm_function, abort_cmd_iu.tag, 0,
+		       RESPONSE_TM_FUNCTION_COMPLETE);
+
+	/* read status */
+	memset(buf, 0, sizeof(buf));
+	/*
+	 * We read data according to SENSE_U size since it's bigger
+	 * than RESPONSE IU
+	 */
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000);
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_tm_abort_task_done;
+	} else
+		ret = analize_received_status(buf);
+
+	if (ret)
+		goto exec_test_tm_abort_task_done;
+
+	/* Verify that no additional data is about to be received */
+	if (!libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000)) {
+		printf("	ERROR: REceived additional data on "
+		       "status ep!\n");
+		ret = -1;
+		goto exec_test_tm_abort_task_done;
+	}
+	ret = 0;
+
+exec_test_tm_abort_task_done:
+	reset_active_cmd_arr();
+	libusb_close(udev);
+	return ret;
+}
+
+/**
+ * exec_test_tm_abort_task_set() - Test the ABORT TASK SET TM
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_tm_abort_task_set(struct libusb_device *dev)
+{
+	struct tm_iu abort_ts_iu, query_ts_iu;
+	struct cmd_iu write_iu, read_iu;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *sts;
+	unsigned char buf[1024];
+	int transferred;
+	int ret = -1;
+
+	if (!dev)
+		return -1;
+
+	/* After a reset occured check the unit attention */
+	if (exec_send_request_sense(dev))
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_test_tm_abort_ts_done;
+	}
+
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+	if (!cmd_ep || !sts) {
+		printf("Didn't find endpoints!\n");
+		goto exec_test_tm_abort_ts_done;
+	}
+
+	reset_active_cmd_arr();
+
+	/* Issue 2 commands to be canceled later on by the ABORT_TASK_SET TM */
+	fill_cmd_iu(&write_iu, 0x0a, UASP_LUN_NUM, 0);
+	write_iu.cdb[4] = 0x02; /* write 2 blocks (of 512 bytes) */
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&write_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_tm_abort_ts_done;
+	}
+
+	/* No status is expected for this command */
+	add_cmd_to_arr(write_iu.cdb[0], write_iu.tag, 1, -1);
+
+	fill_cmd_iu(&read_iu, 0x08, UASP_LUN_NUM, 0);
+	read_iu.cdb[4] = 0x02; /* read 2 blocks (of 512 bytes) */
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&read_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_tm_abort_ts_done;
+	}
+
+	/* No status is expected for this command */
+	add_cmd_to_arr(read_iu.cdb[0], read_iu.tag, 1, -1);
+
+	/* Now issue the ABORT_TASK_SET TM */
+	fill_tm_iu(&abort_ts_iu, 0x02, UASP_LUN_NUM);
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&abort_ts_iu, TMIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_tm_abort_ts_done;
+	}
+
+
+	add_cmd_to_arr(abort_ts_iu.tm_function, abort_ts_iu.tag, 0,
+		       RESPONSE_TM_FUNCTION_COMPLETE);
+
+
+	/* Issue another TM that should not be canceled */
+	fill_tm_iu(&query_ts_iu, 0x81, UASP_LUN_NUM);
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&query_ts_iu, TMIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_tm_abort_ts_done;
+	}
+
+
+	add_cmd_to_arr(query_ts_iu.tm_function, query_ts_iu.tag, 0,
+		       RESPONSE_TM_FUNCTION_COMPLETE);
+
+	/* read status for both TM IUs issued*/
+	memset(buf, 0, sizeof(buf));
+	/*
+	 * We read data according to SENSE_U size since it's bigger
+	 * than RESPONSE IU
+	 */
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000);
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_tm_abort_ts_done;
+	} else
+		ret = analize_received_status(buf);
+
+	if (ret)
+		goto exec_test_tm_abort_ts_done;
+		memset(buf, 0, sizeof(buf));
+
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000);
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_tm_abort_ts_done;
+	} else
+		ret = analize_received_status(buf);
+
+	if (ret)
+		goto exec_test_tm_abort_ts_done;
+
+	/* Verify that no additional data is about to be received */
+	if (!libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000)) {
+		printf("	ERROR: REceived additional data on "
+		       "status ep!\n");
+		ret = -1;
+		goto exec_test_tm_abort_ts_done;
+	}
+	ret = 0;
+exec_test_tm_abort_ts_done:
+	reset_active_cmd_arr();
+	libusb_close(udev);
+	return ret;
+}
+
+/**
+ * exec_test_tm_reset_nexus() - Test the RESET NEXUS TM
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_tm_reset_nexus(struct libusb_device *dev)
+{
+	struct tm_iu reset_nexus_iu;
+	struct cmd_iu inq_iu, unit_ready_iu;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *bulkin, *sts;
+	unsigned char buf[1024];
+	int transferred;
+	int ret = -1;
+
+	if (!dev)
+		return -1;
+
+	/* After a reset occured check the unit attention */
+	if (exec_send_request_sense(dev))
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_test_tm_reset_nexus_done;
+	}
+
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	bulkin = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_DATA_IN);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+	if (!cmd_ep || !sts || !bulkin) {
+		printf("Didn't find endpoints!\n");
+		goto exec_test_tm_reset_nexus_done;
+	}
+
+	reset_active_cmd_arr();
+
+	/* Issue 2 commands to be completed befor the RESET_NEXUS TM */
+	fill_cmd_iu(&inq_iu, 0x12, UASP_LUN_NUM, 0x24);
+	printf("Sending INQUIRY command...\n");
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&inq_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_tm_reset_nexus_done;
+	}
+
+	add_cmd_to_arr(inq_iu.cdb[0], inq_iu.tag, 1, -1);
+	/* No status is expected for this command */
+	fill_cmd_iu(&unit_ready_iu, 0x00, UASP_LUN_NUM, 0);
+	printf("Sending TEST UNIT READY command...\n");
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&unit_ready_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_tm_reset_nexus_done;
+	}
+
+	/* No status is expected for this command */
+	add_cmd_to_arr(unit_ready_iu.cdb[0], unit_ready_iu.tag, 1, -1);
+
+	/* Now issue the RESET_NEXUS TM */
+	printf("Sending RESET NEXUS TM...\n");
+	fill_tm_iu(&reset_nexus_iu, 0x10, UASP_LUN_NUM);
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&reset_nexus_iu, TMIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_tm_reset_nexus_done;
+	}
+
+
+	add_cmd_to_arr(reset_nexus_iu.tm_function, reset_nexus_iu.tag, 0,
+		       RESPONSE_TM_FUNCTION_COMPLETE);
+
+	/* Try reading inquiry result - should fail */
+	/*
+	 * Due to the implementation in dummy_hcd this woun't fail.
+	 * See implementation of dummy_queue() for details
+	 */
+	memset(buf, 0, sizeof(buf));
+	printf("Try Reading INQUERY result...\n");
+	if (!libusb_bulk_transfer(udev, bulkin->bEndpointAddress,
+				   buf, CMDIU_SIZE, &transferred, 2000)){
+		printf("	ERROR: Received data on bulk ep!\n");
+		/* Un-comment if running on a real UDC
+		ret = -1;
+		goto exec_test_tm_reset_nexus_done;*/
+	}
+
+	/*
+	 * We read data according to SENSE_U size since it's bigger
+	 * than RESPONSE IU
+	 */
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000);
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_tm_reset_nexus_done;
+	} else
+		ret = analize_received_status(buf);
+
+	if (ret)
+		goto exec_test_tm_reset_nexus_done;
+
+	/* Verify that no additional data is about to be received */
+	if (!libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000)) {
+		printf("	ERROR: REceived additional data on "
+		       "status ep!\n");
+		ret = -1;
+		goto exec_test_tm_reset_nexus_done;
+	}
+
+	ret = 0;
+exec_test_tm_reset_nexus_done:
+	reset_active_cmd_arr();
+	libusb_close(udev);
+	return ret;
+}
+
+
+/**
+ * exec_test_tm_query_async_ev() - Test the QUERY ASYNC EVENT TM
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_tm_query_async_ev(struct libusb_device *dev)
+{
+	struct tm_iu query_tm_iu;
+	struct response_iu *res_iu;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *sts;
+	unsigned char buf[1024];
+	int transferred;
+	int resp_info = 0;
+	int ret = -1;
+
+	/* Reset the nexus in order for UNIT_ATTENTION to be LUN_RESET */
+	if (exec_test_tm_reset_nexus(dev))
+		return -1;
+
+	if (!dev)
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto test_tm_query_async_ev_done;
+	}
+
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+	if (!cmd_ep || !sts) {
+		printf("Didn't find endpoints!\n");
+		goto test_tm_query_async_ev_done;
+	}
+
+	reset_active_cmd_arr();
+	fill_tm_iu(&query_tm_iu, 0x82, UASP_LUN_NUM);
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&query_tm_iu, TMIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto test_tm_query_async_ev_done;
+	}
+	add_cmd_to_arr(query_tm_iu.tm_function, query_tm_iu.tag, 0,
+		       RESPONSE_TM_FUNCTION_SUCCEEDED);
+	/*
+	 * We read data according to SENSE_U size since it's bigger
+	 * than RESPONSE IU
+	 */
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000);
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto test_tm_query_async_ev_done;
+	} else
+		ret = analize_received_status(buf);
+
+	if (ret)
+		goto test_tm_query_async_ev_done;
+
+	res_iu = (struct response_iu *)buf;
+	resp_info = (res_iu->resp_info[0] << 16) |
+		    (res_iu->resp_info[1] << 8) |
+		    res_iu->resp_info[2];
+
+	if (resp_info != (SS_RESET_OCCURRED | (1 << 20)))
+		printf("	Reseived strange RESPONCE info = %06x",
+		       resp_info);
+
+	ret = 0;
+test_tm_query_async_ev_done:
+	reset_active_cmd_arr();
+	libusb_close(udev);
+	return ret;
+}
+
+/**
+ * exec_test_tm_query_task() - Test the QUERY TASK TM
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_tm_query_task(struct libusb_device *dev)
+{
+	struct tm_iu query_task_iu;
+	struct cmd_iu inq_iu;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *bulkin, *sts;
+	unsigned char buf[1024];
+	int transferred;
+	int ret = -1;
+
+	if (!dev)
+		return -1;
+
+	/* After a reset occured check the unit attention */
+	if (exec_send_request_sense(dev))
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_test_tm_query_task_done;
+	}
+
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	bulkin = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_DATA_IN);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+	if (!cmd_ep || !sts || !bulkin) {
+		printf("Didn't find endpoints!\n");
+		goto exec_test_tm_query_task_done;
+	}
+
+	reset_active_cmd_arr();
+
+	/* Issue a command to be queried later on */
+	fill_cmd_iu(&inq_iu, 0x12, UASP_LUN_NUM, 0x24);
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&inq_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_tm_query_task_done;
+	}
+
+	printf("Issued INQUERY command...\n");
+	add_cmd_to_arr(inq_iu.cdb[0], inq_iu.tag, 1, STATUS_GOOD);
+
+	/* Now issue the QUERY TASK TM */
+	fill_tm_iu(&query_task_iu, 0x80, UASP_LUN_NUM);
+	query_task_iu.task_tag = inq_iu.tag;
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&query_task_iu, TMIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_tm_query_task_done;
+	}
+
+	printf("Issued QUERY TASK TM...\n");
+	add_cmd_to_arr(query_task_iu.tm_function, query_task_iu.tag, 0,
+		       RESPONSE_TM_FUNCTION_SUCCEEDED);
+
+	/* If we're working in HS mode we should receive a READ READY IU */
+	if (get_dev_speed() < USB_SPEED_SUPER) {
+		memset(buf, 0, sizeof(buf));
+		ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+					   UASP_SIZEOF_RW_READY_IU,
+					   &transferred, 2000);
+
+		if (ret) {
+			printf("libusb_bulk_transfer error = %d\n",ret);
+			goto exec_test_tm_query_task_done;
+		}
+		/* Verify the tag */
+		if (((struct rw_ready_iu*)buf)->tag != inq_iu.tag ||
+		    ((struct rw_ready_iu*)buf)->iu_id != IU_ID_READ_READY) {
+			printf("	ERROR: Received Incorrect IU!!!"
+			       " (iu_id = %d, tag = %d, expected_tag = %d)\n\n",
+			       ((struct rw_ready_iu*)buf)->iu_id,
+			       ((struct rw_ready_iu*)buf)->tag, inq_iu.tag);
+			goto exec_test_tm_query_task_done;
+		}
+	}
+
+	/* read status of TM */
+	memset(buf, 0, sizeof(buf));
+	/*
+	 * We read data according to SENSE_U size since it's bigger
+	 * than RESPONSE IU
+	 */
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000);
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_tm_query_task_done;
+	} else {
+		ret = analize_received_status(buf);
+	}
+
+	printf("Reading INQUERY data...\n");
+	/* Complete the INQUERY command handling */
+	memset(buf, 0, sizeof(buf));
+	if (libusb_bulk_transfer(udev, bulkin->bEndpointAddress,
+				   buf, CMDIU_SIZE, &transferred, 2000)){
+		printf("	ERROR: INQUERY failed\n");
+		ret = -1;
+		goto exec_test_tm_query_task_done;
+	}
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000);
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_tm_query_task_done;
+	} else {
+		ret = analize_received_status(buf);
+	}
+
+	if (ret)
+		goto exec_test_tm_query_task_done;
+
+	/*
+	 * Issue another QUERY TASK TM. This time the result should be
+	 * COMPLETE since the command completed
+	 */
+	fill_tm_iu(&query_task_iu, 0x80, UASP_LUN_NUM);
+	query_task_iu.task_tag = inq_iu.tag;
+
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&query_task_iu, TMIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_tm_query_task_done;
+	}
+
+
+	printf("Issued seconf QUERY TASK TM...\n");
+	add_cmd_to_arr(query_task_iu.tm_function, query_task_iu.tag, 0,
+		       RESPONSE_TM_FUNCTION_COMPLETE);
+
+	/* read status */
+	memset(buf, 0, sizeof(buf));
+	/*
+	 * We read data according to SENSE_U size since it's bigger
+	 * than RESPONSE IU
+	 */
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000);
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_tm_query_task_done;
+	} else
+		ret = analize_received_status(buf);
+
+	if (ret)
+		goto exec_test_tm_query_task_done;
+
+	ret = 0;
+
+exec_test_tm_query_task_done:
+	reset_active_cmd_arr();
+	libusb_close(udev);
+	return ret;
+}
+
+
+/**
+ * exec_test_tm_query_task_set() - Test the QUERY TASK SET TM
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_tm_query_task_set(struct libusb_device *dev)
+{
+	struct tm_iu query_task_set_iu;
+	struct cmd_iu unit_ready_iu1, unit_ready_iu2;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *sts;
+	unsigned char buf[1024];
+	int transferred;
+	int ret = -1;
+
+	if (!dev)
+		return -1;
+
+	/* After a reset occured check the unit attention */
+	if (exec_send_request_sense(dev))
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_test_query_task_set_done;
+	}
+
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+	if (!cmd_ep || !sts) {
+		printf("Didn't find endpoints!\n");
+		goto exec_test_query_task_set_done;
+	}
+
+	reset_active_cmd_arr();
+
+	/* Issue 2 commands to be queried later on */
+	fill_cmd_iu(&unit_ready_iu1, 0x00, UASP_LUN_NUM, 0x00);
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&unit_ready_iu1, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_query_task_set_done;
+	}
+
+	printf("Issued TEST UNIT TEADY1 command...\n");
+	add_cmd_to_arr(unit_ready_iu1.cdb[0], unit_ready_iu1.tag, 1,
+		       STATUS_GOOD);
+
+	fill_cmd_iu(&unit_ready_iu2, 0x00, UASP_LUN_NUM, 0x00);
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&unit_ready_iu2, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_query_task_set_done;
+	}
+
+	printf("Issued TEST UNIT TEADY2 command...\n");
+	add_cmd_to_arr(unit_ready_iu2.cdb[0], unit_ready_iu2.tag, 1,
+		       STATUS_GOOD);
+
+	/* Now issue the QUERY TASK SET TM - both command are in processing */
+	fill_tm_iu(&query_task_set_iu, 0x81, UASP_LUN_NUM);
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&query_task_set_iu,
+				   TMIU_SIZE, &transferred, 2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_query_task_set_done;
+	}
+
+	printf("Issued QUERY TASK SET TM "
+	       "(both commands are in processing)...\n");
+	add_cmd_to_arr(query_task_set_iu.tm_function, query_task_set_iu.tag, 0,
+		       RESPONSE_TM_FUNCTION_SUCCEEDED);
+
+	/* read status */
+	memset(buf, 0, sizeof(buf));
+	/*
+	 * We read data according to SENSE_U size since it's bigger
+	 * than RESPONSE IU
+	 */
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000);
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_query_task_set_done;
+	} else
+		ret = analize_received_status(buf);
+
+	if (ret)
+		goto exec_test_query_task_set_done;
+
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000);
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_query_task_set_done;
+	} else
+		ret = analize_received_status(buf);
+
+	if (ret)
+		goto exec_test_query_task_set_done;
+
+
+	memset(buf, 0, sizeof(buf));
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000);
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_query_task_set_done;
+	} else
+		ret = analize_received_status(buf);
+
+	if (ret)
+		goto exec_test_query_task_set_done;
+
+	/*
+	 * Issue another QUERY TASK SET TM. This time the result should be
+	 * COMPLETE since both commands are completed
+	 */
+	fill_tm_iu(&query_task_set_iu, 0x81, UASP_LUN_NUM);
+
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&query_task_set_iu,
+				   TMIU_SIZE, &transferred, 2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_query_task_set_done;
+	}
+
+
+	printf("Issued seconf QUERY TASK SET TM...\n");
+	add_cmd_to_arr(query_task_set_iu.tm_function, query_task_set_iu.tag, 0,
+		       RESPONSE_TM_FUNCTION_COMPLETE);
+
+	/* read status */
+	memset(buf, 0, sizeof(buf));
+	/*
+	 * We read data according to SENSE_U size since it's bigger
+	 * than RESPONSE IU
+	 */
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000);
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_query_task_set_done;
+	} else
+		ret = analize_received_status(buf);
+
+	if (ret)
+		goto exec_test_query_task_set_done;
+
+	ret = 0;
+
+exec_test_query_task_set_done:
+	reset_active_cmd_arr();
+	libusb_close(udev);
+	return ret;
+}
+
+/**
+ * exec_test_tm_overlapped_tag() - Verifies correct behavior in
+ * case of TM overlapped tag attempted
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_tm_overlapped_tag(struct libusb_device *dev)
+{
+	struct tm_iu tag_error_tm;
+	struct cmd_iu unit_ready_iu;
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *cmd_ep, *sts;
+	unsigned char buf[1024];
+	int transferred;
+	int ret = -1;
+
+	if (!dev)
+		return -1;
+
+	/* After a reset occured check the unit attention */
+	if (exec_send_request_sense(dev))
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto exec_test_tm_overlapped_tag_done;
+	}
+
+	cmd_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_CMD);
+	sts = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK, 0,
+					 PIPE_ID_STS);
+	if (!cmd_ep || !sts) {
+		printf("Didn't find endpoints!\n");
+		goto exec_test_tm_overlapped_tag_done;
+	}
+
+	reset_active_cmd_arr();
+
+	/* Issue command for the overlapped tag condition */
+	fill_cmd_iu(&unit_ready_iu, 0x00, UASP_LUN_NUM, 0x00);
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&unit_ready_iu, CMDIU_SIZE,
+				   &transferred,
+				   2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_tm_overlapped_tag_done;
+	}
+
+	printf("Issued TEST UNIT TEADY command (tag = %d)...\n",
+	       unit_ready_iu.tag);
+
+	/* Now issue a TM with the same tag */
+	fill_tm_iu(&tag_error_tm, 0x81, UASP_LUN_NUM);
+	tag_error_tm.tag = unit_ready_iu.tag;
+	ret = libusb_bulk_transfer(udev, cmd_ep->bEndpointAddress,
+				   (unsigned char*)&tag_error_tm,
+				   TMIU_SIZE, &transferred, 2000);
+	if (ret) {
+		printf("Transfer error %d \n",ret);
+		goto exec_test_tm_overlapped_tag_done;
+	}
+
+	printf("Issued a TM with the same tag (= %d)...\n",
+	       tag_error_tm.tag);
+	add_cmd_to_arr(tag_error_tm.tm_function, tag_error_tm.tag, 0,
+		       RESPONSE_OVERLAPPED_TAG_ATTEMPTED);
+
+	/* read status */
+	memset(buf, 0, sizeof(buf));
+	/*
+	 * We read data according to SENSE_U size since it's bigger
+	 * than RESPONSE IU
+	 */
+	ret = libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000);
+	if (ret) {
+		printf("libusb_bulk_transfer error = %d\n",ret);
+		goto exec_test_tm_overlapped_tag_done;
+	} else
+		ret = analize_received_status(buf);
+
+	if (ret)
+		goto exec_test_tm_overlapped_tag_done;
+
+	/* Verify that no additional data is about to be received */
+	if (!libusb_bulk_transfer(udev, sts->bEndpointAddress, buf,
+			   SENSEIU_SIZE, &transferred, 2000)) {
+		printf("	ERROR: REceived additional data on "
+		       "status ep!\n");
+		ret = -1;
+		goto exec_test_tm_overlapped_tag_done;
+	}
+
+	ret = 0;
+exec_test_tm_overlapped_tag_done:
+	reset_active_cmd_arr();
+	libusb_close(udev);
+	/* If test sucseded, verify that the device is functional */
+	if (!ret && exec_send_request_sense(dev)) {
+		printf("	ERROR: After overlapped tag the device is not"
+		       "functional!!!\n");
+		ret = -1;
+	}
+	return ret;
+}
+
diff --git a/tools/usb/unittests/usb/UASP_tests.h b/tools/usb/unittests/usb/UASP_tests.h
new file mode 100644
index 0000000..7b01782
--- /dev/null
+++ b/tools/usb/unittests/usb/UASP_tests.h
@@ -0,0 +1,434 @@
+/*
+ * UASP_tests.h - This file defines tests to be run on a UASP supporting device.
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef _UASP_TESTS_H
+#define _UASP_TESTS_H
+
+extern "C" {
+#include <linux/usb/ch9.h>
+}
+
+#define IUGETDW(w) (((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3])
+
+#define SCSI_SENSE_BUFFERSIZE 96
+
+#define UASP_LUN_NUM	0
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+
+/* IU identifier summary - see table 10 of the UAS Spec */
+enum iu_id {
+	IU_ID_COMMAND			= 0x01,
+	IU_ID_SENSE			= 0x03,
+	IU_ID_RESPONSE			= 0x04,
+	IU_ID_TASK_MANAGEMENT		= 0x05,
+	IU_ID_READ_READY		= 0x06,
+	IU_ID_WRITE_READY		= 0x07,
+};
+
+/* COMMAND IU - Section 6.2.2 from UAS Spec */
+struct cmd_iu {
+	u8 iu_id;	/* should be set to 01h*/
+	u8 reserved;
+	u16 tag;	/* section 4.2 of the UAS spec*/
+
+	u8 b;
+
+	u8 reserved5; /* Should be set to 0 */
+	u8 length; /*
+		     * length is represented only by bits 2-7.
+		     * bits 0-1 are reserved
+		     */
+	u8 reserved7; /*place holder. should be 0*/
+	u8 lun[8];
+	u8 cdb[16];
+	u8 *add_cdb;	/* Additional cdb bytes*/
+};
+#define CMDIU_SIZE 36
+
+
+/* TM FUNCTION IU  - see table 19 of the UAS Spec */
+struct tm_iu {
+	u8 iu_id;	/* Should be set to 05h */
+	u8 reserved1;
+	u16 tag;	/* section 4.2 of the UAS spec*/
+	u8 tm_function; /* valid values defined in tm_function_data */
+	u8 reserved5;
+	/* Reserved for all tm_functions but ABORT_TASK and QUERY_TASK */
+	u16 task_tag;
+	u8 lun[8];
+};
+#define TMIU_SIZE 16
+
+/* SENSE IU -	section	6.2.5 of the UAS spec */
+struct sense_iu {
+	u8 iu_id;	/* should be 0x03h*/
+	u8 reserved1;
+	u16 tag;	/* section 4.2 of the UAS spec*/
+	u16 status_qual;
+	u8 status;	/* Status code*/
+	u8 rsvd8[6];
+	u16 len;
+	u8 sense_data[SCSI_SENSE_BUFFERSIZE];
+};
+#define SENSEIU_SIZE (16 + SCSI_SENSE_BUFFERSIZE)
+
+/* STATUS values of SENSE IU as defined in SAM-4 */
+enum status_code_data {
+	STATUS_GOOD =			0x00,
+	STATUS_CHECK_CONDITION =	0x02,
+	STATUS_CONDITION_MET =		0x04,
+	STATUS_BUSY =			0x08,
+	STATUS_RESERVATION_CONFLICT =	0x18,
+	STATUS_TASK_SET_FULL =		0x28,
+	STATUS_ACA_ACTIVE =		0x30,
+	STATUS_TASK_ABORTED =		0x40,
+};
+
+/* RESPONSE IU - see table 17 of the UAS Spec */
+struct response_iu {
+	u8 iu_id;	/* Should be set to 04h*/
+	u8 reserved;
+	u16 tag;	/* section 4.2 of the UAS spec*/
+	u8 resp_info[3];
+	u8 status;	/* Response code*/
+};
+#define RESPONSEIU_SIZE 8
+
+/* Response code values of RESPONSE IU - see table 18 of the UAS Spec */
+enum response_code_data {
+	RESPONSE_TM_FUNCTION_COMPLETE		= 0x00,
+	RESPONSE_INVALID_IU			= 0x02,
+	RESPONSE_TM_FUNCTION_NOT_SUPPORTED	= 0x04,
+	RESPONSE_TM_FUNCTION_FAILED		= 0x05,
+	RESPONSE_TM_FUNCTION_SUCCEEDED		= 0x08,
+	RESPONSE_INCORRECT_LUN			= 0x09,
+	RESPONSE_OVERLAPPED_TAG_ATTEMPTED	= 0x0A,
+};
+
+/* READ/WRITE READY IU - see table 14/15 of the UAS Spec */
+struct rw_ready_iu {
+	u8 iu_id;
+	u8 reserved;
+	u16 tag;	/* section 4.2 of the UAS spec */
+};
+#define UASP_SIZEOF_RW_READY_IU 4
+
+/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
+#define SS_NO_SENSE				0
+#define SS_COMMUNICATION_FAILURE		0x040800
+#define SS_INVALID_COMMAND			0x052000
+#define SS_INVALID_FIELD_IN_CDB			0x052400
+#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE	0x052100
+#define SS_LOGICAL_UNIT_NOT_SUPPORTED		0x052500
+#define SS_MEDIUM_NOT_PRESENT			0x023a00
+#define SS_MEDIUM_REMOVAL_PREVENTED		0x055302
+#define SS_NOT_READY_TO_READY_TRANSITION	0x062800
+#define SS_RESET_OCCURRED			0x062900
+#define SS_SAVING_PARAMETERS_NOT_SUPPORTED	0x053900
+#define SS_UNRECOVERED_READ_ERROR		0x031100
+#define SS_WRITE_ERROR				0x030c02
+#define SS_WRITE_PROTECTED			0x072700
+#define SS_OVERLAPPED_COMMANDS_ATTEMPTED	0x0b4e00
+
+inline u16 get_next_ip_tag()
+{
+	static u8 my_ip_tag = 1;
+	return my_ip_tag++;
+}
+
+/**
+ * fill_cmd_iu() - Fills the command iu structure with given values
+ * @iu: pointer to the cmd_iu structure to fill
+ * @cdb_opcode: OpCode of the CDB to send
+ * @lun: LUN number
+ * @add_length: additional_length field of the CDB
+ *
+ */
+void fill_cmd_iu(struct cmd_iu *iu, u8 cdb_opcode, u8 lun, u8 add_length);
+
+/**
+ * exec_send_mode_sense10() - Test the MODE_SENSE10 SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * This function sends the MODE_SENSE10 SCSI command to the device and verifies
+ * the correct reply from it.
+ * It consists of several tests (according to the fields of the
+ * MODE_SENSE10 CDB) :
+ * - First test case:
+ *	   page code = 0x08 (cashing)
+ *	   pc = 0 (page control = return current values)
+ * - Second test case:
+ *	   page code = 0x08 (cashing)
+ *	   pc = 01 (page control = return changable values)
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_send_mode_sense10(struct libusb_device *dev);
+
+/**
+ * exec_send_mode_sense() - Test the MODE_SENSE(6) SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * This function sends the MODE_SENSE(6) SCSI command to the device and
+ * verifies the correct reply from it.
+ * It consists of several tests (according to the fields of the MODE_SENSE CDB):
+ * - First test case:
+ *	   page code = 0x08 (cashing)
+ *	   pc = 0 (page control = return current values)
+ * - Second test case:
+ *	   page code = 0x08 (cashing)
+ *	   pc = 01 (page control = return changable values)
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_send_mode_sense(struct libusb_device *dev);
+
+/**
+ * exec_send_prevent_allow_removal() - Test the PREVENT_ALLOW_MEDIA_REMOVAL
+ * SCSI command
+ * @dev:pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_send_prevent_allow_removal(struct libusb_device *dev);
+
+/**
+ * exec_send_read_capacity() - Test the READ_CAPACITY SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * This function sends the READ_CAPACITY SCSI command to the device and
+ * verifies the correct reply from it.
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_send_read_capacity(struct libusb_device *dev);
+
+/**
+ * exec_send_inquiry() - Test the INQUIRY SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * This function sends the INQUIRY SCSI command to the device and verifies the
+ * correct reply from it.
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_send_inquiry(struct libusb_device *dev);
+
+/**
+ * exec_send_request_sense() - Test the REQUEST_SENCE command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * This function sends the REQUEST_SENCE SCSI command to the device and
+ * verifies the correct reply from it.
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_send_request_sense(struct libusb_device *dev);
+
+/**
+ * exec_test_unit_ready() - Test the TEST_UNIT_READY command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_unit_ready(struct libusb_device *dev);
+
+/**
+ * exec_test_read6() - Test the READ6 SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_read6(struct libusb_device *dev);
+
+/**
+ * exec_test_read10() - Test the READ10 SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_read10(struct libusb_device *dev);
+
+/**
+ * exec_test_read12() - Test the READ12 SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_read12(struct libusb_device *dev);
+
+/**
+ * exec_test_write6() - Test the WRITE6 SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_write6(struct libusb_device *dev);
+
+/**
+ * exec_test_write10() - Test the WRITE10 SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_write10(struct libusb_device *dev);
+
+
+/**
+ * exec_test_write12() - Test the WRITE12 SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_write12(struct libusb_device *dev);
+
+/**
+ * exec_test_write_huge() - Test the WRITE10 SCSI command with alot of data
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_write_huge(struct libusb_device *dev);
+
+/**
+ * exec_test_read_format_capacities() - Test the READ FORMAT CAPACITIES
+ * SCSI command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_read_format_capacities(struct libusb_device *dev);
+
+/**
+ * exec_test_start_stop() - Test the TEST_START_STOP_UNIT command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ *
+ * TODO: this test isn't full. It doesn't check that the unit was indeed
+ * started/ejected etc. It just verifies the completion status.
+ */
+int exec_test_start_stop(struct libusb_device *dev);
+
+/**
+ * exec_test_verify() - Test the VERIFY command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_verify(struct libusb_device *dev);
+
+/**
+ * exec_test_synchronize_cache() - Test the SYNCHRONIZE CACHE
+ * command
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_synchronize_cache(struct libusb_device *dev);
+
+/**
+ * exec_test_cmd_overlapped_tag() - Verifies correct behavior in
+ * case of CMD overlapped tag attempted
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_cmd_overlapped_tag(struct libusb_device *dev);
+
+/**
+ * exec_test_tm_reset_lun() - Test the LOGICAL LUN RESET TM
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_tm_reset_lun(struct libusb_device *dev);
+
+/**
+ * exec_test_tm_abort_task() - Test the ABORT_TASK TM
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_tm_abort_task(struct libusb_device *dev);
+
+/**
+ * exec_test_tm_abort_task_set() - Test the ABORT TASK SET TM
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_tm_abort_task_set(struct libusb_device *dev);
+
+/**
+ * exec_test_tm_reset_nexus() - Test the RESET NEXUS TM
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_tm_reset_nexus(struct libusb_device *dev);
+
+/**
+ * exec_test_tm_query_async_ev() - Test the QUERY ASYNC EVENT TM
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_tm_query_async_ev(struct libusb_device *dev);
+
+/**
+ * exec_test_tm_abort_cmd() - Test the QUERY TASK TM
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_tm_query_task(struct libusb_device *dev);
+
+/**
+ * exec_test_tm_query_task_set() - Test the QUERY TASK SET TM
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_tm_query_task_set(struct libusb_device *dev);
+
+/**
+ * exec_test_tm_overlapped_tag() - Verifies correct behavior in
+ * case of TM overlapped tag attempted
+ * @dev: pointer to the libusb device to run the test on
+ *
+ * Return 0 on success, -1 otherwise
+ */
+int exec_test_tm_overlapped_tag(struct libusb_device *dev);
+#endif /*_UASP_TESTS_H*/
diff --git a/tools/usb/unittests/usb/composite_tests.cc b/tools/usb/unittests/usb/composite_tests.cc
new file mode 100644
index 0000000..ea79f36
--- /dev/null
+++ b/tools/usb/unittests/usb/composite_tests.cc
@@ -0,0 +1,1646 @@
+/*
+ * composite_tests.c - USB composite device general tests
+ *
+ * Coding convention:
+ *	External functions begin with test_ sufix.
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include "libusb_utils.h"
+#include "hs_expected_desc.h"
+#include "ss_expected_desc.h"
+#include "usb_tests.h"
+#include "ut_config.h"
+
+
+/**
+ * dump_dev_descriptor() - prints the received device descriptor
+ * @dev_desc: device descriptor to print
+ */
+static void dump_dev_descriptor(struct libusb_device_descriptor dev_desc)
+{
+	printf("Device descriptor:\n"
+	       "bLength		%5u\n"
+	       "bDescriptorType	%5u\n"
+	       "bcdUSB		0x%02x\n"
+	       "bDeviceClass	%5u\n"
+	       "bDeviceSubClass	%5u\n"
+	       "bDeviceProtocol	%5u\n"
+	       "bMaxPacketSize0	%5u\n"
+	       "idVendor	%5u\n"
+	       "idProduct	0x%02x\n"
+	       "bcdDevice	0x%02x\n"
+	       "bNumConfigurations	%5u\n",
+	       dev_desc.bLength, dev_desc.bDescriptorType, dev_desc.bcdUSB,
+	       dev_desc.bDeviceClass, dev_desc.bDeviceSubClass,
+	       dev_desc.bDeviceProtocol, dev_desc.bMaxPacketSize0,
+	       dev_desc.idVendor, dev_desc.idProduct, dev_desc.bcdDevice,
+	       dev_desc.bNumConfigurations);
+}
+
+/**
+ * dump_ep_desc() - prints the endpoint descriptor
+ * @ep_desc: endpoint descriptor to print
+ */
+static void dump_ep_desc(struct libusb_endpoint_descriptor *ep_desc)
+{
+	printf("Endpoint descriptor:\n"
+	       "bLength		%5u\n"
+	       "bDescriptorType	%5u\n"
+	       "bEndpointAddress %5u (%s endpoint)\n",
+	       ep_desc->bLength, ep_desc->bDescriptorType,
+	       ep_desc->bEndpointAddress,
+	       ((ep_desc->bEndpointAddress & LIBUSB_ENDPOINT_IN) ?
+							"IN" : "OUT"));
+
+	printf("bmAttributes	%5u	",ep_desc->bmAttributes);
+
+	switch (usb_endpoint_type(
+		(const struct usb_endpoint_descriptor *)ep_desc)){
+		case USB_ENDPOINT_XFER_CONTROL:
+			printf("Transfer Type	CONTROL\n");
+			break;
+		case USB_ENDPOINT_XFER_ISOC:
+			printf("Transfer Type	ISOC\n");
+			break;
+		case USB_ENDPOINT_XFER_BULK:
+			printf("Transfer Type	BULK\n");
+			break;
+		case USB_ENDPOINT_XFER_INT:
+			printf("Transfer Type	INTR\n");
+			break;
+		default:
+			printf("Transfer Type	Unknown\n");
+			break;
+	}
+       printf("wMaxPacketSize	0x%02x\n"
+	      "bInterval	%5u\n",
+	      ep_desc->wMaxPacketSize, ep_desc->bInterval);
+}
+
+
+/**
+ * check_ep_descriptor() - Verify the recived endpoint descriptor
+ * @ep_desc: the endpoint descriptor to check
+ * @ref_ep_desc: reference endpoint descriptor
+ *
+ * Returns 0 on sucsess -1 for failure
+ *
+ * This function checks the validity of a given endpoint descriptor of the
+ * connected device according to the supplied reference descriptor
+ */
+static int check_ep_descriptor(struct libusb_endpoint_descriptor *ep_desc,
+			       struct libusb_endpoint_descriptor *ref_ep_desc)
+{
+	if ((ep_desc->bmAttributes != ref_ep_desc->bmAttributes) ||
+	    (ep_desc->wMaxPacketSize != ref_ep_desc->wMaxPacketSize) ||
+	    (ep_desc->bInterval != ref_ep_desc->bInterval) ||
+	    ((ep_desc->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) !=
+	     (ref_ep_desc->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)))
+		return -1;
+	return 0;
+}
+
+/**
+ * check_dev_desc() - Verify the recived device descriptor
+ * @dev: libusb device to check
+ * @ref_dev_desc: reference device descriptor to check according to
+ *
+ * Returns 0 on sucsess -1 for failure
+ *
+ * This function checks the validity of the  device descriptor of the connected
+ * device according to the provided reference device descriptor
+ */
+static int check_dev_desc(libusb_device *dev,
+			  struct libusb_device_descriptor ref_dev_desc)
+{
+	struct libusb_device_descriptor dev_desc;
+	if (libusb_get_device_descriptor(dev,&dev_desc))
+	{
+		printf("Couldn't get device descriptor\n");
+		return -1;
+	}
+
+	if (dev_desc.bcdUSB != ref_dev_desc.bcdUSB ||
+	    dev_desc.bMaxPacketSize0 != ref_dev_desc.bMaxPacketSize0)
+	{
+		printf("Incompatible Device descriptor! Expected:\n");
+		dump_dev_descriptor(ref_dev_desc);
+		printf("\nReceived:\n");
+		dump_dev_descriptor(dev_desc);
+		return -1 ;
+	}
+	if (ut_debug)
+		dump_dev_descriptor(dev_desc);
+	return 0;
+}
+
+/**
+ * soursesink_test_setup() - Send a control request to setup/begin a spesific
+ * test (to be handled by f_soursesink).
+ * @udev: libusb device handle for the opened device
+ * @dev: libusb device
+ * @reques: the request code to send . Handled requests are:
+ *	 0x5e - set up the bulk buffer size
+ * @wValue: in case of request = 0x5e: size of the bulk buffer
+ *
+ * Returns: the number of bytes actually transferred on success,
+ *	LIBUSB_ERROR_TIMEOUT if the transfer timed out
+ *	LIBUSB_ERROR_PIPE if the control request was not supported by the device
+ *	LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
+ *	another LIBUSB_ERROR code on other failures
+ *
+ * NOTE: the requests sent by this function are propriatary and are handled
+ * by g_zero (in sourcesink configuration)
+ */
+int soursesink_test_setup(struct libusb_device_handle *udev,
+			  libusb_device *dev,
+			  uint8_t request,
+			  uint16_t wValue)
+{
+	if (!udev || !dev)
+		return LIBUSB_ERROR_IO;
+
+	return libusb_control_transfer(udev, LIBUSB_REQUEST_TYPE_VENDOR |
+				       LIBUSB_RECIPIENT_INTERFACE,
+				       request, wValue, 0, NULL, 0,
+				       BULK_TRANSFERR_TIMEOUT);
+}
+
+/* HS Device tests */
+
+/**
+ * check_hs_intr_desc() - Verify the recived interface descriptor
+ * @dev: libusb device to check descriptors for
+ *
+ * Returns 0 on success -1 for failure
+ *
+ * This function checks the validity of  HS Interface descriptors (including
+ * endpoint descriptors) of the connected device according to the expected
+ * descriptors in hs_expected_desc.h
+ */
+static int check_hs_intr_desc(libusb_device *dev)
+{
+	struct libusb_config_descriptor *config;
+	struct libusb_interface_descriptor *interface_desc;
+	int i,j;
+
+	config = (struct libusb_config_descriptor*)
+			malloc(sizeof(struct libusb_config_descriptor));
+	if (!config) {
+		printf("Error in allocating memory\n");
+		return -1;
+	}
+
+	if (libusb_get_active_config_descriptor(dev, &config))
+		goto check_hs_intr_err;
+
+	for (i = 0; i < config->interface->num_altsetting; i++) {
+		interface_desc = (struct libusb_interface_descriptor *)
+					&(config->interface->altsetting[i]);
+		/* Go over the interface endpoints*/
+		for (j = 0; j < interface_desc->bNumEndpoints; j++) {
+			struct libusb_endpoint_descriptor *ep_desc =
+				(struct libusb_endpoint_descriptor *)
+				&(interface_desc->endpoint[j]);
+			struct libusb_endpoint_descriptor *ref_ep_desc;
+			switch (ep_desc->bmAttributes &
+				USB_ENDPOINT_XFERTYPE_MASK){
+			case USB_ENDPOINT_XFER_CONTROL:
+				/* TODO */
+				break;
+			case USB_ENDPOINT_XFER_ISOC:
+				/* TODO */
+				break;
+			case USB_ENDPOINT_XFER_BULK:
+				if (ep_desc->bEndpointAddress &
+				    LIBUSB_ENDPOINT_IN)
+					ref_ep_desc = &hs_bulk_in_ep_desc;
+				else
+					ref_ep_desc = &hs_bulk_out_ep_desc;
+				break;
+			case USB_ENDPOINT_XFER_INT:
+				ref_ep_desc = &hs_intr_ep_desc;
+				break;
+			default:
+				printf("Unknown endpoint type!\n");
+				goto check_hs_intr_err;
+			}
+
+			if (!ref_ep_desc)
+				goto check_hs_intr_err;
+
+			if (check_ep_descriptor(ep_desc, ref_ep_desc)){
+				printf("Incompatible Endpoint descriptor! "
+				       "Expected:\n");
+				dump_ep_desc(ref_ep_desc);
+				printf("\nReceived:\n");
+				dump_ep_desc(ep_desc);
+				goto check_hs_intr_err;
+			}
+			if (ut_debug)
+				dump_ep_desc(ep_desc);
+		}
+	}
+
+	free(config);
+	return 0;
+check_hs_intr_err:
+	free(config);
+	return -1;
+}
+
+/**
+ * test_hs_descriptors() - checks the validity of HS device descriptors
+ * according to the expected descriptors in hs_expected_desc.h
+ * @dev: libusb device to check
+ *
+ * Returns 0 for sucsess -1 for failure
+ */
+int test_hs_descriptors(libusb_device *dev)
+{
+	struct libusb_device_handle *udev;
+	int ret;
+
+	if (!dev)
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto test_hs_desc_err;
+	}
+
+	if (check_dev_desc(dev, hs_device_descriptor))
+	    goto test_hs_desc_err;
+
+	if (check_hs_intr_desc(dev))
+	    goto test_hs_desc_err;
+
+	ret = 0;
+	goto test_hs_desc_done;
+
+test_hs_desc_err:
+	ret = -1;
+test_hs_desc_done:
+	libusb_close(udev);
+	return ret;
+}
+
+
+/* SS device tests */
+
+/**
+ * dump_usb_ext_cap_desc() - prints the USB 2.0 extension device capability
+ * descriptor
+ * @usb_ext_cap: the descriptor to print
+ */
+static void dump_usb_ext_cap_desc(
+	struct libusb_usb_ext_cap_descriptor *usb_ext_cap)
+{
+	if (!usb_ext_cap)
+		return;
+	printf("  USB 2.0 extension device capability descriptor:\n"
+	       "    bLength			%5u\n"
+	       "    bDescriptorType		%5u\n"
+	       "    bDevCapabilityType		%5u\n"
+	       "    bmAttributes		 0x%02x, %s\n"
+	       ,
+	       usb_ext_cap->bLength,
+	       usb_ext_cap->bDescriptorType,
+	       usb_ext_cap->bDevCapabilityType,
+	       usb_ext_cap->bmAttributes,
+	       (usb_ext_cap->bmAttributes & 0x1) ?
+	       "Supports LPM" : "Doesn't support LPM");
+}
+
+/**
+ * dump_ss_usb_cap_desc() - prints the SuperSpeed USB capability descriptor
+ * @ss_usb_cap: the descriptor to print
+ */
+static void dump_ss_usb_cap_desc(
+	struct libusb_ss_usb_cap_descriptor *ss_usb_cap)
+{
+	static const char *speed[] = {
+		"None",
+		"Low Speed",
+		"Full Speed",
+		"Low & Full Speed",
+		"High Speed",
+		"Low & High Speed",
+		"Full & High Speed",
+		"Low, Full & High Speed",
+		"5Gbps Speed",
+		"Low & 5Gbps Speed",
+		"Full & 5Gbps Speed",
+		"Low, Full & 5Gbps Speed",
+		"High & 5Gbps Speed",
+		"Low, High & 5Gbps Speed",
+		"Full, High & 5Gbps Speed",
+		"Low, Full, High & 5Gbps Speed"
+	};
+
+	if (!ss_usb_cap)
+		return;
+	printf("  SuperSpeed USB capability descriptor:\n"
+	      "    bLength			%5u\n"
+	      "    bDescriptorType		%5u\n"
+	      "    bDevCapabilityType		%5u\n"
+	      "    bmAttributes		 0x%02x, %s\n"
+	      "    wSpeedSupported		 0x%02x,\n %s%s\n"
+	      "    bFunctionalitySupport	 0x%02x,\n %s%s\n"
+	      "    bU1devExitLat		%5u\n"
+	      "    bU2devExitLat		%5u\n",
+	      ss_usb_cap->bLength,
+	      ss_usb_cap->bDescriptorType,
+	      ss_usb_cap->bDevCapabilityType,
+	      ss_usb_cap->bmAttributes,
+	      (ss_usb_cap->bmAttributes & 0x2) ?
+	       "Supports LTM" : "Doesn't support LTM",
+	      ss_usb_cap->wSpeedSupported,
+	      "	Supports ",
+	      speed[ss_usb_cap->wSpeedSupported & 0xF],
+	      ss_usb_cap->bFunctionalitySupport,
+	      "	Min speed at which all the functionality is available is ",
+	      speed[ss_usb_cap->bFunctionalitySupport & 0xF],
+	      ss_usb_cap->bU1devExitLat,
+	      ss_usb_cap->bU2DevExitLat);
+}
+
+/**
+ * dump_bos_desc()- prints the BOS descriptor.
+ * @bos: bos descriptor to print
+ */
+static void dump_bos_desc(struct libusb_bos_descriptor bos)
+{
+	printf("BOS descriptor:\n"
+	       "  bLength             	%5u\n"
+	       "  bDescriptorType     	%5u\n"
+	       "  wTotalLength        	%5u\n"
+	       "  bNumDeviceCaps      	%5u\n",
+	       bos.bLength, bos.bDescriptorType,
+	       bos.wTotalLength, bos.bNumDeviceCaps);
+}
+
+/**
+ * dump_ep_comp_desc() - prints the SS Endpoint Companion Descriptor
+ * @ep_comp_desc: the descriptor to print
+ */
+static void dump_ep_comp_desc(struct libusb_ss_ep_comp_descriptor *ep_comp_desc)
+{
+	printf("Endpoint Companion Descriptor:\n"
+	       "  bLength	      	%5u\n"
+	       "  bDescriptorType	%5u\n"
+	       "  bMaxBurst		%5u\n"
+	       "  bmAttributes		%5u\n"
+	       "  wBytesPerInterval	%5u\n",
+	       ep_comp_desc->bLength, ep_comp_desc->bDescriptorType,
+	       ep_comp_desc->bMaxBurst, ep_comp_desc->bmAttributes,
+	       ep_comp_desc->wBytesPerInterval);
+}
+
+/**
+ * check_ep_comp_descriptor() - checks the validity of endpoint companion
+ * descriptor
+ * @ep_comp_desc: the descriptor to check
+ * @ref_ep_comp_desc: reference descriptor to check according to
+ *
+ * Returns 0 for sucsess -1 for failure
+ *
+ * This function verifies the  validity of the SS endpoint companion descriptor
+ * according to the provided reference endpoint companion descriptor
+ */
+static int check_ep_comp_descriptor(
+	struct libusb_ss_ep_comp_descriptor *ep_comp_desc,
+	struct libusb_ss_ep_comp_descriptor *ref_ep_comp_desc)
+{
+	if ((ep_comp_desc->bLength != ref_ep_comp_desc->bLength) ||
+	    (ep_comp_desc->bDescriptorType !=
+		ref_ep_comp_desc->bDescriptorType) ||
+	    (ep_comp_desc->bMaxBurst != ref_ep_comp_desc->bMaxBurst) ||
+	    (ep_comp_desc->bmAttributes != ref_ep_comp_desc->bmAttributes) ||
+	    (ep_comp_desc->wBytesPerInterval !=
+		ref_ep_comp_desc->wBytesPerInterval))
+		return -1;
+	return 0;
+}
+
+/**
+ * check_ss_intr_desc() - checks the validity of the interface
+ * @descriptor dev: libusb device to check descriptors for
+ * @num_expected_strms_in_ep: the number of expected streams for IN EP's
+ *	ep_comp descriptor
+ * @num_expected_strms_out_ep: the number of expected streams for OUT EP's
+ *	ep_comp descriptor
+ *
+ * Returns 0 on sucsess -1 for failure
+ *
+ * This function checks the validity of SS Interface descriptors (including
+ * endpoint descriptors) of the connected device according to the expected
+ * descriptors in ss_expected_desc.h
+ */
+static int check_ss_intr_desc(libusb_device *dev, int num_expected_strms_in_ep,
+			      int num_expected_strms_out_ep)
+{
+	struct libusb_config_descriptor *config;
+	int i,j,k;
+
+	if (libusb_get_active_config_descriptor(dev, &config))
+		goto check_ss_intr_err;
+
+	/* Go over the configuration interfaces */
+	for (k = 0; k < config->bNumInterfaces; k++) {
+		struct libusb_interface interface = config->interface[k];
+		/* Go over interface alternate settings */
+		for (i = 0; i < interface.num_altsetting; i++) {
+			struct libusb_interface_descriptor *interface_desc =
+				(struct libusb_interface_descriptor *)
+						&(interface.altsetting[i]);
+			/* Go over the interface endpoints */
+			for (j = 0; j < interface_desc->bNumEndpoints; j++) {
+				struct libusb_endpoint_descriptor *ep_desc =
+					(struct libusb_endpoint_descriptor *)
+					&(interface_desc->endpoint[j]);
+				struct libusb_endpoint_descriptor *ref_ep_desc;
+				struct libusb_ss_ep_comp_descriptor
+							ref_ep_comp_desc_copy;
+				struct libusb_ss_ep_comp_descriptor
+							*ref_ep_comp_desc;
+				switch (ep_desc->bmAttributes &
+					USB_ENDPOINT_XFERTYPE_MASK){
+				case USB_ENDPOINT_XFER_CONTROL:
+					/* TODO */
+					break;
+				case USB_ENDPOINT_XFER_ISOC:
+					/* TODO */
+					break;
+				case USB_ENDPOINT_XFER_BULK:
+					if (ep_desc->bEndpointAddress &
+					    LIBUSB_ENDPOINT_IN){
+						ref_ep_desc =
+							&ss_bulk_in_ep_desc;
+						memcpy(&ref_ep_comp_desc_copy,
+				&ss_bulk_in_ep_comp_desc,
+				sizeof(struct libusb_ss_ep_comp_descriptor));
+					ref_ep_comp_desc_copy.bmAttributes =
+						num_expected_strms_in_ep;
+						ref_ep_comp_desc =
+							&ref_ep_comp_desc_copy;
+					}else {
+						ref_ep_desc =
+							&ss_bulk_out_ep_desc;
+						memcpy(&ref_ep_comp_desc_copy,
+				&ss_bulk_out_ep_comp_desc,
+				sizeof(struct libusb_ss_ep_comp_descriptor));
+					ref_ep_comp_desc_copy.bmAttributes =
+						num_expected_strms_out_ep;
+						ref_ep_comp_desc =
+							&ref_ep_comp_desc_copy;
+					}
+					break;
+				case USB_ENDPOINT_XFER_INT:
+					ref_ep_desc = &ss_intr_ep_desc;
+					ref_ep_comp_desc =
+						&ss_intr_ep_comp_desc;
+					break;
+				default:
+					printf("Unknown endpoint type!\n");
+					goto check_ss_intr_err;
+				}
+
+				if (!ref_ep_desc)
+					goto check_ss_intr_err;
+
+				if (check_ep_descriptor(ep_desc, ref_ep_desc)){
+					printf("Incompatible Endpoint "
+					       "descriptor! Expected:\n");
+					dump_ep_desc(ref_ep_desc);
+					printf("\nReceived:\n");
+					dump_ep_desc(ep_desc);
+					goto check_ss_intr_err;
+				}
+
+				/* Check endpoint companion descriptor */
+				if (!ep_desc->ep_comp) {
+					printf("Endpoint companion descriptor "
+					       "is missing!\n");
+					goto check_ss_intr_err;
+				}
+				if (check_ep_comp_descriptor(ep_desc->ep_comp,
+							ref_ep_comp_desc)) {
+					printf("Incompatible Endpoint "
+					       "companion descriptor! "
+					       "Expected:\n");
+					dump_ep_comp_desc(ref_ep_comp_desc);
+					printf("\nReceived:\n");
+					dump_ep_comp_desc(ep_desc->ep_comp);
+					goto check_ss_intr_err;
+				}
+
+				if (ut_debug) {
+					dump_ep_desc(ep_desc);
+					dump_ep_comp_desc(ep_desc->ep_comp);
+				}
+			}
+		}
+	}
+
+	return 0;
+check_ss_intr_err:
+	return -1;
+}
+
+/**
+ * check_bos_desc() - checks the validity of the BOS descriptor
+ * @dev: the libusb device to check the descriptors for
+ *
+ * Returns 0 for sucsess -1 for failure
+ *
+ * This function checks the SS USB device BOS descriptor (and its sub
+ * descriptors) according to the expected descriptors in ss_expected_desc.h
+ */
+static int check_bos_desc(libusb_device *dev)
+{
+	struct libusb_device_handle *udev;
+	struct libusb_bos_descriptor bos;
+	int ret;
+
+	if (!dev)
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		return -1;
+	}
+
+	memset (&bos, 0, sizeof(bos));
+	ret = libusb_utils_get_bos_desc(dev, udev, &bos);
+	if (ret < 0) {
+		perror("can't get BOS descriptor");
+		goto test_bos_error;
+	}
+
+	if (ut_debug){
+		dump_bos_desc(bos);
+		dump_usb_ext_cap_desc(bos.usb_ext_cap);
+		dump_ss_usb_cap_desc(bos.ss_usb_cap);
+	}
+
+	/* BOS descriptor */
+	if ((bos.bLength != ss_bos_desc.bLength) ||
+	    (bos.bDescriptorType != ss_bos_desc.bDescriptorType) ||
+	    (bos.wTotalLength != ss_bos_desc.wTotalLength) ||
+	    (bos.bNumDeviceCaps != ss_bos_desc.bNumDeviceCaps)){
+		printf("Incompatible BOS descriptor! Expected:\n");
+		dump_bos_desc(ss_bos_desc);
+		printf("\nReceived:\n");
+		dump_bos_desc(bos);
+		goto test_bos_error;
+	}
+
+	/* USB 2.0 extension device capability descriptor */
+	if (bos.usb_ext_cap) {
+		struct libusb_usb_ext_cap_descriptor *usb_ext_cap;
+		struct libusb_usb_ext_cap_descriptor *exp_usb_ext_cap;
+
+		usb_ext_cap = bos.usb_ext_cap;
+		exp_usb_ext_cap = &ss_usb20_ext_desc;
+		if ((usb_ext_cap->bLength != exp_usb_ext_cap->bLength) ||
+		    (usb_ext_cap->bDescriptorType !=
+			exp_usb_ext_cap->bDescriptorType) ||
+		    (usb_ext_cap->bDevCapabilityType !=
+			exp_usb_ext_cap->bDevCapabilityType) ||
+		    (usb_ext_cap->bmAttributes !=
+			exp_usb_ext_cap->bmAttributes) ||
+		    (usb_ext_cap->bmAttributes !=
+			exp_usb_ext_cap->bmAttributes)){
+			printf("Incompatible USB 2.0 extension device "
+			       "capability descriptor! Expected:\n");
+			dump_usb_ext_cap_desc(exp_usb_ext_cap);
+			printf("\nReceived:\n");
+			dump_usb_ext_cap_desc(usb_ext_cap);
+			goto test_bos_error;
+		}
+	} else
+		goto test_bos_error;
+
+	/* SuperSpeed USB capability descriptor */
+	if (bos.ss_usb_cap) {
+		struct libusb_ss_usb_cap_descriptor *ss_usb_cap;
+		struct libusb_ss_usb_cap_descriptor *exp_ss_usb_cap;
+
+		ss_usb_cap = bos.ss_usb_cap;
+		exp_ss_usb_cap = &ss_usb_capability_desc;
+		if((ss_usb_cap->bLength != exp_ss_usb_cap->bLength) ||
+		   (ss_usb_cap->bDescriptorType !=
+			exp_ss_usb_cap->bDescriptorType) ||
+		   (ss_usb_cap->bDevCapabilityType !=
+			exp_ss_usb_cap->bDevCapabilityType) ||
+		   (ss_usb_cap->bmAttributes != exp_ss_usb_cap->bmAttributes) ||
+		   (ss_usb_cap->wSpeedSupported !=
+			exp_ss_usb_cap->wSpeedSupported) ||
+		   (ss_usb_cap->bFunctionalitySupport !=
+			exp_ss_usb_cap->bFunctionalitySupport) ||
+		   (ss_usb_cap->bU1devExitLat !=
+			exp_ss_usb_cap->bU1devExitLat) ||
+		   (ss_usb_cap->bU2DevExitLat !=
+			exp_ss_usb_cap->bU2DevExitLat)){
+			printf("Incompatible SuperSpeed USB capability "
+			       "descriptor! Expected:\n");
+			dump_ss_usb_cap_desc(exp_ss_usb_cap);
+			printf("\nReceived\n");
+			dump_ss_usb_cap_desc(ss_usb_cap);
+			goto test_bos_error;
+		}
+	}else
+		goto test_bos_error;
+
+	ret = 0;
+	goto test_bos_done;
+
+test_bos_error:
+	ret = -1;
+test_bos_done:
+	libusb_close(udev);
+	return ret;
+}
+
+/**
+ * test_ss_descriptors() - checks the validity of SS device descriptors
+ * according to the expected descriptors in ss_expected_desc.h
+ * @dev: libusb device to check
+ * @num_expected_strms_in_ep: the number of expected streams for IN EP's
+ *	ep_comp descriptor
+ * @num_expected_strms_out_ep: the number of expected streams for OUT EP's
+ *	ep_comp descriptor
+ *
+ * Returns 0 for sucsess -1 for failure
+ */
+int test_ss_descriptors(libusb_device *dev, int num_expected_strms_in_ep,
+			int num_expected_strms_out_ep)
+{
+	struct libusb_device_handle *udev;
+	int ret;
+
+	if (!dev)
+		return -1;
+
+	ret = libusb_open(dev, &udev);
+	if (ret) {
+		printf("Couldn't open device (%d) \n", ret);
+		return -1;
+	}
+
+	if (check_dev_desc(dev, ss_device_descriptor))
+		goto test_ss_desc_err;
+
+	if (check_ss_intr_desc(dev, num_expected_strms_in_ep,
+			       num_expected_strms_out_ep))
+		goto test_ss_desc_err;
+
+	if (check_bos_desc(dev))
+		goto test_ss_desc_err;
+
+	ret = 0;
+	goto test_ss_desc_done;
+
+test_ss_desc_err:
+	ret = -1;
+test_ss_desc_done:
+	libusb_close(udev);
+	return ret;
+}
+
+/**
+ * test_connect_disconnect() - initiates a connect/disconnect sequence by
+ * the device.
+ * @dev: libusb device
+ * @dev_speed: the original speed of the connected device (before the test)
+ * @num_expected_strms_in_ep: the number of expected streams for IN EP's
+ *	ep_comp descriptor (the descriptors are used the verify the connection)
+ * @num_expected_strms_out_ep: the number of expected streams for OUT EP's
+ *	ep_comp descriptor (the descriptors are used the verify the connection)
+ *
+ * Returns 0 for sucsess -1 for failure
+ *
+ * After the device is connected it's descriptors are verified according to the
+ * speed. The connection speed should be maintained!
+ */
+int test_connect_disconnect(libusb_device *dev,
+			    enum usb_device_speed dev_speed,
+			    int num_expected_strms_in_ep,
+			    int num_expected_strms_out_ep)
+{
+	struct libusb_device_handle *udev;
+	libusb_device *new_dev;
+	int ret = -1;
+	uint16_t wValue;
+
+	struct libusb_device_descriptor dev_desc;
+	if (libusb_get_device_descriptor(dev, &dev_desc))
+	{
+		printf("Couldn't get device descriptor\n");
+		return -1;
+	}
+
+	if (ut_debug)
+		printf("In test_connect_disconnect\n");
+
+	if (!dev)
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		return -1;
+	}
+
+	ret = libusb_control_transfer(udev, LIBUSB_REQUEST_TYPE_VENDOR |
+				       LIBUSB_RECIPIENT_DEVICE,
+				       CONN_DISCONN_TEST, 0, 0, NULL, 0,
+				       BULK_TRANSFERR_TIMEOUT);
+
+	/*
+	 * We ignore the LIBUSB_ERROR_NO_DEVICE because the device disconnects
+	 * before the response is handled by the host
+	 */
+	if ((ret < 0) && (ret != LIBUSB_ERROR_NO_DEVICE)){
+		printf("Couldn't send setup test control packet = %d\n", ret);
+		goto test_connect_disconnect_err;
+	}
+
+	libusb_close(udev);
+
+	/* Wait for test completion and verify dev. connection */
+	(void)sleep(2);
+
+	/*
+	 * After the reenumeration we need to update the libusb device handle.
+	 * The devnum isn't valid anymore so we need to update the productid
+	 * and the vendorid according to device descriptor
+	 */
+	libusb_utils_exit();
+	libusb_utils_init();
+	new_dev = get_libusb_dev();
+	if (!new_dev) {
+		return -1;
+	}
+
+	/* Verify successfull conection by checking descriptors */
+	switch (dev_speed) {
+	case USB_SPEED_SUPER:
+		printf("num_expected_strms_in_ep = %d\n",
+		       num_expected_strms_in_ep);
+		printf("num_expected_strms_out_ep = %d\n",
+		       num_expected_strms_out_ep);
+		ret = test_ss_descriptors(new_dev, num_expected_strms_in_ep,
+			       num_expected_strms_out_ep);
+		break;
+	default:
+		ret = test_hs_descriptors(new_dev);
+	}
+
+	goto test_connect_disconnect_done;
+
+test_connect_disconnect_err:
+	libusb_close(udev);
+test_connect_disconnect_done:
+	return ret;
+}
+
+/**
+ * test_get_status_functionality() - verify the GET_STATUS request handling
+ * @dev: Libusb device hook
+ * @in_udev: External hook to the libusb device
+ * @bmRequestType: The request's bmRequestType
+ * @expected_res: The expected post-action status
+ *
+ * Returns 0 for sucsess, (-1) for failure
+ *
+ * This is a general function that sends a GET_STATUS request to {HS / SS}
+ * {device / EP / interface} with test specific parameters
+ */
+static int test_get_status_functionality(
+				libusb_device               *dev,
+				struct libusb_device_handle *in_udev,
+				uint8_t                      bmRequestType,
+				uint16_t                     wIndex,
+				unsigned char               *expected_res)
+{
+	struct libusb_device_handle *udev = NULL;
+	unsigned char data[2] = {0};
+	int transfer_res = 0, ret_val = 0;
+	bool init_libusb = 0;
+
+	if (!in_udev) {
+		if (!dev) {
+			printf("libusb device  == NULL..\n");
+			return -1;
+		}
+
+		if (libusb_open(dev, &udev)) {
+			printf("Couldn't open device\n");
+			return -1;
+		}
+		init_libusb = 1;
+	}
+	else {
+		udev = in_udev;
+	}
+
+	transfer_res = libusb_control_transfer(udev, /* libusb_device_handle */
+				bmRequestType,		/* bmRequestType */
+				LIBUSB_REQUEST_GET_STATUS, /* bRequest */
+				0,			   /* wValue */
+				wIndex,			   /* wIndex */
+				data,			   /* returned data */
+				2,			   /* wLength */
+				CTL_REQ_TRANSFERR_TIMEOUT);/* timeout */
+
+	if ((transfer_res == LIBUSB_ERROR_NO_DEVICE) ||
+		(transfer_res == LIBUSB_ERROR_TIMEOUT) ||
+		(transfer_res == LIBUSB_ERROR_IO) ||
+		(transfer_res == LIBUSB_ERROR_PIPE))
+	{
+		printf("LIBUSB error (%d)\n", transfer_res);
+		ret_val = -1;
+	}
+
+	if ( (data[0] != expected_res[0]) || (data[1] != expected_res[1]) ){
+		printf("data (0x%x, 0x%x) != expected_res (0x%x, 0x%x)..\n",
+				data[0], data[1], expected_res[0],
+				expected_res[1]);
+		ret_val = -1;
+	}
+
+	if (init_libusb)
+		libusb_close(udev);
+
+	return ret_val;
+}
+
+/**
+ * test_ss_get_status_default_device() - verify the GET_STATUS(dev) request
+ * handling
+ * @dev: Libusb device hook
+ *
+ * Returns 0 for sucsess, (-1) for failure
+ *
+ * This function sends a GET_STATUS request to the ss device in default state
+ * (when LTM, U1 & U2 are not enabled) and checks that the response is  as
+ * expected (section 9.4.5 in the USB3 standard)
+ */
+int test_ss_get_status_default_device(libusb_device *dev)
+{
+	return test_get_status_functionality(dev, NULL,
+			(LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD |
+			 LIBUSB_RECIPIENT_DEVICE),
+			0x00, /* For GetStatus(DEVICE) request wIndex=0 */
+			ss_get_status_default_device_expected);
+}
+
+/**
+ * test_ss_get_status_default_interface() - verify the GET_STATUS(intr) request
+ * handling
+ * @dev: Libusb device hook
+ * @interface_id: interface id to run the test on
+ *
+ * Returns 0 for sucsess, (-1) for failure
+ *
+ * This function sends a GET_STATUS request to the ss interface in default state
+ * (section 9.4.5 in the USB3 standard)
+ */
+int test_ss_get_status_default_interface(libusb_device *dev,
+					 int interface_id)
+{
+	return test_get_status_functionality(dev, NULL,
+			(LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD |
+			 LIBUSB_RECIPIENT_INTERFACE),
+			interface_id, ss_get_status_default_interface_expected);
+}
+
+/**
+ * test_ss_get_status_default_ep() - verify the GET_STATUS(ep) request handlind
+ * @dev: Libusb device hook
+ * @interface_id: interface id to run the test on
+ *
+ * Returns 0 for sucsess, (-1) for failure
+ *
+ * This function sends a  GET_STATUS request to the ss endpoint in default state
+ * (section 9.4.5 in the USB3 standard). It's run for the BULK IN endpoint and
+ * assumes the device has such.
+ */
+int test_ss_get_status_default_ep(libusb_device *dev,
+				  int interface_id)
+{
+	struct libusb_endpoint_descriptor *in_ep;
+	struct libusb_device_handle *udev = NULL;
+	int rc = -1;
+
+	if (!dev) {
+		printf("libusb device  == NULL..\n");
+		return -1;
+	}
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		return -1;
+	}
+
+	in_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK,
+					 interface_id, PIPE_ID_UNDEF);
+
+	if (!in_ep) {
+		printf("Didn't find BULK IN endpoint!\n");
+		goto ss_get_status_default_ep_done;
+	}
+
+	rc = test_get_status_functionality(dev, udev,
+			( LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD |
+			  LIBUSB_RECIPIENT_ENDPOINT),
+			(uint16_t)in_ep->bEndpointAddress,
+			ss_get_status_default_ep_expected);
+
+ss_get_status_default_ep_done:
+	libusb_close(udev);
+	return rc;
+}
+
+/**
+ * test_hs_get_status_default_device() - verify the GET_STATUS(dev) request
+ * handling
+ * @dev: Libusb device hook
+ *
+ * Returns 0 for sucsess, (-1) for failure
+ *
+ * This function sends a  GET_STATUS request to the hs device in default state
+ * and checks that the response is as expected (section 9.4.5 in the USB2
+ * standard)
+ */
+int test_hs_get_status_default_device(libusb_device *dev)
+{
+	return test_get_status_functionality(dev, NULL,
+			( LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD |
+			  LIBUSB_RECIPIENT_DEVICE),
+			0x00, /* For GetStatus(DEVICE) request wIndex=0 */
+			hs_get_status_default_device_expected);
+}
+
+/**
+ * test_hs_get_status_default_interface() - verify the GET_STATUS(intr) request
+ * handling
+ * @dev: Libusb device hook
+ * @interface_id: interface id to run the test on
+ *
+ * Returns 0 for sucsess, (-1) for failure
+ *
+ * This function sends a GET_STATUS request to the hs interface in default state
+ * (section 9.4.5 in the USB2 standard)
+ */
+int test_hs_get_status_default_interface(libusb_device *dev,
+					 int interface_id)
+{
+	return test_get_status_functionality(dev, NULL,
+			(LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD |
+			 LIBUSB_RECIPIENT_INTERFACE),
+			interface_id, hs_get_status_default_interface_expected);
+}
+
+/**
+ * test_hs_get_status_default_ep() - verify the GET_STATUS(ep) request handlind
+ * @dev: Libusb device hook
+ * @interface_id: interface id to run the test on
+ *
+ * Returns 0 for sucsess, (-1) for failure
+ *
+ * This function sends a GET_STATUS request to the hs endpoint in default state
+ * (section 9.4.5 in the USB2 standard)
+ */
+int test_hs_get_status_default_ep(libusb_device *dev,
+				  int interface_id)
+{
+	struct libusb_endpoint_descriptor *in_ep;
+	struct libusb_device_handle *udev = NULL;
+	int rc = -1;
+
+	if (!dev) {
+		printf("libusb device  == NULL..\n");
+		return -1;
+	}
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		return -1;
+	}
+
+	in_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK,
+					 interface_id, PIPE_ID_UNDEF);
+
+	if (!in_ep) {
+		printf("Didn't find BULK IN endpoint!\n");
+		goto hs_get_status_default_ep_done;
+	}
+
+	rc = test_get_status_functionality(dev, udev,
+			( LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD |
+			  LIBUSB_RECIPIENT_ENDPOINT),
+			(uint16_t)in_ep->bEndpointAddress,
+			hs_get_status_default_ep_expected);
+
+hs_get_status_default_ep_done:
+	libusb_close(udev);
+	return rc;
+}
+
+/**
+ * test_set_feature() - verify the SET_FEATURE request handling
+ * @dev: Libusb device hook
+ * @bmRequestType: The request's bmRequestType
+ * @wValue: The request's wValue
+ * @wIndex: The request's wIndex
+ * @pre_status:- The expected status before the set cmd
+ * @post_status: The expected status after the set cmd
+ *
+ * Returns 0 for sucsess, (-1) for failure
+ *
+ * This is a general function that sends a SET_FEATURE request
+ * to {HS / SS} {device / EP / interface} with test specific
+ * parameters. The tests verifies the new settings.
+ */
+static int test_set_feature(libusb_device *dev,
+					  uint8_t  bmRequestType,
+					  uint16_t wValue,
+					  uint16_t wIndex,
+					  unsigned char *pre_status,
+					  unsigned char *post_status)
+{
+	struct libusb_device_handle *udev = NULL;
+	int transfer_res = 0, ret_val = -1;
+
+	if (!dev) {
+		printf("libusb device == NULL..\n");
+		return -1;
+	}
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		return -1;
+	}
+
+	/* Make sure that pre status is as expected */
+	ret_val = test_get_status_functionality(dev, udev,
+				LIBUSB_ENDPOINT_IN | bmRequestType,
+				wIndex, pre_status);
+
+	if (ret_val)
+	{
+		printf("Set feature test: Initial status != expected..\n");
+		goto exit_set_feature;
+	}
+
+	transfer_res = libusb_control_transfer(udev, 		/* device_hdl */
+				bmRequestType,			/* req type */
+				LIBUSB_REQUEST_SET_FEATURE,	/* bRequest */
+				wValue,				/* wValue */
+				wIndex,				/* wIndex */
+				NULL,				/* ret data */
+				0,				/* wLength */
+				CTL_REQ_TRANSFERR_TIMEOUT);	/* timeout */
+
+	if ((transfer_res == LIBUSB_ERROR_NO_DEVICE) ||
+	    (transfer_res == LIBUSB_ERROR_TIMEOUT) ||
+	    (transfer_res == LIBUSB_ERROR_IO) ||
+	    (transfer_res == LIBUSB_ERROR_PIPE) ) {
+		printf("LIBUSB error : (%d)\n", transfer_res);
+		ret_val = -1;
+		goto exit_set_feature;
+	}
+
+	/* Make sure that post status is as expected */
+	ret_val = test_get_status_functionality(dev, udev,
+				LIBUSB_ENDPOINT_IN | bmRequestType,
+				wIndex, post_status);
+
+	if (ret_val) {
+		printf("Set feature test:Post SET status != expected..\n");
+		goto exit_set_feature;
+	}
+
+exit_set_feature:
+	libusb_close(udev);
+	return ret_val;
+}
+
+/**
+ * test_clear_feature() - verify the CLEAR_FEATURE
+ * request handling
+ * @dev: Libusb device hook
+ * @bmRequestType: The request's bmRequestType
+ * @wValue: The request's wValue
+ * @wIndex: The request's wIndex
+ * @pre_status:- The expected status before the set cmd
+ * @post_status: The expected status after the set cmd
+ *
+ * Returns 0 for sucsess, (-1) for failure
+ *
+ * This is a general function that sends a CLEAR_FEATURE request
+ * to {HS / SS} {device / EP / interface} with test specific
+ * parameters. The test verifies the new settings.
+ */
+static int test_clear_feature(libusb_device *dev,
+					  uint8_t  bmRequestType,
+					  uint16_t wValue,
+					  uint16_t wIndex,
+					  unsigned char *pre_status,
+					  unsigned char *post_status)
+{
+	struct libusb_device_handle *udev = NULL;
+	int transfer_res = 0, ret_val = -1;
+
+	if (!dev) {
+		printf("libusb device == NULL..\n");
+		return -1;
+	}
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		return -1;
+	}
+
+	/* Make sure that pre status is as expected */
+	ret_val = test_get_status_functionality(dev, udev,
+				LIBUSB_ENDPOINT_IN | bmRequestType,
+				wIndex, pre_status);
+
+	if (ret_val)
+	{
+		printf("Clear feature test: Initial status != expected..\n");
+		goto exit_clear_feature;
+	}
+
+	/* Send the CLEAR_FEATURE: */
+	transfer_res = libusb_control_transfer(udev,		/* device_hdl */
+				bmRequestType,			/* req type */
+				LIBUSB_REQUEST_CLEAR_FEATURE,	/* bRequest */
+				wValue,				/* wValue */
+				wIndex,				/* wIndex */
+				NULL,				/* ret data */
+				0,				/* wLength */
+				CTL_REQ_TRANSFERR_TIMEOUT);	/* timeout */
+
+	if ( (transfer_res == LIBUSB_ERROR_NO_DEVICE) ||
+	     (transfer_res == LIBUSB_ERROR_TIMEOUT) ||
+	     (transfer_res == LIBUSB_ERROR_IO) ||
+	     (transfer_res == LIBUSB_ERROR_PIPE)) {
+		printf("LIBUSB error in CLEAR_FEATURE (%d)\n", transfer_res);
+		ret_val = -1;
+		goto exit_clear_feature;
+	}
+
+	/* Make sure that we are back to the initial status */
+	ret_val = test_get_status_functionality(dev, udev,
+				LIBUSB_ENDPOINT_IN | bmRequestType,
+				wIndex, post_status);
+
+	if (ret_val)
+		printf("Clear feature test:Post CLEAR status != expected..\n");
+
+exit_clear_feature:
+	libusb_close(udev);
+	return ret_val;
+}
+
+/**
+ * test_set_feature_functionality() - verify the SET_FEATURE request handling
+ * @dev: Libusb device hook
+ * @bmRequestType: The request's bmRequestType
+ * @wValue: The request's wValue
+ * @wIndex: The request's wIndex
+ * @pre_status:- The expected status before the set cmd
+ * @post_status: The expected status after the set cmd
+ *
+ * Returns 0 for sucsess, (-1) for failure
+ *
+ * This is a general function that sends a SET_FEATURE request to {HS / SS}
+ * {device / EP / interface} with test specific parameters, after verifying the
+ * new settings, the tests clears the change.
+ */
+static int test_set_feature_functionality(libusb_device *dev,
+					  uint8_t  bmRequestType,
+					  uint16_t wValue,
+					  uint16_t wIndex,
+					  unsigned char *pre_status,
+					  unsigned char *post_status)
+{
+	int ret_val = -1;
+
+	ret_val = test_set_feature(dev,
+						  bmRequestType,
+						  wValue,
+						  wIndex,
+						  pre_status,
+						  post_status);
+
+	if (ret_val < 0) {
+		printf("test_set_feature failed\n");
+		return ret_val;
+	}
+
+	ret_val = test_clear_feature(dev,
+						  bmRequestType,
+						  wValue,
+						  wIndex,
+						  post_status,
+						  pre_status);
+
+	if (ret_val < 0) {
+		printf("test_set_feature failed\n");
+		return ret_val;
+	}
+
+	return ret_val;
+}
+
+/**
+ * test_ss_set_feature_u1_device() - verify the SET_FEATURE(U1) handling
+ * @dev: Libusb device hook
+ *
+ * Returns 0 for sucsess, (-1) for failure
+ *
+ * This function sends a SET_FEATURE request to the ss device in default state,
+ * to set the U1 power level capability
+ */
+int test_ss_set_feature_u1_device(libusb_device *dev)
+{
+	return test_set_feature_functionality(dev,
+			(LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_STANDARD |
+			 LIBUSB_RECIPIENT_DEVICE), U1_ENABLE_FEATURE_SEL,
+			/* For SetFeature/GetStatus for DEVICE requests
+			 *  wIndex = 0x00
+			 */
+			0x00,
+			ss_get_status_default_device_expected,
+			ss_get_status_U1_enabled_device_expected);
+}
+
+/**
+ * test_ss_set_feature_u2_device() - verify the SET_FEATURE(U2) handling
+ * @dev: Libusb device hook
+ *
+ * Returns 0 for sucsess, (-1) for failure
+ *
+ * This function sends a SET_FEATURE request to the ss device in default state,
+ * to set the U2 power level capability
+ */
+int test_ss_set_feature_u2_device(libusb_device *dev)
+{
+	return test_set_feature_functionality(dev,
+			( LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_STANDARD |
+			  LIBUSB_RECIPIENT_DEVICE), U2_ENABLE_FEATURE_SEL,
+			/* For SetFeature/GetStatus for DEVICE requests
+			 *  wIndex = 0x00
+			 */
+			0x00,
+			ss_get_status_default_device_expected,
+			ss_get_status_U2_enabled_device_expected);
+}
+
+/**
+ * test_ss_set_feature_ltm_device() - verify the SET_FEATURE(LTM) handling
+ * @dev: Libusb device hook
+ *
+ * Returns 0 for sucsess, (-1) for failure
+ *
+ * This function sends a SET_FEATURE request to the ss device in default state,
+ * to set the LTM capability
+ */
+int test_ss_set_feature_ltm_device(libusb_device *dev)
+{
+	return test_set_feature_functionality(dev,
+			( LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_STANDARD |
+			  LIBUSB_RECIPIENT_DEVICE), LTM_ENABLE_FEATURE_SEL,
+			/* For SetFeature/GetStatus for DEVICE requests
+			 *  wIndex = 0x00
+			 */
+			0x00,
+			ss_get_status_default_device_expected,
+			ss_get_status_LTM_enabled_device_expected);
+}
+
+/**
+ * test_ss_set_feature_halt_ep() - verify the SET_FEATURE(HALT_EP) handling
+ * @dev: Libusb device hook
+ * @interface_id: interface id to run the test on
+ *
+ * Returns 0 for sucsess, (-1) for failure
+ *
+ * This function sends a SET_FEATURE request to the ss EP in default state, to
+ * set the halt feature It's run for the BULK IN endpoint and assumes  the
+ * device has such.
+ */
+int test_ss_set_feature_halt_ep(libusb_device *dev,
+				int interface_id)
+{
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *in_ep;
+	int ret_val = -1;
+
+	if (!dev) {
+		printf("libusb device == NULL..\n");
+		return -1;
+	}
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		return -1;
+	}
+	in_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+			     LIBUSB_TRANSFER_TYPE_BULK,
+			     interface_id, PIPE_ID_UNDEF);
+	libusb_close(udev);
+
+	if (!in_ep) {
+		printf("Didn't find BULK IN endpoint!\n");
+		goto ss_set_feature_halt_ep_done;
+	}
+
+	ret_val =  test_set_feature_functionality(dev,
+			(LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_STANDARD |
+			 LIBUSB_RECIPIENT_ENDPOINT),
+			HALT_ENABLE_FEATURE_SEL,
+			(uint16_t)in_ep->bEndpointAddress,
+			ss_get_status_default_ep_expected,
+			ss_get_status_halt_enabled_ep_expected);
+
+ss_set_feature_halt_ep_done:
+	return ret_val;
+}
+
+/**
+ * test_hs_set_feature_halt_ep() - verify the SET_FEATURE(HALT_EP) handling
+ * @dev: Libusb device hook
+ * @interface_id: interface id to run the test on
+ *
+ * Returns 0 for sucsess, (-1) for failure
+ *
+ * This function sends a SET_FEATURE request to the hs EP in default state,
+ * to set the halt feature. It's run for the BULK IN endpoint and assumes the
+ * device has such.
+ */
+int test_hs_set_feature_halt_ep(libusb_device *dev,
+				int interface_id)
+{
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *in_ep;
+	int ret_val = -1;
+
+	if (!dev) {
+		printf("libusb device == NULL..\n");
+		return -1;
+	}
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		return -1;
+	}
+	in_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+			     LIBUSB_TRANSFER_TYPE_BULK,
+			     interface_id, PIPE_ID_UNDEF);
+	libusb_close(udev);
+
+	if (!in_ep) {
+		printf("Didn't find BULK IN endpoint!\n");
+		goto hs_set_feature_halt_ep_done;
+	}
+
+	ret_val =  test_set_feature_functionality(dev,
+			(LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_STANDARD |
+			 LIBUSB_RECIPIENT_ENDPOINT),
+			HALT_ENABLE_FEATURE_SEL,
+			(uint16_t)in_ep->bEndpointAddress,
+			hs_get_status_default_ep_expected,
+			hs_get_status_halt_enabled_ep_expected);
+
+hs_set_feature_halt_ep_done:
+	return ret_val;
+}
+
+/**
+ * test_ss_set_feature_suspend_low_power_interface() - verify the
+ * SET_FEATURE(FUNCTION_SUSPEND) functionality
+ * @dev: Libusb device hook
+ * @interface_id: interface id to run the test on
+ *
+ * Returns 0 for sucsess, (-1) for failure
+ *
+ * This function sends a SET_FEATURE request to the ss interface in default
+ * state, to set the suspend functionality for low power
+ */
+int test_ss_set_feature_suspend_low_power_interface(libusb_device *dev,
+						    int interface_id)
+{
+	int ret_val = 0;
+
+	/* Suspend the interface */
+	ret_val = test_set_feature(dev,
+			(LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_STANDARD |
+			 LIBUSB_RECIPIENT_INTERFACE),
+			SUSPEND_ENABLE_FEATURE_SEL,
+			interface_id | (FUNC_SUSPEND_OPT_LOW_POWER << 8),
+			hs_get_status_default_interface_expected,
+			ss_get_status_suspend_low_power_interface_expected);
+
+	if (ret_val < 0)
+		goto ss_set_feature_suspend_interface_done;
+
+	/* Check that the device suspended the interface */
+	ret_val = usb_tests_read_gadget_sysfs_file((char*)GADGET_ZERO_FUNC_SUSPENDED_SYSFS_PATH);
+	if (ret_val != 1) {
+		printf("Function is not in suspend state, %d", ret_val);
+		goto ss_set_feature_suspend_interface_done;
+	}
+
+	/* Resume the interface */
+	ret_val = test_set_feature(dev,
+			(LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_STANDARD |
+			 LIBUSB_RECIPIENT_INTERFACE),
+			SUSPEND_ENABLE_FEATURE_SEL,
+			interface_id,
+			ss_get_status_suspend_low_power_interface_expected,
+			hs_get_status_default_interface_expected);
+
+	if (ret_val < 0)
+		goto ss_set_feature_suspend_interface_done;
+
+	/* Check that the device resumed the interface */
+	ret_val = usb_tests_read_gadget_sysfs_file((char*)GADGET_ZERO_FUNC_SUSPENDED_SYSFS_PATH);
+	if (ret_val != 0) {
+		printf("Function is in suspend state, %d", ret_val);
+		goto ss_set_feature_suspend_interface_done;
+	}
+
+ss_set_feature_suspend_interface_done:
+	return ret_val;
+}
+
+/**
+ * test_ss_set_feature_suspend_remote_wakeup_interface() - verify the
+ * SET_FEATURE(FUNCTION_SUSPEND) functionality
+ * @dev: Libusb device hook
+ * @interface_id: interface id to run the test on
+ *
+ * Returns 0 for sucsess, (-1) for failure
+ *
+ * This function sends a SET_FEATURE request to the ss interface in default
+ * state, to set the suspend functionality for remote wakeup
+ */
+int test_ss_set_feature_suspend_remote_wakeup_interface(libusb_device *dev,
+							int interface_id)
+{
+	int ret_val = 0;
+
+	/* Suspended the interface */
+	ret_val = test_set_feature(dev,
+			(LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_STANDARD |
+			 LIBUSB_RECIPIENT_INTERFACE),
+			SUSPEND_ENABLE_FEATURE_SEL,
+			interface_id | (FUNC_SUSPEND_OPT_LOW_POWER << 8),
+			hs_get_status_default_interface_expected,
+			ss_get_status_suspend_low_power_interface_expected);
+
+	if (ret_val < 0)
+		goto ss_set_feature_suspend_remote_wakeup_interface_done;
+
+	/* Check that the device suspended the interface */
+	ret_val = usb_tests_read_gadget_sysfs_file((char*)GADGET_ZERO_FUNC_SUSPENDED_SYSFS_PATH);
+	if (ret_val != 1) {
+		printf("Function is not in suspend state, %d", ret_val);
+		ret_val = -1;
+		goto ss_set_feature_suspend_remote_wakeup_interface_done;
+	}
+
+	/* Set the Function Remote Wake capability */
+	ret_val = usb_tests_write_gadget_sysfs_file_int(
+		(char*)ZERO_GADGET_ZERO_FUNC_WAKEUP_CAPABLE_SYSFS_PATH, 1);
+	if (ret_val != 0) {
+		printf("write file failed, %d", ret_val);
+		goto ss_set_feature_suspend_remote_wakeup_interface_done;
+	}
+
+	/* Set the Function Remote Wake Enabled feature */
+	ret_val = test_set_feature(dev,
+			(LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_STANDARD |
+			 LIBUSB_RECIPIENT_INTERFACE),
+			SUSPEND_ENABLE_FEATURE_SEL,
+			interface_id | (FUNC_SUSPEND_OPT_WAKEUP_EN << 8),
+			ss_get_status_suspend_remote_wu_cap_interface_expected,
+			ss_get_status_suspend_remote_wu_en_cap_interface_expected);
+
+	if (ret_val != 0)
+		goto ss_set_feature_suspend_remote_wakeup_interface_done;
+
+	/* Check that the device enabled the Function Remote Wake */
+	ret_val = usb_tests_read_gadget_sysfs_file(
+		(char*)ZERO_GADGET_ZERO_FUNC_WAKEUP_ENABLED_SYSFS_PATH);
+	if (ret_val != 1) {
+		printf("Function wake is not enabled, %d", ret_val);
+		goto ss_set_feature_suspend_remote_wakeup_interface_done;
+	}
+
+	/* Trigger Function Remote Wake by the device */
+	ret_val = usb_tests_write_gadget_sysfs_file_int(
+		(char*)ZERO_GADGET_ZERO_FUNC_WAKEUP_TRIGGER_SYSFS_PATH, 1);
+	if (ret_val != 0) {
+		printf("write file failed, %d", ret_val);
+		goto ss_set_feature_suspend_remote_wakeup_interface_done;
+	}
+
+	/* Resume the interface */
+	ret_val = test_set_feature(dev,
+			(LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_STANDARD |
+			 LIBUSB_RECIPIENT_INTERFACE),
+			SUSPEND_ENABLE_FEATURE_SEL,
+			interface_id,
+			ss_get_status_suspend_remote_wu_en_cap_interface_expected,
+			ss_get_status_suspend_remote_wu_cap_interface_expected);
+
+	if (ret_val < 0)
+		goto ss_set_feature_suspend_remote_wakeup_interface_done;
+
+	/* Check that the device resumed the interface */
+	ret_val = usb_tests_read_gadget_sysfs_file((char*)GADGET_ZERO_FUNC_SUSPENDED_SYSFS_PATH);
+	if (ret_val != 0) {
+		printf("Function is in suspend state, %d", ret_val);
+		goto ss_set_feature_suspend_remote_wakeup_interface_done;
+	}
+
+	/* Clear the Function Remote Wake capability */
+	ret_val = usb_tests_write_gadget_sysfs_file_int(
+		(char*)ZERO_GADGET_ZERO_FUNC_WAKEUP_CAPABLE_SYSFS_PATH, 0);
+	if (ret_val != 0) {
+		printf("write file failed, %d", ret_val);
+		goto ss_set_feature_suspend_remote_wakeup_interface_done;
+	}
+
+	if (ret_val < 0)
+		goto ss_set_feature_suspend_remote_wakeup_interface_done;
+
+ss_set_feature_suspend_remote_wakeup_interface_done:
+	return ret_val;
+}
+
+/**
+ * test_hs_set_feature_suspend_remote_wakeup_interface() - verify the
+ * SET_FEATURE(FUNCTION_SUSPEND) functionality
+ * @dev: Libusb device hook
+ * @interface_id: interface id to run the test on
+ *
+ * Returns 0 for sucsess, (-1) for failure
+ *
+ * This function sends a SET_FEATURE request to the ss interface in default
+ * state, to set the suspend functionality for remote wakeup
+ */
+int test_hs_set_feature_suspend_interface(libusb_device *dev,
+					  int interface_id)
+{
+	return test_set_feature_functionality(dev,
+			(LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_STANDARD |
+			 LIBUSB_RECIPIENT_INTERFACE),
+			SUSPEND_ENABLE_FEATURE_SEL,
+			interface_id,
+			hs_get_status_default_interface_expected,
+			hs_get_status_default_interface_expected);
+}
+
diff --git a/tools/usb/unittests/usb/composite_tests.h b/tools/usb/unittests/usb/composite_tests.h
new file mode 100644
index 0000000..db68db0
--- /dev/null
+++ b/tools/usb/unittests/usb/composite_tests.h
@@ -0,0 +1,65 @@
+/*
+ * composite_tests.h - USB composite device general tests
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef COMPOSITE_TESTS_H
+#define COMPOSITE_TESTS_H
+
+#include <linux/kernel.h>
+#include <linux/usb/ch9.h>
+#include "libusb_utils.h"
+
+int soursesink_test_setup(struct libusb_device_handle *udev, libusb_device *dev,
+			  uint8_t request, uint16_t wValue);
+int test_hs_descriptors(libusb_device *dev);
+int test_ss_descriptors(libusb_device *dev, int num_expected_strms_in_ep,
+			    int num_expected_strms_out_ep);
+int test_connect_disconnect(libusb_device *dev, enum usb_device_speed dev_speed,
+			    int num_expected_strms_in_ep,
+			    int num_expected_strms_out_ep);
+int test_ss_get_status_default_device(libusb_device *dev);
+int test_ss_get_status_default_interface(libusb_device *dev, int interface_id);
+int test_ss_get_status_default_ep(libusb_device *dev, int interface_id);
+int test_hs_get_status_default_device(libusb_device *dev);
+int test_hs_get_status_default_interface(libusb_device *dev, int interface_id);
+int test_hs_get_status_default_ep(libusb_device *dev, int interface_id);
+int test_ss_set_feature_u1_device(libusb_device *dev);
+int test_ss_set_feature_u2_device(libusb_device *dev);
+int test_ss_set_feature_ltm_device(libusb_device *dev);
+int test_ss_set_feature_halt_ep(libusb_device *dev, int interface_id);
+int test_hs_set_feature_halt_ep(libusb_device *dev, int interface_id);
+int test_ss_set_feature_suspend_low_power_interface(libusb_device *dev,
+						    int interface_id);
+int test_ss_set_feature_suspend_remote_wakeup_interface(libusb_device *dev,
+							int interface_id);
+int test_hs_set_feature_suspend_interface(libusb_device *dev, int interface_id);
+
+#endif /*COMPOSITE_TESTS_H*/
diff --git a/tools/usb/unittests/usb/g_serial_tests.cc b/tools/usb/unittests/usb/g_serial_tests.cc
new file mode 100644
index 0000000..3da7870
--- /dev/null
+++ b/tools/usb/unittests/usb/g_serial_tests.cc
@@ -0,0 +1,198 @@
+/*
+ * g_serial_tests.c - generic USB serial function driver tests
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <linux/usb/ch9.h>
+
+#include "ut_config.h"
+#include "libusb_utils.h"
+#include "composite_tests.h"
+
+/**
+ * test_single_bulk_in() - Initiate a single bulk in transfer
+ * @dev: libusb device to test
+ * @data_size: size of the data buffer to receive
+ * @interface_id: interface id to run the test on
+ *
+ * Returns 0 on sucsess -1 for failure
+ *
+ * TODO: add data validity check
+ * 	 add debug information!
+ */
+int test_single_bulk_in(libusb_device *dev, int data_size,
+			int interface_id)
+{
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *in_ep;
+	unsigned char *data_in;
+	int transferred = 0;
+	int ret;
+
+	if (!dev)
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto test_single_bulk_in_err;
+	}
+
+	data_in = (unsigned char *)malloc(data_size+10);
+	if (!data_in) {
+		printf("Error allocating memory!\n");
+		goto test_single_bulk_in_err;
+	}
+
+	/*
+	 * First send the control request to setup the buffer size on
+	 * the device
+	 */
+	if (soursesink_test_setup(udev, dev, SET_BULK_BUF_SIZE, data_size) < 0){
+		printf("Coldn't send setup test control packet\n");
+		goto test_single_bulk_in_err;
+	}
+
+	in_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+					 LIBUSB_TRANSFER_TYPE_BULK,
+					 interface_id, PIPE_ID_UNDEF);
+
+	if (!in_ep) {
+		printf("Didn't find BULK IN endpoint!\n");
+		goto test_single_bulk_in_err;
+	}
+
+	ret = libusb_bulk_transfer(udev, in_ep->bEndpointAddress, data_in,
+				   data_size, &transferred,
+				   BULK_TRANSFERR_TIMEOUT);
+	if (ret) {
+		printf("Transferr error %d (endpoint = %u)\n",ret,
+		       in_ep->bEndpointAddress);
+		goto test_single_bulk_in_err;
+	}
+
+	if (transferred != data_size) {
+		printf("The number of bytes actually "
+		       "transferred (%d) != data size (%d)",
+		       transferred, data_size);
+		goto test_single_bulk_in_err;
+	}
+
+	ret = 0;
+	goto test_single_bulk_in_done;
+test_single_bulk_in_err:
+	ret = -1;
+test_single_bulk_in_done:
+	libusb_close(udev);
+	free(data_in);
+	return ret;
+}
+
+/**
+ * test_single_bulk_out() - Initiate a single bulk out transfer
+ * @dev: libusb device to test
+ * @data_size: size of the data buffer to send
+ * @interface_id: interface id to run the test on
+ *
+ * Returns 0 on sucsess -1 for failure
+ *
+ * TODO: add data validity check
+ *	 add debug information!
+ */
+int test_single_bulk_out(libusb_device *dev, int data_size,
+			 int interface_id)
+{
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *out_ep;
+	unsigned char *data_out;
+	int transferred = 0;
+	int ret, i;
+
+	if (!dev)
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		goto test_single_bulk_out_err;
+	}
+
+	data_out = (unsigned char *)malloc(data_size+10);
+	if (!data_out) {
+		printf("Error allocating memory!\n");
+		goto test_single_bulk_out_err;
+	}
+
+	/*Fill in the data buffer*/
+	for (i = 0; i < data_size; i++)
+		snprintf((char*)(&data_out[i]), 1, "%d", i);
+
+	/*First send the control request to start the test in f_sourcesink*/
+	if (soursesink_test_setup(udev, dev, 0x5e, data_size) < 0){
+		printf("Codn't send setup test controll packet\n");
+		goto test_single_bulk_out_err;
+	}
+
+	out_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+			     LIBUSB_TRANSFER_TYPE_BULK,
+			     interface_id, PIPE_ID_UNDEF);
+
+	if (!out_ep) {
+		printf("Didn't find BULK OUT endpoint!\n");
+		goto test_single_bulk_out_err;
+	}
+
+	ret = libusb_bulk_transfer(udev, out_ep->bEndpointAddress, data_out,
+				   data_size, &transferred,
+				   BULK_TRANSFERR_TIMEOUT);
+	if (ret) {
+		printf("Transferr error %d (endpoint = %u)\n",ret,
+		       out_ep->bEndpointAddress);
+		goto test_single_bulk_out_err;
+	}
+
+	if (transferred != data_size) {
+		printf("The number of bytes actually transferred (%d) != "
+		       "data size (%d)", transferred, data_size);
+		goto test_single_bulk_out_err;
+	}
+
+	ret = 0;
+	goto test_single_bulk_out_done;
+test_single_bulk_out_err:
+	ret = -1;
+test_single_bulk_out_done:
+	libusb_close(udev);
+	free(data_out);
+	return ret;
+}
+
diff --git a/tools/usb/unittests/usb/g_serial_tests.h b/tools/usb/unittests/usb/g_serial_tests.h
new file mode 100644
index 0000000..48a2723
--- /dev/null
+++ b/tools/usb/unittests/usb/g_serial_tests.h
@@ -0,0 +1,68 @@
+/*
+ * g_serial_tests.h - generic USB serial function driver tests
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef G_SERIAL_TESTS_H
+#define G_SERIAL_TESTS_H
+
+#include <linux/kernel.h>
+#include "libusb_utils.h"
+
+/**
+ * test_single_bulk_in() - Initiate a single bulk in transfer
+ * @dev: libusb device to test
+ * @data_size: size of the data buffer to receive
+ * @interface_id: interface id to run the test on
+ *
+ * Returns 0 on sucsess -1 for failure
+ *
+ * TODO: add data validity check
+ *	 add debug information!
+ */
+int test_single_bulk_in(libusb_device *dev, int data_size,
+			int interface_id);
+
+
+/**
+ * test_single_bulk_out() - Initiate a single bulk out transfer
+ * @dev: libusb device to test
+ * @data_size: size of the data buffer to send
+ * @interface_id: interface id to run the test on
+ *
+ * Returns 0 on sucsess -1 for failure
+ *
+ * TODO: add data validity check
+ *	 add debug information!
+ */
+int test_single_bulk_out(libusb_device *dev, int data_size,
+			 int interface_id);
+
+#endif /*G_SERIAL_TESTS_H*/
diff --git a/tools/usb/unittests/usb/hs_expected_desc.h b/tools/usb/unittests/usb/hs_expected_desc.h
new file mode 100644
index 0000000..3223038
--- /dev/null
+++ b/tools/usb/unittests/usb/hs_expected_desc.h
@@ -0,0 +1,164 @@
+/*
+ * hs_expected_desc.h - Expected descriptors when opperation in HS mode
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include "libusb_utils.h"
+
+/* This is the expected value for the HS device descriptor */
+struct libusb_device_descriptor hs_device_descriptor = {
+	18,			/* bLength */
+	LIBUSB_DT_DEVICE,	/* bDescriptorType */
+	0x0210,			/* bcdUSB */
+	2,			/* bDeviceClass = LIBUSB_CLASS_COMM */
+	0,			/* bDeviceSubClass */
+	0,			/* bDeviceProtocol */
+	64,			/* bMaxPacketSize0 */
+	0x0525,			/* idVendor; May be different */
+	0xa4a7,			/* idProduct; May be different */
+	0,			/* bcdDevice; TODO: update */
+	0,			/* iManufacturer; May be different */
+	1,			/* iProduct; May be different */
+	2,			/* iSerialNumber; May be different */
+	1			/* bNumConfigurations */
+};
+
+/* This is the expected value for the HS device BULK OUT endpoint descriptor */
+struct libusb_endpoint_descriptor hs_bulk_out_ep_desc = {
+	7,			/* bLength */
+	LIBUSB_DT_ENDPOINT,	/* bDescriptorType */
+	LIBUSB_ENDPOINT_OUT,	/* bEndpointAddress */
+	2,			/*
+				 * bmAttributes:Transfer Type	Bulk
+				 *		Synch Type	None
+				 *		Usage Type	Data
+				 */
+	512,			/* wMaxPacketSize */
+	0,			/* bInterval */
+	0,			/* bRefresh; Not used since not audio device */
+	0,			/* bSynchAddress; Not used */
+	NULL,			/* ep_comp */
+	NULL,			/* extra */
+	0			/* extra_length */
+};
+
+/* This is the expected value for the HS device BULK IN endpoint descriptor */
+struct libusb_endpoint_descriptor hs_bulk_in_ep_desc = {
+	7,			/* bLength */
+	LIBUSB_DT_ENDPOINT,	/* bDescriptorType */
+	LIBUSB_ENDPOINT_IN,	/* bEndpointAddress */
+	2,			/*
+				 * bmAttributes:Transfer Type	Bulk
+				 *		Synch Type	None
+				 *		Usage Type	Data
+				 */
+	512,			/* wMaxPacketSize */
+	0,			/* bInterval */
+	0,			/* bRefresh; Not used since not audio device */
+	0,			/* bSynchAddress; Not used */
+	NULL,			/* ep_comp */
+	NULL,			/* extra */
+	0			/* extra_length */
+};
+
+/* This is the expected value for the HS device INTERRUPT endpoint descriptor */
+struct libusb_endpoint_descriptor hs_intr_ep_desc = {
+	7,			/* bLength */
+	LIBUSB_DT_ENDPOINT,	/* bDescriptorType */
+	LIBUSB_ENDPOINT_IN,	/* bEndpointAddress */
+	3,			/*
+				 * bmAttributes:Transfer Type	Interrupt
+				 *		Synch Type	None
+				 *		Usage Type	Data
+				 */
+	0xa,			/* wMaxPacketSize */
+	9,			/* bInterval */
+	0,			/* bRefresh; Not used since not audio device */
+	0,			/* bSynchAddress; Not used */
+	NULL,			/* ep_comp */
+	NULL,			/* extra */
+	0			/* extra_length */
+};
+
+/* This is the expected value for the HS device zero interface descriptor */
+struct libusb_interface_descriptor hs_zero_intr_descriptor = {
+	9,			/* bLength */
+	LIBUSB_DT_INTERFACE,	/* bDescriptorType */
+	0,			/* bInterfaceNumber */
+	0,			/* bAlternateSetting */
+	1,			/* bNumEndpoints */
+	LIBUSB_CLASS_COMM,	/* bInterfaceClass; May be different*/
+	0,			/* bInterfaceSubClass; Should be different */
+	0,			/* bInterfaceProtocol; Should be different */
+	0,			/* iInterface; Should be different */
+	NULL,			/* endpoint */
+	NULL,			/* extra */
+	NULL			/* extra_length */
+};
+
+/* This is the expected value for the HS device interface descriptor */
+struct libusb_interface_descriptor hs_intr_descriptor = {
+	9,			/* bLength */
+	LIBUSB_DT_INTERFACE,	/* bDescriptorType */
+	1,			/* bInterfaceNumber */
+	0,			/* bAlternateSetting */
+	2,			/* bNumEndpoints */
+	LIBUSB_CLASS_DATA,	/* bInterfaceClass; May be different */
+	0,			/* bInterfaceSubClass; Should be different */
+	0,			/* bInterfaceProtocol; Should be different */
+	0,			/* iInterface; Should be different */
+	NULL,			/* endpoint */
+	NULL,			/* extra */
+	NULL			/* extra_length */
+};
+
+
+/*
+ * Expected returned data values for the HS GET_STATUS tests
+ * (dummy_hcd configuration..)
+ */
+
+/*
+ * Expected result is 0x0001 - that means that only self-powered is enabled
+ * while Remote-wakeup is disabled
+ */
+unsigned char hs_get_status_default_device_expected[2] = { 0x01, 0x00};
+
+/* Expected result is 0x0000 (all is reserved) */
+unsigned char hs_get_status_default_interface_expected[2] = { 0x00, 0x00};
+
+/* Expected result is 0x0000 - that means that this ep is not halted */
+unsigned char hs_get_status_default_ep_expected[2] = { 0x00, 0x00};
+
+/* Expected result is 0x0001 - that means that this ep is halt enabled */
+unsigned char hs_get_status_halt_enabled_ep_expected[2] = { 0x01, 0x00};
diff --git a/tools/usb/unittests/usb/libusb_utils.cc b/tools/usb/unittests/usb/libusb_utils.cc
new file mode 100644
index 0000000..f8e60c7
--- /dev/null
+++ b/tools/usb/unittests/usb/libusb_utils.cc
@@ -0,0 +1,358 @@
+/*
+ * libusb_utils.c - libusb utilities
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include "libusb_utils.h"
+
+#include <linux/usb/ch9.h>
+
+
+static libusb_device **devs;
+static int devcnt;
+static int was_initialized = false;
+
+/**
+ * libusb_utils_parse_descriptor() - gets a descriptor buffer and parses it
+ * to the descriptor message.
+ * @source: the descriptor buffer to be parsed
+ * @descriptor: the bit mapping of the descriptor, for example use "bbwd"
+ *	for parsing a descriptor that contains byte, byte, 16-bit word,
+ *	32-bit word.
+ * @dest: a pointer to the descriptor message
+ * @host_endian: set host_endian if the w values are already in host endian
+ *	format, as opposed to bus endian.
+ *
+ */
+int libusb_utils_parse_descriptor(unsigned char *source,
+				  char *descriptor, void *dest,
+				  int host_endian)
+{
+	unsigned char *sp = source, *dp = (unsigned char*)dest;
+	uint16_t w;
+	uint32_t d;
+	char *cp;
+
+	for (cp = descriptor; *cp; cp++) {
+		switch (*cp) {
+			case 'b':	/* 8-bit byte */
+				*dp++ = *sp++;
+				break;
+			case 'w':
+			/* 16-bit word, convert from little endian to CPU */
+				/* Align to word boundary */
+				dp += ((unsigned long)dp & 1UL);
+
+				if (host_endian) {
+					memcpy(dp, sp, 2);
+				} else {
+					w = (sp[1] << 8) | sp[0];
+					*((uint16_t *)dp) = w;
+				}
+				sp += 2;
+				dp += 2;
+				break;
+			/* 32-bit word, convert from little endian to CPU */
+			case 'd':
+			/* Align to dword boundary */
+				dp = (unsigned char*)(((unsigned long)dp + 3)
+						      & ~3UL);
+				if (host_endian) {
+					memcpy(dp, sp, 4);
+				} else {
+					d = (sp[3] << 24) | (sp[2] << 16) |
+						(sp[1] << 8) | sp[0];
+					*((uint32_t *)dp) = d;
+				}
+				sp += 4;
+				dp += 4;
+				break;
+		}
+	}
+	return sp - source;
+}
+
+/**
+ * libusb_utils_get_bos_desc() - returns the BOS descriptor
+ * @dev: libusb device
+ * @udev: libusb device handle for the opened device
+ * @bos: the bos descriptor
+ *
+ * Returns 0 on success -1 on failure
+ *
+ * This function is relevent only for SS device.
+ */
+int libusb_utils_get_bos_desc(struct libusb_device *dev,
+		   struct libusb_device_handle *udev,
+		   struct libusb_bos_descriptor *bos)
+{
+	unsigned char bos_buf[LIBUSB_DT_BOS_MAX_SIZE];
+	int ret;
+	int ctrl_timeout = (5*1000);	/* milliseconds */
+
+	if (!dev | !udev)
+	    return -1;
+
+	memset (bos_buf, 0, sizeof(bos_buf));
+
+	ret = libusb_control_transfer(udev,
+			LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD |
+			      LIBUSB_RECIPIENT_DEVICE,
+			LIBUSB_REQUEST_GET_DESCRIPTOR,
+			LIBUSB_DT_BOS << 8, 0,
+			bos_buf, sizeof bos_buf, ctrl_timeout);
+
+	if (ret < 0 && errno != EPIPE) {
+		perror("can't get BOS");
+		return -1;
+	}
+
+	/* all supper-speed devices have a BOS */
+	if ((ret == 0) || (bos_buf[1] != LIBUSB_DT_BOS)) {
+		printf("not a BOS descriptor, buf[1]=%x\n", bos_buf[1]);
+		return -1;
+	}
+
+	libusb_parse_bos_desc(dev, bos, bos_buf);
+
+	return 0;
+}
+
+/**
+ * libusb_utils_get_device_by_num() - returns the device according to its
+ * bus number and device number
+ * @busnum: bus number
+ * @devnum: device number
+ *
+ * Returns pointer to the libusb device or NULL on failure
+ */
+libusb_device *libusb_utils_get_device_by_num(int busnum, int devnum)
+{
+	int i;
+	uint8_t bus, addr;
+	libusb_device *dev;
+
+	for (i = 0; (dev = devs[i]) != NULL; i++) {
+		bus = libusb_get_bus_number(dev);
+		addr = libusb_get_device_address(dev);
+
+
+		if (((busnum != -1) && (busnum != bus)) ||
+		    ((devnum != -1) && (devnum != addr)))
+			continue;
+
+		return dev;
+	}
+	return NULL;
+}
+
+/**
+ * libusb_utils_get_device_by_product_vendor() -returns the device according to
+ * its product ID and vendor ID
+ * @vendorid: vendor ID
+ * @productid: product ID
+ *
+ * Returns pointer to the libusb device or NULL on failure
+ */
+libusb_device *libusb_utils_get_device_by_product_vendor(int vendorid,
+							 int productid)
+{
+	int i;
+	libusb_device *dev;
+
+	for (i = 0; (dev = devs[i]) != NULL; i++) {
+		struct libusb_device_descriptor dev_desc;
+
+		if (libusb_get_device_descriptor(dev, &dev_desc) < 0) {
+			printf("Couldn't get device descriptor\n");
+			return NULL;
+		}
+		if (((vendorid != -1) && (vendorid != (int)dev_desc.idVendor))
+		    || ((productid != -1) &&
+			(productid != (int)dev_desc.idProduct))){
+			printf("dev_desc.idVendor = %d, dev_desc.idProduct = %d"
+			       "productid = %d, vendorid= %d\n",
+			       (int)dev_desc.idVendor,
+			       (int)dev_desc.idProduct, productid, vendorid);
+			continue;
+		}
+		return dev;
+	}
+	return NULL;
+}
+
+static struct libusb_uasp_pipe_usage_desc *get_pipe_usage_desc(
+	unsigned char *extra_ep_data,
+	int extra_length
+)
+{
+	struct libusb_uasp_pipe_usage_desc *pipe_usage_d = NULL;
+	if (extra_length < 0x04)
+		return NULL;
+	pipe_usage_d = (struct libusb_uasp_pipe_usage_desc *)extra_ep_data;
+	if (pipe_usage_d->bDescriptorType != LIBUSB_DT_PIPE_USAGE)
+		return NULL;
+	return pipe_usage_d;
+}
+
+/**
+ * get_ep_from_intrf() - returns the endpoint descriptor
+ * @dev: libusb device
+ * @ep_type: endpoint type (USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT})
+ * @interface: the interface in which ep list to search for the endpoint
+ * @pipeID - for UASP device specify the pipe id of the
+ *		 endpoint. If not a UASP device pipeID=0
+ *
+ * This function returns the endpoint descriptor (from a specified interfce)
+ * according to its transfer type direction, and if UASP device then pipe id.
+ *
+ * Returns the endpoint descriptor of the requested endpoint or NULL in case
+ * of error
+ */
+static struct libusb_endpoint_descriptor *get_ep_from_intrf(
+		struct libusb_interface *interface,
+		int direction,
+		int ep_type,
+		int pipeID
+)
+{
+	int i,j;
+	struct libusb_uasp_pipe_usage_desc *pipe_desc = NULL;
+	/* Go over interface alternate settings */
+	for (i = 0; i < interface->num_altsetting; i++) {
+		struct libusb_interface_descriptor *interface_desc =
+			(struct libusb_interface_descriptor *)
+					(interface->altsetting + i);
+		/* Go over the interface endpoints */
+		for (j = 0; j < interface_desc->bNumEndpoints; j++) {
+			struct libusb_endpoint_descriptor *ep_desc =
+				(struct libusb_endpoint_descriptor *)
+				(interface_desc->endpoint + j);
+			if (((ep_desc->bmAttributes &
+			      USB_ENDPOINT_XFERTYPE_MASK) == ep_type) &&
+			    ((ep_desc->bEndpointAddress &
+			     LIBUSB_ENDPOINT_DIR_MASK) == direction)){
+				if (!pipeID)
+					return ep_desc;
+
+				pipe_desc =
+					get_pipe_usage_desc(
+						(unsigned char*)ep_desc->extra,
+							ep_desc->extra_length);
+				if (pipe_desc &&
+				    (pipe_desc->bPipeID == pipeID))
+					return ep_desc;
+			}
+		}
+	}
+	return NULL;
+
+}
+
+/**
+ * libusb_utils_get_ep_desc() - returns the endpoint descriptor according to
+ * its transfer type, direction and if UASP device then pipe id.
+ * @dev: libusb device
+ * @ep_type: endpoint type (USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT})
+ * @intr_num: number of the interface the ep belongs to.
+ *	If this value is -1 then we'll return the first ep that is complient
+ *	with the direction and type, regardless of the interface
+ * @pipeID - for UASP device specify the pipe id of the
+ *		 endpoint. If not a UASP device pipeID=0
+ * Returns the endpoint descriptor of the requested endpoint or NULL in case
+ * of error
+ */
+struct libusb_endpoint_descriptor *libusb_utils_get_ep_desc(
+				libusb_device *dev,
+				int direction,
+				int ep_type,
+				int intr_num,
+				int pipeID)
+{
+	struct libusb_config_descriptor *config;
+	int k;
+	struct libusb_endpoint_descriptor *ret_val = NULL;
+
+	if (libusb_get_active_config_descriptor(dev, &config))
+		return NULL;
+
+	if ((intr_num > -1) && (intr_num < config->bNumInterfaces))
+		ret_val = get_ep_from_intrf(
+		      (struct libusb_interface *)(config->interface + intr_num),
+		      direction, ep_type, pipeID);
+	else {
+		for (k = 0; k < config->bNumInterfaces; k++) {
+			ret_val = get_ep_from_intrf(
+			     (struct libusb_interface *)(config->interface + k),
+			     direction, ep_type, pipeID);
+			if (ret_val)
+				return ret_val;
+		}
+	}
+	return ret_val;
+}
+
+/**
+ * libusb_utils_init() - initializes the libusb
+ *
+ * This function initializes the libusb and gets the list of devices.
+ * The function returns the number of devices
+ */
+int libusb_utils_init(void)
+{
+	int err = 0;
+
+	if (was_initialized)
+		return devcnt;
+
+	err = libusb_init(NULL);
+	if (err < 0)
+		return err;
+	devcnt = libusb_get_device_list(NULL, &devs);
+	was_initialized = true;
+
+	return devcnt;
+}
+
+
+/**
+ * libusb_utils_exit() - un-inits the libusb
+ *
+ * This function un-inits the libusb and frees the device list
+ */
+void libusb_utils_exit(void)
+{
+	libusb_free_device_list(devs, 1);
+	was_initialized = false;
+	libusb_exit(NULL);
+}
diff --git a/tools/usb/unittests/usb/libusb_utils.h b/tools/usb/unittests/usb/libusb_utils.h
new file mode 100644
index 0000000..96f9d93
--- /dev/null
+++ b/tools/usb/unittests/usb/libusb_utils.h
@@ -0,0 +1,149 @@
+/*
+ * libusb_utils.h - libusb utilities
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+extern "C" {
+#include <libusb.h>
+}
+
+/**
+ * libusb_utils_parse_descriptor() - gets a descriptor buffer and parses it
+ * to the descriptor message.
+ * @source: the descriptor buffer to be parsed
+ * @descriptor: the bit mapping of the descriptor, for example use "bbwd" for
+ *	parsing a descriptor that contains byte, byte, 16-bit word, 32-bit word.
+ * @dest: a pointer to the descriptor message
+ * @host_endian: set host_endian if the w values are already in host endian
+ *	format, as opposed to bus endian.
+ *
+ */
+int libusb_utils_parse_descriptor(unsigned char *source,
+				  char *descriptor, void *dest,
+				  int host_endian);
+
+
+/**
+ * libusb_utils_get_device_by_num() - returns the device according to its
+ * bus number and device number
+ * @busnum: bus number
+ * @devnum: device number
+ *
+ * Returns pointer to the libusb device or NULL on failure
+ */
+libusb_device *libusb_utils_get_device_by_num(int busnum, int devnum);
+
+
+/**
+ * libusb_utils_get_device_by_product_vendor() -returns the device according to
+ * its product ID and vendor ID
+ * @vendorid: vendor ID
+ * @productid: product ID
+ *
+ * Returns pointer to the libusb device or NULL on failure
+ */
+libusb_device *libusb_utils_get_device_by_product_vendor(int vendorid,
+							 int productid);
+
+/**
+ * libusb_utils_get_ep_desc() - returns the endpoint descriptor according to
+ * its transfer type, direction and if UASP device then pipe id.
+ * @dev: libusb device
+ * @ep_type: endpoint type (USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT})
+ * @intr_num: number of the interface the ep belongs to.
+ *	If this value is -1 then we'll return the first ep that is complient
+ *	with the direction and type, regardless of the interface
+ * @pipeID - for UASP device specify the pipe id of the
+ *		 endpoint. If not a UASP device pipeID=0
+ * Returns the endpoint descriptor of the requested endpoint or NULL in case
+ * of error
+ */
+struct libusb_endpoint_descriptor *libusb_utils_get_ep_desc(
+				libusb_device *dev,
+				int direction,
+				int ep_type,
+				int intr_num,
+				int pipeID);
+
+/**
+ * This function returns the endpoint descriptor according to
+ * its transfer type, direction and pipe usage.
+ * This function is used only with UASP device
+ *
+ * @param dev - libusb device
+ * @param ep_type - endpoint type (USB_ENDPOINT_XFER_{CONTROL,
+ *		  ISOC, BULK, INT})
+ * @param intr_num - number of the interface the ep belongs to.
+ *		   If this value is -1 then we'll return the
+ *		   first ep that is complient with the direction
+ *		   and type, regardless of the interface
+ * @param pipeID - the usage of the pipe, one of the bellow
+ *			PIPE_ID_CMD, PIPE_ID_STS, PIPE_ID_DATA_IN,
+ *			PIPE_ID_DATA_OUT
+ * @return - the endpoint descriptor of the requested endpoint
+ *	   or NULL in case of error
+ */
+struct libusb_endpoint_descriptor *libusb_utils_get_ep_desc_by_usage(
+				libusb_device *dev,
+				int direction,
+				int ep_type,
+				int intr_num,
+				u_int8_t pipeID);
+
+
+/**
+ * libusb_utils_get_bos_desc() - returns the BOS descriptor
+ * @dev: libusb device
+ * @udev: libusb device handle for the opened device
+ * @bos: the bos descriptor
+ *
+ * Returns 0 on success -1 on failure
+ *
+ * This function is relevent only for SS device.
+ */
+int libusb_utils_get_bos_desc(struct libusb_device *dev,
+		   struct libusb_device_handle *udev,
+		   struct libusb_bos_descriptor *bos);
+
+/**
+ * libusb_utils_init() - initializes the libusb
+ *
+ * This function initializes the libusb and gets the list of devices.
+ * The function returns the number of devices
+ */
+int libusb_utils_init(void);
+
+/**
+ * libusb_utils_exit() - un-inits the libusb
+ *
+ * This function un-inits the libusb and frees the device list
+ */
+void libusb_utils_exit(void);
+
diff --git a/tools/usb/unittests/usb/ss_expected_desc.h b/tools/usb/unittests/usb/ss_expected_desc.h
new file mode 100644
index 0000000..36c2e74
--- /dev/null
+++ b/tools/usb/unittests/usb/ss_expected_desc.h
@@ -0,0 +1,291 @@
+/*
+ * ss_expected_desc.h - Expected descriptors when opperation in SS mode
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include "libusb_utils.h"
+
+extern "C" {
+#include <linux/usb/ch9.h>
+}
+
+/*
+ * Device capability type codes. Table 9-11 from USB 3.0 spec
+ * This should be defined in ch9.h but is not. Untill then we
+ * define it here
+ */
+#define	USB_CAP_TYPE_USB20_EXTENSION	0x02
+#define	USB_CAP_TYPE_SUPERSPEED_USB	0x03
+#define	USB_CAP_TYPE_CONTAINER_ID	0x04
+
+
+/* This is the expected value for the SS device descriptor */
+struct libusb_device_descriptor ss_device_descriptor = {
+	18,			/* bLength; */
+	LIBUSB_DT_DEVICE,	/* bDescriptorType */
+	0x0300,			/* bcdUSB */
+	2,			/* bDeviceClass = LIBUSB_CLASS_COMM */
+	0,			/* bDeviceSubClass */
+	0,			/* bDeviceProtocol */
+	0x09,			/* bMaxPacketSize0 */
+	0x0525,			/* idVendor: May be different! */
+	0xa4a7,			/* idProduct: May be different! */
+	0,			/* bcdDevice. TODO: update */
+	0,			/* iManufacturer. May be different! */
+	1,			/* iProduct. May be different! */
+	2,			/* iSerialNumber. May be different!*/
+	1			/* bNumConfigurations */
+};
+
+/* This is the expected value for the SS device zero interface descriptor */
+struct libusb_interface_descriptor ss_zero_intr_descriptor = {
+	9,			/* bLength */
+	LIBUSB_DT_INTERFACE,	/* bDescriptorType */
+	0,			/* bInterfaceNumber */
+	0,			/* bAlternateSetting */
+	1,			/* bNumEndpoints */
+	LIBUSB_CLASS_COMM,	/* bInterfaceClass. May be different */
+	0,			/* bInterfaceSubClass. Should be different */
+	0,			/* bInterfaceProtocol. Should be different */
+	0,			/* iInterface. Should be different */
+	NULL,			/* endpoint */
+	NULL,			/* extra */
+	NULL			/* extra_length */
+};
+
+/* This is the expected value for the SS device interface descriptor */
+struct libusb_interface_descriptor ss_intr_descriptor = {
+	9,			/* bLength */
+	LIBUSB_DT_INTERFACE,	/* bDescriptorType */
+	1,			/* bInterfaceNumber */
+	0,			/* bAlternateSetting */
+	2,			/* bNumEndpoints */
+	LIBUSB_CLASS_DATA,	/* bInterfaceClass. May be different */
+	0,			/* bInterfaceSubClass. Should be different */
+	0,			/* bInterfaceProtocol. Should be different */
+	0,			/* iInterface. Should be different */
+	NULL,			/* endpoint */
+	NULL,			/* extra */
+	NULL			/* extra_length */
+};
+
+
+/* This is the expected value for the SS device BULK OUT endpoint descriptor */
+struct libusb_endpoint_descriptor ss_bulk_out_ep_desc = {
+	7,			/* bLength */
+	LIBUSB_DT_ENDPOINT,	/* bDescriptorType */
+	LIBUSB_ENDPOINT_OUT,	/* bEndpointAddress */
+	2,			/*
+				 * bmAttributes:Transfer Type	Bulk
+				 *		Synch Type	None
+				 *		Usage Type	Data
+				 */
+	1024,			/* wMaxPacketSize */
+	0,			/* bInterval */
+	0,			/* bRefresh; Not used */
+	0,			/* bSynchAddress; Not used */
+	NULL,			/* ep_comp */
+	NULL,			/* extra */
+	0			/* extra_length */
+};
+
+/*
+ * This is the expected (default) value for the SS device BULK OUT endpoint
+ * companion descriptor: bursting is not supported streaming is not supported
+ */
+struct libusb_ss_ep_comp_descriptor ss_bulk_out_ep_comp_desc = {
+	6,			/* bLength */
+	LIBUSB_DT_SS_ENDPOINT_COMP,/* bDescriptorType */
+	0,			/* bMaxBurst */
+	0,			/* bmAttributes */
+	0			/* wBytesPerInterval */
+};
+
+
+/* This is the expected value for the SS device BULK IN endpoint descriptor */
+struct libusb_endpoint_descriptor ss_bulk_in_ep_desc = {
+	7,			/* bLength */
+	LIBUSB_DT_ENDPOINT,	/* bDescriptorType */
+	LIBUSB_ENDPOINT_IN,	/* bEndpointAddress */
+	2,			/*
+				 * bmAttributes:Transfer Type	Bulk
+				 *		Synch Type	None
+				 *		Usage Type	Data
+				 */
+	1024,			/* wMaxPacketSize */
+	0,			/* bInterval */
+	0,			/* bRefresh. Not used since not audio device*/
+	0,			/* bSynchAddress. Not used */
+	NULL,			/* ep_comp */
+	NULL,			/* extra */
+	0			/* extra_length */
+};
+
+/*
+ * This is the expected (default) value for the SS device BULK IN endpoint
+ * companion descriptor: bursting is not supported, streaming is not supported
+ */
+struct libusb_ss_ep_comp_descriptor ss_bulk_in_ep_comp_desc = {
+	6,			/* bLength */
+	LIBUSB_DT_SS_ENDPOINT_COMP,/* bDescriptorType */
+	0,			/* bMaxBurst */
+	0,			/* bmAttributes */
+	0			/* wBytesPerInterval */
+};
+
+/* This is the expected value for the SS device INTERRUPT endpoint descriptor */
+struct libusb_endpoint_descriptor ss_intr_ep_desc = {
+	7,			/* bLength */
+	LIBUSB_DT_ENDPOINT,	/* bDescriptorType */
+	LIBUSB_ENDPOINT_IN,	/* bEndpointAddress */
+	3,			/*
+				 * bmAttributes:Transfer Type	Interrupt
+				 *		Synch Type	None
+				 *		Usage Type	Data
+				 */
+	0xa,			/* wMaxPacketSize */
+	9,			/* bInterval */
+	0,			/* bRefresh. Not used since not audio device*/
+	0,			/* bSynchAddress. */
+	NULL,			/* ep_comp */
+	NULL,			/* extra */
+	0			/* extra_length */
+};
+
+/*
+ * This is the expected (default) value for the SS device INTERRUPT endpoint
+ * companion descriptor: bursting is not supported, streaming is not supported
+ */
+struct libusb_ss_ep_comp_descriptor ss_intr_ep_comp_desc = {
+	6,			/* bLength */
+	LIBUSB_DT_SS_ENDPOINT_COMP,/* bDescriptorType */
+	0,			/* bMaxBurst */
+	0,			/* bmAttributes */
+	0xa			/* wBytesPerInterval */
+};
+
+/* This is the expected (default) value for the SS device BOS descriptor */
+struct libusb_bos_descriptor ss_bos_desc = {
+	5,			/* bLength */
+	USB_DT_BOS,		/* bDescriptorType */
+	22,			/* wTotalLength */
+	2,			/* bNumDeviceCaps */
+	NULL,			/* usb_ext_cap */
+	NULL			/* ss_usb_cap */
+};
+
+/*
+ * This is the expected (default) value for the SS device USB 2.0 Extension
+ * descriptor
+ */
+struct libusb_usb_ext_cap_descriptor ss_usb20_ext_desc = {
+	7,			/* bLength */
+	USB_DT_DEVICE_CAPABILITY,/* bDescriptorType */
+	USB_CAP_TYPE_USB20_EXTENSION,/* bDevCapabilityType */
+	0X02			/* bmAttributes: Support LPM */
+};
+
+/*
+ * This is the expected (default) value for the SS device SuperSpeed USB
+ * Capability descriptor: LTM not capble
+ */
+struct libusb_ss_usb_cap_descriptor ss_usb_capability_desc = {
+	10,			/* bLength */
+	USB_DT_DEVICE_CAPABILITY,/* bDescriptorType */
+	USB_CAP_TYPE_SUPERSPEED_USB,/* bDevCapabilityType */
+	0,			/* bmAttributes */
+	0x0f,			/* wSpeedSupported */
+	0x01,			/* bFunctionalitySupport */
+	1,			/* bU1devExitLat */
+	500			/* bU2DevExitLat */
+};
+
+
+/*
+ * Expected returned data values for the SS GET_STATUS tests
+ * (dummy_hcd configuration..)
+ */
+
+/* Expected result is 0x0001 - that means that only self-powered is enabled */
+unsigned char ss_get_status_default_device_expected[2] = { 0x01, 0x00};
+
+/* Expected result is 0x0005 - that means that self-powered, &U1 are enabled */
+unsigned char ss_get_status_U1_enabled_device_expected[2] = { 0x05, 0x00};
+
+/* Expected result is 0x0009 - that means that self-powered, & U2 are enabled */
+unsigned char ss_get_status_U2_enabled_device_expected[2] = { 0x09, 0x00};
+
+/* Expected result is 0x0011 - that means that self-powered & LTM are enabled */
+unsigned char ss_get_status_LTM_enabled_device_expected[2] = { 0x11, 0x00};
+
+/*
+ * Expected result is 0x0000 - that means that this interface is
+ * Remote-wakeup capable
+ */
+unsigned char ss_get_status_default_interface_expected[2] = { 0x00, 0x00};
+
+/* Expected result is 0x0001 - that means that this ep is halt enabled */
+unsigned char ss_get_status_halt_enabled_ep_expected[2] = { 0x01, 0x00};
+
+/* Expected result is 0x0000 - that means that this ep is not halted */
+unsigned char ss_get_status_default_ep_expected[2] = { 0x00, 0x00};
+
+/*
+ * Expected result is 0x0001 - that means that this interface's low power
+ * was enabled (lsb)
+ * In the case of g_zero due to the stub functionality, the
+ * expected value is 0x0000.
+ */
+unsigned char ss_get_status_suspend_low_power_interface_expected[2] = {
+	0x00, 0x00};
+
+/*
+ * Expected result is 0x0001 - that means that this interface's is remote
+ * wake up capable (bit #1)
+ */
+unsigned char ss_get_status_suspend_remote_wu_cap_interface_expected[2] = {
+	0x01, 0x00};
+
+/*
+ * Expected result is 0x0002 - that means that this interface's remote wake up
+ * was enabled (bit #2)
+ */
+unsigned char ss_get_status_suspend_remote_wu_en_interface_expected[2] = {
+	0x02, 0x00};
+
+/*
+* Expected result is 0x0003 - that means that this interface's is remote
+* wake up capable (bit #1) and was enabled (bit #2)
+*/
+unsigned char ss_get_status_suspend_remote_wu_en_cap_interface_expected[2] = {
+	0x03, 0x00};
diff --git a/tools/usb/unittests/usb/streams_tests.cc b/tools/usb/unittests/usb/streams_tests.cc
new file mode 100644
index 0000000..5954bdb
--- /dev/null
+++ b/tools/usb/unittests/usb/streams_tests.cc
@@ -0,0 +1,243 @@
+/*
+ * streams_tests.h - USB3 streams tests
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <linux/usb/ch9.h>
+
+#include "ut_config.h"
+#include "libusb_utils.h"
+#include "composite_tests.h"
+
+/**
+ * cb_transfer_complete() - Callback supplied to
+ * libusb_fill_bulk_transfer. The callback increases a counter
+ * implemented by the transfer's user_data variable.
+ * @transfer: the transfer that was cpmpleted
+ *
+ */
+static void cb_transfer_complete(struct libusb_transfer *transfer)
+{
+	int *completed = (int*)transfer->user_data;
+	fprintf(stderr, "cb_transfer_complete, user_data is %d \n", *completed);
+	if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
+		fprintf(stderr, "cb_transfer_complete with error %d\n",
+			transfer->status);
+	else
+		(*completed)++;
+}
+
+/**
+ * test_streams_bulk_loopback() - Initiate N bulk OUT transfers
+ * on N streams, and verify reception on bulk IN EP.
+ * @dev: libusb device to test
+ * @data_size: size of the data buffer to send
+ * @interface_id: interface id to run the test on
+ * @num_streams: number of streams
+ *
+ * Returns 0 on sucsess -1 for failure
+ */
+int test_streams_bulk_loopback(libusb_device *dev, int data_size,
+			 int interface_id, int num_streams)
+{
+	struct libusb_device_handle *udev;
+	struct libusb_endpoint_descriptor *out_ep, *in_ep;
+	unsigned char *data_out[num_streams];
+	unsigned char *data_in[num_streams];
+	int ret, i, j;
+	struct libusb_transfer *transfer[num_streams];
+	int completed = 0;
+	unsigned int eps = 0;
+
+	if (!dev)
+		return -1;
+
+	if (libusb_open(dev, &udev)) {
+		printf("Couldn't open device\n");
+		ret = -1;
+		goto test_bulk_loopback_done;
+	}
+
+	for (j = 0; j < num_streams; j++) {
+		transfer[j] = libusb_alloc_transfer(0);
+		if (!transfer[j]) {
+			printf("Couldn't alloc transfer\n");
+			ret = -1;
+			goto test_bulk_loopback_done;
+		}
+	}
+
+	for (j = 0; j < num_streams; j++) {
+		data_out[j] = (unsigned char *)malloc(data_size+10);
+		data_in[j] = (unsigned char *)malloc(data_size+10);
+	}
+
+
+	/* Fill in the OUT data buffer with a pattern corresponding to stream_id */
+	for (j = 0; j < num_streams; j++)
+		for (i = 0; i < data_size; i++)
+		{
+			data_out[j][i] = j+1;
+			data_in[j][i] = 0;
+		}
+
+	/* We should reset the gadget so it would expect stream IDs starting
+	   from 1 */
+	if (libusb_reset_device(udev) < 0)
+	{
+		printf("Couldn't reset device");
+		ret = -1;
+		goto test_bulk_loopback_done;
+	}
+
+	out_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_OUT,
+			     LIBUSB_TRANSFER_TYPE_BULK,
+			     interface_id, PIPE_ID_UNDEF);
+
+	if (!in_ep) {
+		printf("Didn't find BULK OUT endpoint!\n");
+		ret = -1;
+		goto test_bulk_loopback_done;
+	}
+
+	in_ep = libusb_utils_get_ep_desc(dev, LIBUSB_ENDPOINT_IN,
+				 LIBUSB_TRANSFER_TYPE_BULK,
+				 interface_id, PIPE_ID_UNDEF);
+
+	if (!in_ep) {
+		printf("Didn't find BULK IN endpoint!\n");
+		ret = -1;
+		goto test_bulk_loopback_done;
+	}
+
+	eps |= (1 << (in_ep->bEndpointAddress & LIBUSB_ENDPOINT_ADDRESS_MASK));
+	eps |= (0x10000 << (out_ep->bEndpointAddress & LIBUSB_ENDPOINT_ADDRESS_MASK));
+
+	printf("Allocting streams for ep map %d\n", eps);
+
+	/* Allocate streams (Current implementation allocates 256 streams) */
+	if (libusb_alloc_streams(udev, eps) < 0)
+	{
+		printf("Codn't alloc streams for OUT EP\n");
+		ret = -1;
+		goto test_bulk_loopback_done;
+	}
+
+	for (j = 0; j < num_streams; j++) {
+		libusb_fill_bulk_transfer(transfer[j], udev, out_ep->bEndpointAddress,
+			data_out[j], data_size, cb_transfer_complete, &completed,
+			BULK_TRANSFERR_TIMEOUT);
+		transfer[j]->flags = LIBUSB_TRANSFER_SHORT_NOT_OK
+		 | LIBUSB_TRANSFER_FREE_TRANSFER;
+	    transfer[j]->stream_id = j+1;
+		if (libusb_submit_transfer(transfer[j]) < 0) {
+			printf("Codn't submit transfer\n");
+			ret = -1;
+			goto test_bulk_loopback_done;
+		}
+	}
+
+	while (completed < num_streams)
+		libusb_handle_events(NULL);
+
+	for (j = 0; j < num_streams; j++) {
+		if (transfer[j]->actual_length != data_size) {
+			printf("The number of bytes actually transferred (%d) != "
+				   "data size (%d)", transfer[j]->actual_length, data_size);
+			ret = -1;
+			goto test_bulk_loopback_done;
+		}
+	}
+
+	completed = 0;
+
+	for (j = 0; j < num_streams; j++) {
+		transfer[j] = libusb_alloc_transfer(0);
+		if (!transfer[j]) {
+			printf("Couldn't alloc transfer\n");
+			ret = -1;
+			goto test_bulk_loopback_done;
+		}
+	}
+
+	for (j = 0; j < num_streams; j++) {
+		libusb_fill_bulk_transfer(transfer[j], udev, in_ep->bEndpointAddress,
+			data_in[j], data_size, cb_transfer_complete, &completed,
+			BULK_TRANSFERR_TIMEOUT);
+		transfer[j]->flags = LIBUSB_TRANSFER_SHORT_NOT_OK
+		 | LIBUSB_TRANSFER_FREE_TRANSFER;
+		transfer[j]->stream_id = j+1;
+		if (libusb_submit_transfer(transfer[j]) < 0) {
+			printf("Codn't submit transfer\n");
+			ret = -1;
+			goto test_bulk_loopback_done;
+		}
+	}
+
+	while (completed < num_streams)
+		libusb_handle_events(NULL);
+
+	for (j = 0; j < num_streams; j++) {
+		if (transfer[j]->actual_length != data_size) {
+			printf("The number of bytes actually transferred (%d) != "
+				"data size (%d)\n", transfer[j]->actual_length, data_size);
+			ret = -1;
+			goto test_bulk_loopback_done;
+		}
+		if (data_in[j][0] != transfer[j]->stream_id) {
+			printf("Epected data on stream is %d instead of %d\n", data_in[j][0],
+				transfer[j]->stream_id);
+			ret = -1;
+			goto test_bulk_loopback_done;
+		}
+	}
+
+	if (libusb_free_streams(udev, eps) < 0)
+	{
+		printf("Codn't free streams for OUT EP\n");
+		ret = -1;
+		goto test_bulk_loopback_done;
+	}
+
+	ret = 0;
+test_bulk_loopback_done:
+	libusb_close(udev);
+
+	for (j = 0; j < num_streams; j++) {
+		free(data_out[j]);
+		free(data_in[j]);
+	}
+
+	return ret;
+}
+
diff --git a/tools/usb/unittests/usb/streams_tests.h b/tools/usb/unittests/usb/streams_tests.h
new file mode 100644
index 0000000..5b1db91
--- /dev/null
+++ b/tools/usb/unittests/usb/streams_tests.h
@@ -0,0 +1,51 @@
+/*
+ * streams_tests.h - USB3 streams tests
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef STREAMS_TESTS_H
+#define STREAMS_TESTS_H
+
+#include <linux/kernel.h>
+#include "libusb_utils.h"
+
+/**
+ * test_streams_bulk_loopback() - Initiate N bulk OUT transfers
+ * on N streams, and verify reception on bulk IN EP.
+ * @dev: libusb device to test
+ * @data_size: size of the data buffer to send
+ * @interface_id: interface id to run the test on
+ * @num_streams: number of streams
+ *
+ * Returns 0 on sucsess -1 for failure
+ */
+int test_streams_bulk_loopback(libusb_device *dev, int data_size,
+			 int interface_id, int num_streams);
+
+#endif /*STREAMS_TESTS_H*/
diff --git a/tools/usb/unittests/usb/usb_devel_mode.cc b/tools/usb/unittests/usb/usb_devel_mode.cc
new file mode 100644
index 0000000..159a99b
--- /dev/null
+++ b/tools/usb/unittests/usb/usb_devel_mode.cc
@@ -0,0 +1,185 @@
+/*
+ * This file implements the option of running the Unit Test FW in
+ * development mode.
+ *
+  * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "usb_devel_mode.h"
+#include "UASP_tests.h"
+
+/* This enum defines the tests that can be run in development mode */
+enum devel_commands{
+	RUN_ALL_TESTS = 1,
+	SEND_SC_INQUIRY,
+	SEND_SC_REQUEST_SENSE,
+	TEST_UNIT_READY,
+	READ_CAPACITY,
+	MODE_SENSE,
+	MODE_SENSE10,
+	ALLOW_MEDIUM_REMOVAL,
+	READ_6,
+	READ_10,
+	READ_12,
+	WRITE_6,
+	WRITE_10,
+	WRITE_12,
+	WRITE10_HUGE,
+	READ_FORMAT_CAPACITIES,
+	TEST_START_STOP_UNIT,
+	TEST_VERIFY,
+	TEST_SYNC_CACHE,
+	TEST_TM_RESET_LUN,
+	TEST_TM_ABORT_TASK,
+	TEST_TM_ABORT_TASK_SET,
+	TEST_TM_RESET_NEXUS,
+	TEST_QUERY_ASYNC_EVENT,
+	TEST_QUERY_TASK,
+	TEST_QUERY_TASK_SET,
+	TEST_TM_TAG_OVERLAPP,
+	TEST_CMD_TAG_OVERLAPP,
+	ILEGAL_CMD  /* Should be the last one! */
+};
+
+struct exec_cmd {
+    int (*func)(struct libusb_device *dev);
+    char test_name[100];
+};
+
+/**
+ * print_mem() - dump memory in the given location
+ * @buf: pointer to the memory buffer to print
+ * @size: size of buffer to print
+ *
+ */
+void print_mem(unsigned char *buf, int size)
+{
+	int i;
+	printf("Memory dump at %x:\n	", buf);
+	for (i = 0; i < size; i++) {
+		printf(" 0x%02x", buf[i]);
+		if (!(i % 24))
+			printf("\n	");
+	}
+	printf("\n");
+}
+
+static int run_all_UASP_tests(struct libusb_device *dev);
+static struct exec_cmd cmd_arr[] = {
+	{run_all_UASP_tests, "All UASP Tests"},
+	{exec_send_inquiry, "INQUIRY CMD-IU (OpCode = 0x12)"},
+	{exec_send_request_sense, "REQUEST_SENSE CMD-IU (OpCode = 0x03)"},
+	{exec_test_unit_ready, "TEST_UNIT_READY (OpCode = 0x00)"},
+	{exec_send_read_capacity, "READ_CAPACITY (OpCode = 0x25)"},
+	{exec_send_mode_sense, "MODE_SENSE6 (OpCode = 0x01)"},
+	{exec_send_mode_sense10, "MODE_SENSE10 (OpCode = 0x5a)"},
+	{exec_send_prevent_allow_removal,
+		"ALLOW_MEDIUM_REMOVAL (OpCode = 0x1e)"},
+	{exec_test_read6, "READ_6 (OpCode = 0x08)"},
+	{exec_test_read10, "READ_10 (OpCode = 0x28)"},
+	{exec_test_read12, "READ_12 (OpCode = 0xa8)"},
+	{exec_test_write6, "WRITED_6 (OpCode = 0x0a)"},
+	{exec_test_write10, "WRITE_10 (OpCode = 0x2a)"},
+	{exec_test_write12, "WRITE_12 (OpCode = 0xaa)"},
+	{exec_test_write_huge, "WRITE10 with huge data"},
+	{exec_test_read_format_capacities,
+		"READ_FORMAT_CAPACITIES (OpCode = 0x23)"},
+	{exec_test_start_stop, "START_STOP_UNIT (OpCode = ox1b)"},
+	{exec_test_verify, "VERIFY (OpCode = 0x2f)"},
+	{exec_test_synchronize_cache, "SYNCHRONIZE CACHE (OpCode = 0x35)"},
+	{exec_test_tm_reset_lun, "TM LOGICAL UNIT RESET (Code = 0x08)"},
+	{exec_test_tm_abort_task, "TM ABORT TASK (Code = 0x01)"},
+	{exec_test_tm_abort_task_set, "TM ABORT TASK SET (Code = 0x02)"},
+	{exec_test_tm_reset_nexus, "TM RESET NEXUS (Code = 0x10)"},
+	{exec_test_tm_query_async_ev, "TM QUERY ASYNC EVENT (Code = 0x82)"},
+	{exec_test_tm_query_task, "TM QUERY TASK (Code = 0x80)"},
+	{exec_test_tm_query_task_set, "TM QUERY TASK SET (Code = 0x81)"},
+	{exec_test_tm_overlapped_tag, "Test TM IU Tag Overlapping"},
+	{exec_test_cmd_overlapped_tag, "Test CMD IU Tag Overlapping"},
+};
+
+static int run_all_UASP_tests(struct libusb_device *dev)
+{
+	int i, rc;
+	for (i = 1; i < ILEGAL_CMD -1; i++) {
+		printf("\n\n Running Test %s:\n", cmd_arr[i].test_name);
+		rc = cmd_arr[i].func(dev);
+		if (rc) {
+			printf("\n Test #%i (%s) Failed!\n", i+1,
+			       cmd_arr[i].test_name);
+			return rc;
+		}
+		sleep(1);
+	}
+	return rc;
+}
+
+int run_in_devel_mode(struct libusb_device *dev)
+{
+	int choice = 0;
+	int ret_val = 0;
+	int i = 0;
+
+	printf("\n\n\n---------------------------------------------"
+	       "---------------------------------------------------\n");
+
+	printf("Choose command to perform:\nUASP commands:\n"
+	       "	0. Exit\n");
+	for (i = 0; i < ILEGAL_CMD - 1; i++)
+		printf("	%d. Run %s test\n", i+1, cmd_arr[i].test_name);
+	printf("Enter your choice: ");
+	(void)scanf("%d",&choice);
+
+	while ((choice > 0) && (choice < ILEGAL_CMD)){
+		if (cmd_arr[choice-1].func)
+			ret_val = cmd_arr[choice-1].func(dev);
+		else
+			printf("Sorry, %d command is not yet implemented\n",
+			       choice);
+
+		printf("\n\n\n---------------------------------------------"
+		       "---------------------------------------------------\n");
+
+		printf("Choose command to perform:\nUASP commands:\n"
+		       "	0. Exit\n");
+		for (i = 0; i < ILEGAL_CMD - 1; i++)
+			printf("	%d. Run %s test\n", i+1,
+				cmd_arr[i].test_name);
+		printf("Enter your choice: ");
+		scanf("%d",&choice);
+	}
+
+	return ret_val;
+}
diff --git a/tools/usb/unittests/usb/usb_devel_mode.h b/tools/usb/unittests/usb/usb_devel_mode.h
new file mode 100644
index 0000000..03d9603
--- /dev/null
+++ b/tools/usb/unittests/usb/usb_devel_mode.h
@@ -0,0 +1,50 @@
+/*
+ * This file defines the option of running the Unit Test FW in
+ * development mode.
+ *
+  * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef _USB_DEVEL_MODE_H
+#define _USB_DEVEL_MODE_H
+
+#include "libusb_utils.h"
+
+int run_in_devel_mode(struct libusb_device *dev);
+
+
+/**
+ * print_mem() - dump memory in the given location
+ * @buf: pointer to the memory buffer to print
+ * @size: size of buffer to print
+ *
+ */
+void print_mem(unsigned char *buf, int size);
+
+#endif /*_USB_DEVEL_MODE_H*/
diff --git a/tools/usb/unittests/usb/usb_tests.cc b/tools/usb/unittests/usb/usb_tests.cc
new file mode 100644
index 0000000..bbbdbf2
--- /dev/null
+++ b/tools/usb/unittests/usb/usb_tests.cc
@@ -0,0 +1,651 @@
+/*
+ * This file defines the unit tests for a SuperSpeed/HighSpeed USB device.
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <limits.h>
+#include "g_serial_tests.h"
+#include "UASP_tests.h"
+#include "streams_tests.h"
+#include "composite_tests.h"
+#include "libusb_utils.h"
+#include <gtest/gtest.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <argp.h>
+#include "ut_config.h"
+#include "usb_tests.h"
+
+/**
+ * If this flag is set to 1, debug information wil be printed. Received as
+ * input parameter from user
+ */
+int ut_debug = 0;
+
+/**
+ * usb_tests_params - defines the tests parameters
+ * @busnum: the connected usb device bus number
+ * @devnum: the connected usb device number
+ * @vendorid: the connected usb device Vendor ID
+ * @productid: the connected usb deviceProduct ID
+ * @dev: the libusb devise to run the tests on
+ * @dev_speed: The speed of the connected usb device
+ * @num_expected_strms_in_ep: number of expected streams for IN EP's
+ *	ep_comp desc
+ * @num_expected_strms_out_ep: number of expected streams for OUT EP's
+ *	ep_comp desc
+ * @intr_num: number of the interface to run the test on
+ * @devel: Setting this flag to 1 will result in using the UT env for
+ *  	development purposes and none of the test suites will be run
+ * @uasp_dev: Setting this flag to 1 will result in running only the UASP
+ *	test suite
+ * @streams_dev: Setting this flag to 1 will result in running
+ *  only streams tests
+ */
+struct usb_tests_params {
+	int busnum;
+	int devnum;
+	int vendorid;
+	int productid;
+	struct libusb_device *dev;
+	enum usb_device_speed dev_speed;
+	int num_expected_strms_in_ep;
+	int num_expected_strms_out_ep;
+	int intr_num;
+	int devel;
+	int uasp_dev;
+	char gadget_sysfs_path[MAX_STRING_LEN];
+	int streams_dev;
+};
+
+/* Tests parameters */
+static struct usb_tests_params tests_params;
+
+/**
+ * print_params() - This function prints the usb tests parameters
+ * @p:pointer to the usb_tests_params structure
+ *
+ */
+void print_params(struct usb_tests_params *p)
+{
+	printf("busnum    = %d\n"
+	       "devnum    = %d\n"
+	       "vendorid  = %d\n"
+	       "productid = %d\n"
+	       "debug	  = %d\n"
+	       "num_expected_strms_in_ep = %d\n"
+	       "num_expected_strms_out_ep = %d\n"
+	       "interface_number = %d\n"
+	       "devel	  = %d\n"
+	       "uasp_dev	 = %d\n"
+	       "gadget_sysfs_path = %s\n",
+		   "streams_dev	 = %d\n",
+	       p->busnum, p->devnum, p->vendorid, p->productid, ut_debug,
+	       p->num_expected_strms_in_ep, p->num_expected_strms_out_ep,
+	       p->intr_num, p->devel, p->uasp_dev, p->gadget_sysfs_path,
+		   p->streams_dev);
+}
+
+/**
+ * options - Data structures defined for the parameters parsing as
+ * 	described in argp.h
+ *
+ * An array of parameters options to be used by argp to parse the parameters.
+ * The last field of the array should be NULL for terminating the search of
+ * the parameters.
+ */
+static struct argp_option options[] = {
+	/*{name,	key, arg,   flags, doc		group}*/
+	{ "busnum",	1, "integer", 0, "Bus number",	 1 },
+	{ "devnum",	2, "integer", 0, "Device number",1 },
+	{ "productid",	3, "integer", 0, "Product ID",	 2 },
+	{ "vendorid",	4, "integer", 0, "Vendor ID",	 2 },
+	{ "debug",	5, "integer", 0, "Debug Info",	 3 },
+	{ "gtest_output",6,"string",  0, "gtest_output", 3 },
+	{ "num_expected_strms_in_ep",7,"integer",  0,
+		"num_expected_strms for IN EP", 4 },
+	{ "num_expected_strms_out_ep",8,"integer",  0,
+		"num_expected_strms for OUT EP", 4 },
+	{ "interface",	9,  "integer", 0,
+		"interface number to run the tests on", 5},
+	{ "devel",	10, "integer", 0, "Development",  6},
+	{ "uasp_dev",   11, "integer", 0, "Run UASP tests",  6},
+	{ "gadget_sysfs_path", 12, "string", 0, "Gadget SYSFS Path", 6},
+	{ "streams_dev",   13, "integer", 0, "Run streams tests",  6},
+	{0, 0, 0, 0, 0, 0},
+};
+
+/**
+ * parse_opt() - This is an argp parsing function.
+ * @key:
+ * @arg:
+ * @state:
+ *
+ */
+static error_t parse_opt(int key, char *arg, struct argp_state *state)
+{
+	int x;
+	char string[MAX_STRING_LEN];
+
+	struct usb_tests_params *p = (struct usb_tests_params*)state->input;
+	if (arg && key != 12)
+		sscanf(arg, "%i", &x);
+	else if (arg)
+		sscanf(arg, "%s", string);
+
+	switch (key) {
+	case 1:
+		p->busnum = x;
+		break;
+	case 2:
+		p->devnum = x;
+		break;
+	case 3:
+		p->productid = x;
+		break;
+	case 4:
+		p->vendorid = x;
+		break;
+	case 5:
+		ut_debug = x;
+		break;
+	case 7:
+		p->num_expected_strms_in_ep = x;
+		break;
+
+	case 8:
+		p->num_expected_strms_out_ep = x;
+		break;
+	case 9:
+		p->intr_num = x;
+		break;
+	case 10:
+		p->devel = x;
+		break;
+	case 11:
+		p->uasp_dev = x;
+		break;
+	case 12:
+		strcpy(p->gadget_sysfs_path, string);
+		break;
+	case 13:
+		p->streams_dev = x;
+	}
+	return 0;
+}
+
+
+/**
+ * argp - Parsing state.
+ * An argp structure contains a set of options declarations, a function to
+ * deal with parsing one, documentation string, a possible vector of child
+ * argp's, and perhaps a function to filter help output.  When actually
+ * parsing options, getopt is called with the union of all the argp
+ * structures chained together through their CHILD pointers, with conflicts
+ * being resolved in favor of the first occurrence in the chain.
+ *
+ */
+static struct argp argp = { options, parse_opt,
+	"Googletest arguments",		/*args_doc*/
+	"usb tests parameters",		/*doc*/
+	0,				/*children*/
+	0,				/* help_filter*/
+	0				/*argp_domain*/
+};
+
+
+/**
+ * get_dev_speed() - returns the speed of the connected device.
+ *
+ * Return speed of the connected device.
+ * In case of an error return USB_SPEED_UNKNOWN
+ */
+enum usb_device_speed get_dev_speed(void){
+	return tests_params.dev_speed;
+}
+
+/**
+ * This function returns the true if the devel input gflag was
+ * set, meaning none of the test suites should be run.
+ *
+ * Returns bool - the value of tests_params.devel
+ */
+bool is_devel_mode(void)
+{
+	return tests_params.devel;
+}
+
+/**
+ * This function returns the true if the uasp_dev input flag was
+ * set, meaning only the UASP test suite should be run.
+ *
+ * Returns bool - the value of tests_params.uasp_dev
+ */
+bool is_uasp_device(void)
+{
+	return tests_params.uasp_dev;
+}
+
+/**
+ * This function returns the true if the streams_dev input flag
+ * was set, meaning streams tests should be run.
+ *
+ * Returns bool - the value of tests_params.streams_dev
+ */
+bool is_streams_device(void)
+{
+	return tests_params.streams_dev;
+}
+
+/**
+ * get_libusb_dev() - finds and returns the libusb device
+ *
+ * Return pointer to the libusb device or NULL on failier
+ *
+ * This function finds and returns the libusb device according to the input
+ * parameters: either device number and bus number or product id and vendor id
+ *
+ */
+libusb_device *get_libusb_dev(void)
+{
+	if (tests_params.busnum && tests_params.devnum) {
+		tests_params.dev = libusb_utils_get_device_by_num(
+			tests_params.busnum, tests_params.devnum);
+	}
+	else
+		tests_params.dev = libusb_utils_get_device_by_product_vendor(
+			tests_params.vendorid, tests_params.productid);
+	return tests_params.dev;
+}
+
+/**
+ * usb_tests_read_gadget_sysfs_file() - read from gadget sysfs file
+ * @path: path for the gadget sysfs file
+ *
+ * Return the integer read from the file
+ *
+ * This function reads an integer from given gadget sysfs file
+ */
+int usb_tests_read_gadget_sysfs_file(char* path)
+{
+	char filename[MAX_STRING_LEN];
+	FILE* file;
+	ssize_t nread;
+	int data;
+
+	sprintf(filename, "%s%s", tests_params.gadget_sysfs_path, path);
+	file = fopen(filename, "r");
+	if (file == NULL)
+		return -1;
+
+	nread = fscanf(file, "%d", &data);
+	if (nread <= 0)
+		return -1;
+
+	fclose(file);
+	return data;
+}
+
+/**
+ * usb_tests_write_gadget_sysfs_file_int() - writes to gadget sysfs file an
+ * integer value
+ * @path: path for the gadget sysfs file
+ * @value: value to write to the file
+ *
+ * Return 0 for sucsess, -1 for failure
+ *
+ * This function writes an integer from given gadget sysfs file
+ */
+int usb_tests_write_gadget_sysfs_file_int(char* path, int value)
+{
+	char filename[MAX_STRING_LEN];
+	FILE* file;
+	ssize_t nwrite;
+
+	sprintf(filename, "%s%s", tests_params.gadget_sysfs_path, path);
+	file = fopen(filename, "w");
+	if (file == NULL)
+		return -1;
+
+	nwrite = fprintf(file, "%d", value);
+	if (nwrite != 1)
+		return -1;
+
+	fclose(file);
+	return 0;
+}
+
+/**
+ * usb_tests_write_gadget_sysfs_file_str() - writes to gadget
+ * sysfs file a string value
+ * @path: path for the gadget sysfs file
+ * @value: value to write to the file
+ *
+ * Return 0 for sucsess, -1 for failure
+ *
+ * This function writes an integer from given gadget sysfs file
+ */
+int usb_tests_write_gadget_sysfs_file_str(char* path, char *value)
+{
+	char filename[MAX_STRING_LEN];
+	FILE* file;
+	ssize_t nwrite;
+
+	sprintf(filename, "%s%s", tests_params.gadget_sysfs_path, path);
+	file = fopen(filename, "w");
+	if (file == NULL)
+		return -1;
+
+	nwrite = fprintf(file, "%s", value);
+	if (nwrite != strlen(value))
+		return -1;
+
+	fclose(file);
+	return 0;
+}
+
+/**
+ * usb_tests_init() - init the libusb utility to be used by the tests.
+ * @argc: number of command line arguments
+ * @argv: command line arguments array
+ *
+ * Return 0 for success, -1 for failure
+ *
+ * This function initializes the libusb utility to be used by the tests.
+ * This function should be called prior to any libusb functions.
+ */
+int usb_tests_init(int argc, char **argv)
+{
+	int ret_val = 0;
+	memset ((void*)&tests_params, 0, sizeof(tests_params));
+
+	ret_val = argp_parse(&argp, argc, argv, 0, 0, &tests_params);
+	/* Verify input parameters */
+	if ((!tests_params.busnum || !tests_params.devnum) &&
+	    (!tests_params.productid || !tests_params.vendorid)) {
+		printf("Missing input! You must supply either busnum and "
+		       "devnum, or productid and vendorid\n");
+		return -1;
+	}
+
+	libusb_utils_init();
+
+	(void)get_libusb_dev();
+	if (!tests_params.dev) {
+		printf("Wrong input! Couldn't allocate device\n");
+		libusb_utils_exit();
+		return -1;
+	}
+
+	if (!ut_debug)
+		libusb_set_debug(NULL,0);
+
+	tests_params.dev_speed = (enum usb_device_speed)
+					libusb_get_dev_speed(tests_params.dev);
+
+	if (strlen(tests_params.gadget_sysfs_path) == 0)
+		strcpy(tests_params.gadget_sysfs_path,
+		       DEFAULT_GADGET_SYSFS_PATH);
+
+
+	return 0;
+}
+
+/**
+ * usb_tests_exit() - exit the libusb utility.
+ */
+void usb_tests_exit()
+{
+	libusb_utils_exit();
+}
+
+/* HS test cases */
+
+/* HS Descriptors tests */
+TEST(CompositeHSTests, test_hs_descriptors) {
+	EXPECT_EQ(0,test_hs_descriptors(tests_params.dev));
+}
+
+/* HS GET_STATUS tests */
+TEST(CompositeHSTests, test_hs_get_status_default_device) {
+	EXPECT_EQ(0, test_hs_get_status_default_device(tests_params.dev));
+}
+
+TEST(CompositeHSTests, test_hs_get_status_default_interface) {
+	EXPECT_EQ(0,
+		  test_hs_get_status_default_interface(tests_params.dev,
+						  tests_params.intr_num));
+}
+
+TEST(CompositeHSTests, test_hs_get_status_default_ep) {
+	EXPECT_EQ(0, test_hs_get_status_default_ep(tests_params.dev,
+						   tests_params.intr_num));
+}
+
+/* HS SET_FEATURE tests */
+TEST(CompositeHSTests, test_hs_set_feature_suspend_interface) {
+	EXPECT_EQ(0, test_hs_set_feature_suspend_interface(tests_params.dev,
+						   tests_params.intr_num));
+}
+
+TEST(CompositeHSTests, test_hs_set_feature_halt_ep) {
+	EXPECT_EQ(0, test_hs_set_feature_halt_ep(tests_params.dev,
+						 tests_params.intr_num));
+}
+
+/* SS test cases */
+
+/* SS Descriptors tests */
+TEST(CompositeSSTests, test_ss_descriptors) {
+	EXPECT_EQ(0, test_ss_descriptors(tests_params.dev,
+				 tests_params.num_expected_strms_in_ep,
+				 tests_params.num_expected_strms_out_ep));
+}
+
+/* SS GET_STATUS tests */
+TEST(CompositeSSTests, test_ss_get_status_default_device) {
+	EXPECT_EQ(0, test_ss_get_status_default_device(tests_params.dev));
+}
+
+TEST(CompositeSSTests, test_ss_get_status_default_interface) {
+	EXPECT_EQ(0,
+		  test_ss_get_status_default_interface(tests_params.dev,
+						  tests_params.intr_num));
+}
+
+TEST(CompositeSSTests, test_ss_get_status_default_ep) {
+	EXPECT_EQ(0, test_ss_get_status_default_ep(tests_params.dev,
+						   tests_params.intr_num));
+}
+
+/* SS SET_FEATURE tests */
+
+TEST(CompositeSSTests, test_ss_set_feature_u1_device) {
+	EXPECT_EQ(0, test_ss_set_feature_u1_device(tests_params.dev));
+}
+
+TEST(CompositeSSTests, test_ss_set_feature_u2_device) {
+	EXPECT_EQ(0, test_ss_set_feature_u2_device(tests_params.dev));
+}
+
+TEST(CompositeSSTests, test_ss_set_feature_ltm_device) {
+	EXPECT_EQ(0, test_ss_set_feature_ltm_device(tests_params.dev));
+}
+
+TEST(CompositeSSTests, test_ss_set_feature_halt_ep) {
+	EXPECT_EQ(0, test_ss_set_feature_halt_ep(tests_params.dev,
+						 tests_params.intr_num));
+}
+
+TEST(CompositeSSTests, test_ss_set_feature_suspend_low_power_interface) {
+	EXPECT_EQ(0, test_ss_set_feature_suspend_low_power_interface(
+		tests_params.dev, tests_params.intr_num));
+}
+
+TEST(CompositeSSTests, test_ss_set_feature_suspend_remote_wakeup_interface) {
+	EXPECT_EQ(0, test_ss_set_feature_suspend_remote_wakeup_interface(
+		tests_params.dev, tests_params.intr_num));
+}
+
+
+/* General test cases */
+TEST(SerialTests, test_single_bulk_in){
+	EXPECT_EQ(0, test_single_bulk_in(tests_params.dev, 40,
+					 tests_params.intr_num));
+}
+
+TEST(SerialTests, test_single_bulk_out){
+	EXPECT_EQ(0, test_single_bulk_out(tests_params.dev, 40,
+					  tests_params.intr_num));
+}
+
+/* Streams test cases*/
+TEST(StreamsTests, test_streams_bulk_loopback) {
+	EXPECT_EQ(0, test_streams_bulk_loopback(tests_params.dev, 40,
+		tests_params.intr_num, 8));
+}
+
+/* This test should be the last one since it changes the libusb device */
+TEST(DummyTests, test_connect_disconnect) {
+	EXPECT_EQ(0, test_connect_disconnect(tests_params.dev,
+				tests_params.dev_speed,
+				tests_params.num_expected_strms_in_ep,
+				tests_params.num_expected_strms_out_ep));
+}
+
+/* UASP Test cases */
+TEST(UASPTests, exec_send_inquiry) {
+	EXPECT_EQ(0, exec_send_inquiry(tests_params.dev));
+}
+
+TEST(UASPTests, exec_send_request_sense) {
+	EXPECT_EQ(0, exec_send_request_sense(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_unit_ready) {
+	EXPECT_EQ(0, exec_test_unit_ready(tests_params.dev));
+}
+
+
+TEST(UASPTests, exec_send_read_capacity) {
+	EXPECT_EQ(0, exec_send_read_capacity(tests_params.dev));
+}
+
+TEST(UASPTests, exec_send_mode_sense) {
+	EXPECT_EQ(0, exec_send_mode_sense(tests_params.dev));
+}
+
+TEST(UASPTests, exec_send_mode_sense10) {
+	EXPECT_EQ(0, exec_send_mode_sense10(tests_params.dev));
+}
+
+TEST(UASPTests, exec_send_prevent_allow_removal) {
+	EXPECT_EQ(0, exec_send_prevent_allow_removal(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_read6) {
+	EXPECT_EQ(0, exec_test_read6(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_read10) {
+	EXPECT_EQ(0, exec_test_read10(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_read12) {
+	EXPECT_EQ(0, exec_test_read12(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_write6) {
+	EXPECT_EQ(0, exec_test_read12(tests_params.dev));
+}
+TEST(UASPTests, exec_test_write10) {
+	EXPECT_EQ(0, exec_test_read12(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_write12) {
+	EXPECT_EQ(0, exec_test_read12(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_write_huge) {
+	EXPECT_EQ(0, exec_test_write_huge(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_read_format_capacities){
+	EXPECT_EQ(0, exec_test_read_format_capacities(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_start_stop){
+	EXPECT_EQ(0, exec_test_start_stop(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_verify){
+	EXPECT_EQ(0, exec_test_verify(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_synchronize_cache){
+	EXPECT_EQ(0, exec_test_synchronize_cache(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_tm_reset_lun){
+	EXPECT_EQ(0, exec_test_tm_reset_lun(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_tm_abort_task){
+	EXPECT_EQ(0, exec_test_tm_abort_task(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_tm_abort_task_set){
+	EXPECT_EQ(0, exec_test_tm_abort_task_set(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_tm_reset_nexus){
+	EXPECT_EQ(0, exec_test_tm_reset_nexus(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_tm_query_async_ev){
+	EXPECT_EQ(0, exec_test_tm_query_async_ev(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_tm_query_task){
+	EXPECT_EQ(0, exec_test_tm_query_task(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_tm_query_task_set){
+	EXPECT_EQ(0, exec_test_tm_query_task_set(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_tm_overlapped_tag){
+	EXPECT_EQ(0, exec_test_tm_overlapped_tag(tests_params.dev));
+}
+
+TEST(UASPTests, exec_test_cmd_overlapped_tag){
+	EXPECT_EQ(0, exec_test_cmd_overlapped_tag(tests_params.dev));
+}
+
diff --git a/tools/usb/unittests/usb/usb_tests.h b/tools/usb/unittests/usb/usb_tests.h
new file mode 100644
index 0000000..0d1b2ba
--- /dev/null
+++ b/tools/usb/unittests/usb/usb_tests.h
@@ -0,0 +1,146 @@
+/*
+ * usb_tests.h - general usb tests functions
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef USB_TEST_H
+#define USB_TEST_H
+
+extern "C" {
+#include <linux/usb/ch9.h>
+}
+
+#include "libusb.h"
+
+#define GADGET_SUSPENED_SYSFS_PATH "suspened"
+#define GADGET_ZERO_FUNC_SUSPENDED_SYSFS_PATH "sourcesink/func_suspend"
+#define ZERO_GADGET_ZERO_FUNC_WAKEUP_CAPABLE_SYSFS_PATH \
+	"sourcesink/func_wakeup_capable"
+#define ZERO_GADGET_ZERO_FUNC_WAKEUP_ENABLED_SYSFS_PATH \
+	"sourcesink/func_wakeup_enabled"
+#define ZERO_GADGET_ZERO_FUNC_WAKEUP_TRIGGER_SYSFS_PATH \
+	"sourcesink/func_wakeup_trigger"
+
+/**
+ * get_libusb_dev() - finds and returns the libusb device
+ *
+ * Return pointer to the libusb device or NULL on failier
+ *
+ * This function finds and returns the libusb device according to the input
+ * parameters: either device number and bus number or product id and vendor id
+ *
+ */
+libusb_device *get_libusb_dev(void);
+
+
+/**
+ * usb_tests_init() - init the libusb utility to be used by the tests.
+ * @argc: number of command line arguments
+ * @argv: command line arguments array
+ *
+ * Return 0 for sucsess, -1 for failier
+ *
+ * This function initializes the libusb utility to be used by the tests.
+ * This function should be called prior to any libusb functions.
+ */
+int usb_tests_init(int argc, char **argv);
+
+/**
+ * get_dev_speed() - returns the speed of the connected device.
+ *
+ * Return speed of the connected device.
+ * In case of an error return USB_SPEED_UNKNOWN
+ */
+enum usb_device_speed get_dev_speed(void);
+
+/**
+ * usb_tests_exit() - exit the libusb utility.
+ */
+void usb_tests_exit();
+
+/**
+ * This function returns the true if the devel input gflag was
+ * set, meaning none of the test suites should be run.
+ *
+ * Return bool - the value of tests_params.devel
+ */
+bool is_devel_mode(void);
+
+/**
+ * This function returns the true if the uasp_dev input gflag
+ * was set, meaning only the UASP test suite should be run.
+ *
+ * Returns bool - the value of tests_params.uasp_dev
+ */
+bool is_uasp_device(void);
+
+/**
+ * This function returns the true if the streams_dev input flag
+ * was set, meaning streams tests should be run.
+ *
+ * Returns bool - the value of tests_params.streams_dev
+ */
+bool is_streams_device(void);
+
+/*
+ * usb_tests_read_gadget_sysfs_file() - read from gadget sysfs file
+ * @path: path for the gadget sysfs file
+ *
+ * Return the integer read from the file
+ *
+ * This function reads an integer from given gadget sysfs file
+ */
+int usb_tests_read_gadget_sysfs_file(char *path);
+
+/**
+ * usb_tests_write_gadget_sysfs_file_int() - writes to gadget sysfs file an
+ * integer value
+ * @path: path for the gadget sysfs file
+ * @value: value to write to the file
+ *
+ * Return 0 for sucsess, -1 for failure
+ *
+ * This function writes an integer from given gadget sysfs file
+ */
+int usb_tests_write_gadget_sysfs_file_int(char *path, int value);
+
+/**
+ * usb_tests_write_gadget_sysfs_file_str() - writes to gadget
+ * sysfs file a string value
+ * @path: path for the gadget sysfs file
+ * @value: value to write to the file
+ *
+ * Return 0 for sucsess, -1 for failure
+ *
+ * This function writes an integer from given gadget sysfs file
+ */
+int usb_tests_write_gadget_sysfs_file_str(char *path, char *value);
+
+#endif /*USB_TEST_H*/
diff --git a/tools/usb/unittests/usb/usb_tests_main.cc b/tools/usb/unittests/usb/usb_tests_main.cc
new file mode 100644
index 0000000..cabbfbe
--- /dev/null
+++ b/tools/usb/unittests/usb/usb_tests_main.cc
@@ -0,0 +1,83 @@
+/*
+ * usb_tests_main.cc - main file of the Unit Tests Framework
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+
+#include <iostream>
+#include <stdio.h>
+
+#include <gtest/gtest.h>
+#include "usb_tests.h"
+
+#include "usb_devel_mode.h"
+
+int main(int argc, char **argv) {
+
+	int ret_val = 0;
+	char *updated_argv[argc+1];
+	char hs_filter[] = "--gtest_filter=-*SS*:*UASP*:*Streams*";
+	char ss_filter[] = "--gtest_filter=-*HS*:*UASP*:*Streams*";
+	int i;
+
+	if (usb_tests_init(argc, argv))
+		return -1;
+
+    if (is_devel_mode())
+	    return run_in_devel_mode(get_libusb_dev());
+
+	/* get current device speed and update tests filter according to it*/
+	for (i = 0; i < argc; i++) {
+		updated_argv[i] = argv[i];
+	}
+
+	if (is_uasp_device())
+		updated_argv[i] = "--gtest_filter=*UASP*";
+	else if (is_streams_device())
+		updated_argv[i] = "--gtest_filter=*Streams*";
+	else
+		switch (get_dev_speed()) {
+		case USB_SPEED_SUPER:
+			updated_argv[i] = ss_filter;
+			break;
+		default:
+			updated_argv[i] = hs_filter;
+		}
+	argc++;
+
+	testing::InitGoogleTest(&argc, updated_argv);
+
+	ret_val = RUN_ALL_TESTS();
+
+	usb_tests_exit();
+
+	return ret_val;
+}
diff --git a/tools/usb/unittests/usb/ut_config.h b/tools/usb/unittests/usb/ut_config.h
new file mode 100644
index 0000000..9148796
--- /dev/null
+++ b/tools/usb/unittests/usb/ut_config.h
@@ -0,0 +1,89 @@
+/*
+ * ut_config.h - Unittests global variables and defenitions
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef UT_CONFIG
+#define UT_CONFIG
+
+/*
+ * This is the timeout (in millseconds) to wait before giving up
+ * on a bulk transfer due to no response being received.
+ */
+#define BULK_TRANSFERR_TIMEOUT 2000
+
+/*
+ * This is the timeout (in millseconds) to wait before giving up
+ * on a control request due to no response being received.
+ */
+#define CTL_REQ_TRANSFERR_TIMEOUT 2000
+
+/*
+ * This is the timeout (in seconds) to wait for the device to
+ * recconect in connect/disconnect test
+ */
+#define WAIT_FOR_CONN 2
+
+/*
+ * This is control request code to be sent to gadget zero
+ * (soursesink) to initiate a connect/disconnect sequence
+ */
+#define CONN_DISCONN_TEST 0x52
+
+/*
+ * This is control request code to be sent to gadget zero
+ * (soursesink) to set up the bulk buffer size
+ */
+#define SET_BULK_BUF_SIZE 0x5e
+
+/*
+ * These are features selectors of the HALT, U1, U2, LTM ,
+ * SUSPEND & REMOTE_WU for the SET_FEATURE command
+ */
+#define HALT_ENABLE_FEATURE_SEL      0
+#define SUSPEND_ENABLE_FEATURE_SEL   0
+#define U1_ENABLE_FEATURE_SEL        48
+#define U2_ENABLE_FEATURE_SEL        49
+#define LTM_ENABLE_FEATURE_SEL       50
+
+#define FUNC_SUSPEND_OPT_LOW_POWER   0x1
+#define FUNC_SUSPEND_OPT_WAKEUP_EN   0x2
+
+#define MAX_STRING_LEN 255
+#define DEFAULT_GADGET_SYSFS_PATH \
+	"/sys/devices/platform/dummy_udc/gadget/"
+
+/*
+ * If this flag is set to 1, debug information wil be printed.
+ * Received as input parameter from user
+ */
+extern int ut_debug;
+
+#endif /*UT_CONFIG*/
-- 
1.7.0.4

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ