[RFC/PATCH/RESEND 1/3] usb unittests framework: test files

From: Tatyana Brokhman
Date: Wed Jun 22 2011 - 04:37:31 EST


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

Signed-off-by: Tatyana Brokhman <tlinder@xxxxxxxxxxxxxx>

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

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

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