All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tatyana Brokhman <tlinder@codeaurora.org>
To: balbi@ti.com
Cc: linux-usb@vger.kernel.org, linux-arm-msm@vger.kernel.org,
	ablay@codeaurora.org, Tatyana Brokhman <tlinder@codeaurora.org>,
	open list <linux-kernel@vger.kernel.org>
Subject: [RFC/PATCH/RESEND 1/3] usb unittests framework: test files
Date: Wed, 22 Jun 2011 11:34:08 +0300	[thread overview]
Message-ID: <1308731651-7397-2-git-send-email-tlinder@codeaurora.org> (raw)
In-Reply-To: <1308731651-7397-1-git-send-email-tlinder@codeaurora.org>

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

Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.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.

WARNING: multiple messages have this Message-ID (diff)
From: Tatyana Brokhman <tlinder@codeaurora.org>
To: balbi@ti.com
Cc: linux-usb@vger.kernel.org, linux-arm-msm@vger.kernel.org,
	ablay@codeaurora.org, Tatyana Brokhman <tlinder@codeaurora.org>,
	linux-kernel@vger.kernel.org (open list)
Subject: [RFC/PATCH/RESEND 1/3] usb unittests framework: test files
Date: Wed, 22 Jun 2011 11:34:08 +0300	[thread overview]
Message-ID: <1308731651-7397-2-git-send-email-tlinder@codeaurora.org> (raw)
In-Reply-To: <1308731651-7397-1-git-send-email-tlinder@codeaurora.org>

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

Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.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.

  reply	other threads:[~2011-06-22  8:34 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-06-22  8:34 [RFC/PATCH/RESEND 0/3] usb:tools: usb unittests framework Tatyana Brokhman
2011-06-22  8:34 ` Tatyana Brokhman [this message]
2011-06-22  8:34   ` [RFC/PATCH/RESEND 1/3] usb unittests framework: test files Tatyana Brokhman
     [not found] ` <1308731651-7397-1-git-send-email-tlinder-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2011-06-22  8:34   ` [RFC/PATCH/RESEND 2/3] usb unittests framework: Documentation Tatyana Brokhman
2011-06-22  8:34     ` Tatyana Brokhman
2011-06-22  8:34 ` [RFC/PATCH/RESEND 3/3] usb unitests framework: libusb patches Tatyana Brokhman
2011-06-22  8:34   ` Tatyana Brokhman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1308731651-7397-2-git-send-email-tlinder@codeaurora.org \
    --to=tlinder@codeaurora.org \
    --cc=ablay@codeaurora.org \
    --cc=balbi@ti.com \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.