All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH/RFC 1/5] usb:tools: usb unittests framework
@ 2011-06-16 13:31 ` Tatyana Brokhman
  0 siblings, 0 replies; 54+ messages in thread
From: Tatyana Brokhman @ 2011-06-16 13:31 UTC (permalink / raw)
  To: greg; +Cc: linux-usb, linux-arm-msm, balbi, ablay, Tatyana Brokhman, open list

This patch introduces a user-space framework for developing unit tests in
order to test the USB functionality of a connected device.
These tests communicate with the USB device via libusb interface.
They are meant to run with the g_zero and dummy_hcd module since several
proprietary control messages were added to those modules. But a smaller
subset of the tests can be run on any USB device and on real UDCs.

Implemented tests:
1. Test device descriptors - this test is applicable both for HS and SS
   devices
2. Test the SET_FEATURE requests
3. Test bulk in
4. Test bulk out
5. Test connect/disconnect
6. Streams capability testing
7. UAS test suite

This patch also includes patches that should be applied to libusb.
Some of them were already sent upstream for approval but not yet accepted.
Other will be sent in the near future.

For more info please read the files under Documentation.

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

---
 .../usb/unittests/Documentation/autoconfig_readme  |   20 +
 .../usb/unittests/Documentation/create-gadget-img  |   47 +
 tools/usb/unittests/Documentation/unittests-info   |  526 +++++
 tools/usb/unittests/Documentation/unittests-setup  |  127 ++
 .../0001-Add-support-to-USB3-descriptors.patch     |  420 ++++
 ...2-Add-support-for-libusb_get_device_speed.patch |  172 ++
 .../libusb_patches/0003-Add-UAS-defines.patch      |   56 +
 .../0004-libusb-Add-stream-support-to-LIBUSB.patch |  314 +++
 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         | 1645 +++++++++++++++
 tools/usb/unittests/usb/composite_tests.h          |  293 +++
 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 +
 29 files changed, 10377 insertions(+), 0 deletions(-)
 create mode 100644 tools/usb/unittests/Documentation/autoconfig_readme
 create mode 100644 tools/usb/unittests/Documentation/create-gadget-img
 create mode 100644 tools/usb/unittests/Documentation/unittests-info
 create mode 100644 tools/usb/unittests/Documentation/unittests-setup
 create mode 100644 tools/usb/unittests/libusb_patches/0001-Add-support-to-USB3-descriptors.patch
 create mode 100644 tools/usb/unittests/libusb_patches/0002-Add-support-for-libusb_get_device_speed.patch
 create mode 100644 tools/usb/unittests/libusb_patches/0003-Add-UAS-defines.patch
 create mode 100644 tools/usb/unittests/libusb_patches/0004-libusb-Add-stream-support-to-LIBUSB.patch
 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/Documentation/autoconfig_readme b/tools/usb/unittests/Documentation/autoconfig_readme
new file mode 100644
index 0000000..07112e1
--- /dev/null
+++ b/tools/usb/unittests/Documentation/autoconfig_readme
@@ -0,0 +1,20 @@
+
+Questions can be refereed to tlinder@codeaurora.org.
+Copyright (C) 2011 Code Aurora Forum. All rights reserved
+
+Description
+-----------
+This script is used to automatically configure the kernel .config file
+(instead of using menuconfig).
+This script should be ran after using defconfig.
+
+Please note that the script modifies the .config file under out-32 (and
+should be executed in the out-32 directory).
+
+The script activates the dummy_HCD controller and configures the gadget
+to operate in  a SS mode.
+
+--
+Created by a consultant of the Qualcomm Innovation Center, Inc.
+The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
+
diff --git a/tools/usb/unittests/Documentation/create-gadget-img b/tools/usb/unittests/Documentation/create-gadget-img
new file mode 100644
index 0000000..edb34a7
--- /dev/null
+++ b/tools/usb/unittests/Documentation/create-gadget-img
@@ -0,0 +1,47 @@
+
+Questions can be refereed to tlinder@codeaurora.org.
+Copyright (C) 2011 Code Aurora Forum. All rights reserved
+
+
+This is how disk is built:
+-------------------------
+VM points to the location of the Virtual Machine
+
+cd $VM
+mkdir rootfs
+# create unformatted image
+qemu-img create -f raw gadget.img 600M
+# format it with ext2
+mkfs.ext2 -F gadget.img
+# mount
+fuseext2 gadget.img rootfs -o rw+
+# populate disk with basic Linux installation
+debootstrap --arch=i386 karmic rootfs
+
+#prepare image for real life
+echo "proc            /proc           proc    defaults        0       0" >> rootfs/etc/fstab
+echo "/dev/sda        /               ext2    defaults        0       0" >> rootfs/etc/fstab
+
+echo "user    ALL=(ALL) ALL" >> rootfs/etc/sudoers
+
+echo "auto lo" >> rootfs/etc/network/interfaces
+echo "iface lo inet loopback" >> rootfs/etc/network/interfaces
+echo "auto eth0" >> rootfs/etc/network/interfaces
+echo "iface eth0 inet dhcp" >> rootfs/etc/network/interfaces
+
+#unmount it
+fusermount -u rootfs
+
+Boot in a single mode (use -append "root=/dev/sda single"); in the VM, execute:
+
+useradd user
+passwd -d user
+echo "root:root00" | chpasswd
+apt-get --yes install openssh-server
+halt
+
+NOTE: instructions are incomplete
+
+--
+Created by a consultant of the Qualcomm Innovation Center, Inc.
+The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
\ No newline at end of file
diff --git a/tools/usb/unittests/Documentation/unittests-info b/tools/usb/unittests/Documentation/unittests-info
new file mode 100644
index 0000000..163b270
--- /dev/null
+++ b/tools/usb/unittests/Documentation/unittests-info
@@ -0,0 +1,526 @@
+
+Questions can be refereed to tlinder@codeaurora.org.
+Copyright (C) 2011 Code Aurora Forum. All rights reserved
+
+1: INPUT PARAMETERS
+-------------------
+
+Usb_test receives the following input parameters:
+1.int busnum - the bus number of the USB device to run the tests on
+2.int devnum - the device number of the USB device to run the tests on
+3.int productid - the product id of the USB device to run the tests on
+4.int vendorid - the vendor id of the USB device to run the tests on
+The above data can be retrieved by running lsusb command on the VM/Linux host
+the USB device is connected to.
+Note: You should provide either busnum and devnum or productid and vendorid
+as an input.
+5.int num_expected_strms_in_ep - the number of expected streams for IN EP's
+  ep_comp desc
+6.int num_expected_strms_out_ep - the number of expected streams for OUT EP's
+  ep_comp desc
+7.int intr_num - the number of the interface to run the test on
+8.int devel - set this flag to 1 if you wish to run in development mode.
+  (Refer to section 3 for more details)
+9.int uasp_dev - set this flag to 1 if running the test on a UAS Gadget driver
+10.int debug - this flag indicates if debug information will be printed or not.
+  The default is that no debug info will be printed (debug = 0). You can change
+  that by setting debug = 1 (optional)
+11.int streams_dev - Setting this flag to 1 will result in running only streams
+  tests
+12.char gadget_sysfs_path[MAX_STRING_LEN] - Gadget sysfs path. The default is:
+  "/sys/devices/platform/dummy_udc/gadget/"
+
+Example:
+./usb_tests --busnum=2 --devnum=3 --debug=1
+
+
+2: RUNNING A SUBSET OF THE TESTS (ACCORDING TO DEVICE SPEED)
+------------------------------------------------------------
+
+On Unittests initialization the speed of the connected device is read and the
+appropriate test suite is excluded from the tests to run. Meaning if it's a
+HS/SS device CompositeSSTests/ CompositeHSTests won't be run.
+Beside this exception GoogleTest will run all the test suites.
+
+
+3. RUNNING IN DEVELOPMENT MODE
+------------------------------
+
+It's possible to choose a test to run. In order to do so run the test in
+development mode, meaning
+	./usb_tests --busnum=2 --devnum=3 -devel=1
+This will open a list of test for you to choose which test to run.
+At the moment this option is developed for UAS tests only but other tests can be
+easily added to this menu.
+
+4: IMPLEMENTED TESTS
+--------------
+
+4.1: DUMMY TESTS
+
+4.1.1 test_connect_disconnect
+  Test Suite: DummyTests
+  Test Name: test_connect_disconnect
+  Test Description:
+  This test verifies the connect&disconnect sequence.
+  Verification is done by testing the correct enumeration descriptors were sent
+  (according to speed).
+
+
+4.2: COMPOSITE HS TESTS
+
+This test suite is applicable only for a HS device. The test in this suite
+verify chapter 9 requests that are applicable only to HS device.
+For example: HS descriptors.
+
+4.2.1 Test_hs_descriptors
+  Test Suite: CompositeHSTests
+  Test Name: test_hs_descriptors
+  Test Description:
+  This test verifies the validity of the HS device and interface descriptors
+  returned as part of the enumeration sequence.
+  Verification is done according to the expected descriptors defined in
+  hs_expected_desc.h
+
+4.2.2 Test_hs_get_status_default_device
+  Test Suite: CompositeHSTests
+  Test Name: test_hs_get_status_default_device
+  Test Description:
+  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)
+
+4.2.3 Test_hs_get_status_default_interface
+  Test Suite: CompositeHSTests
+  Test Name: test_hs_get_status_default_interface
+  Test Description:
+  This function sends a GET_STATUS request to the hs interface in default state
+  (section 9.4.5 in the USB2 standard)
+
+4.2.4 Test_hs_get_status_default_endpoint
+  Test Suite: CompositeHSTests
+  Test Name: test_hs_get_status_default_endpoint
+  Test Description:
+  This function sends a GET_STATUS request to the hs endpoint in default state
+  (section 9.4.5 in the USB2 standard)
+
+4.2.5 Test_hs_set_feature_suspend_interface
+  Test Suite: CompositeHSTests
+  Test Name: test_hs_set_feature_suspend_interface
+  Test Description:
+  This function sends a SET_FEATURE request to the ss interface in default
+  state, to set the suspend functionality for remote wakeup.
+
+4.2.6 Test_hs_set_feature_halt_ep
+  Test Suite: CompositeHSTests
+  Test Name: test_hs_set_feature_halt_ep
+  Test Description:
+  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.
+
+
+4.3: COMPOSITE SS TESTS
+
+This test suite is applicable only for a SS device. The test in this suite
+verify chapter 9 modifications that were made/added by the USB 3.0 spec.
+
+4.3.1 Test_ss_descriptors
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_descriptors
+  Test Description:
+  This test verifies the validity of the HS device, interface and BOS
+  descriptors returned as part of the enumeration sequence.
+  Verification is done according to the expected descriptors defined in
+  ss_expected_desc.h
+
+4.3.2 Test_ss_get_status_default_device
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_get_status_default_device
+  Test Description:
+  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)
+  Verification of the GetStatus() request is done by the SetFeature()
+  (with bmRequestType = 0x80H) request sent prior to the GetStatus() request.
+
+4.3.3 Test_ss_get_status_default_interface
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_get_status_default_interface
+  Test Description:
+  This function sends a GET_STATUS request to the ss interface in default state
+  (section 9.4.5 in the USB3 standard)
+  Verification of the GetStatus() request is done by the SetFeature()
+  (with bmRequestType = 0x81H) request sent prior to the GetStatus() request.
+  Refer to Section 9.4.5 of the USB 3.0 spec for details on GetStatus request.
+
+4.3.4 Test_ss_get_status_default_ep
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_get_status_default_ep
+  Test Description:
+  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.
+  Verification of the GetStatus() request is done by the SetFeature()
+  (with bmRequestType = 0x81H) request sent prior to the GetStatus() request.
+  Refer to Section 9.4.5 of the USB 3.0 spec for details on GetStatus request.
+
+4.3.5 Test_ss_set_feature_u1_device
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_set_feature_u1_device
+  Test Description:
+  This function sends a SET_FEATURE request to the ss device in default state,
+  to set the U1 power level capability.
+  Verification that the SetFeature request was successful is done by GetStatus()
+  request with bmRequestType = 0x81H. Refer to Section 9.4.5 of the USB 3.0 spec
+  for details on GetStatus request.
+  Refer to section 9.4.9 and Table 9-6 of the USB 3.0 spec for more details on
+  the SetFeature request.
+
+4.3.6 Test_ss_set_feature_u2_device
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_set_feature_u2_device
+  Test Description:
+  This function sends a SET_FEATURE request to the ss device in default state,
+  to set the U2 power level capability.
+  Verification that the SetFeature request was successful is done by GetStatus()
+  request with bmRequestType = 0x81H. Refer to Section 9.4.5 of the USB 3.0
+  spec for details on GetStatus request.
+  Refer to section 9.4.9 and Table 9-6 of the USB 3.0 spec for more details on
+  the SetFeature request.
+
+4.3.7 Test_ss_set_feature_ltm_device
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_set_feature_u2_device
+  Test Description:
+  This function sends a SET_FEATURE request to the ss device in default state,
+  to set the LTM capability.
+  Verification that the SetFeature request was successful is done by GetStatus()
+  request with bmRequestType = 0x81H. Refer to Section 9.4.5 of the USB 3.0
+  spec for details on GetStatus request.
+  Refer to section 9.4.9 and Table 9-6 of the USB 3.0 spec for more details on
+  the SetFeature request.
+
+4.3.8 Test_ss_set_feature_halt_ep
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_set_feature_halt_ep
+  Test Description:
+  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.
+  Verification that the SetFeature request was successful is done by GetStatus()
+  request with bmRequestType = 0x81H. Refer to Section 9.4.5 of the USB 3.0
+  spec for details on GetStatus request.
+  Refer to section 9.4.9 and Table 9-6 of the USB 3.0 spec for more details on
+  the SetFeature request.
+
+4.3.9 Test_ss_set_feature_suspend_low_power_interface
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_set_feature_suspend_low_power_interface
+  Test Description:
+  This function sends a SET_FEATURE request to the ss interface in default
+  state, to set the suspend functionality for low power.
+  Verification that the SetFeature request was successful is done by GetStatus()
+  request with bmRequestType = 0x81H. Refer to Section 9.4.5 of the USB 3.0
+  spec for details on GetStatus request.
+  Refer to section 9.4.9 and Table 9-6 of the USB 3.0 spec for more details on
+  the SetFeature request.
+
+4.3.10 Test_ss_set_feature_suspend_remote_wakeup_interface
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_set_feature_suspend_remote_wakeup_interface
+  Test Description:
+  This function sends a SET_FEATURE request to the ss interface in default
+  state, to set the suspend functionality for remote wakeup.
+  Verification that the SetFeature request was successful is done by GetStatus()
+  request with bmRequestType = 0x81H. Refer to Section 9.4.5 of the USB 3.0
+  spec for details on GetStatus request.
+  Refer to section 9.4.9 and Table 9-6 of the USB 3.0 spec for more details on
+  the SetFeature request.
+
+
+4.4: SERIAL TESTS
+
+The tests in this test suite are general data transfer tests that are applicable
+to all devices (HS and SS) and test the data transfers in the Gadget framework,
+not in a specific FD. The test in this test suite should be performed on the
+g_zero module using f_sourcesink gadget.
+
+4.4.1 Test_single_bulk_in
+  Test Suite: SerialTests
+  Test Name: test_single_bulk_in
+  Test Description:
+  This test verifies a single BULK transfer on a BULK IN endpoint. Data transfer
+  size is an input parameter for the test.
+
+4.4.2 Test_single_bulk_out
+  Test Suite: SerialTests
+  Test Name: test_single_bulk_out
+  Test Description:
+  This test verifies a single BULK transfer on a BULK OUT endpoint. Data
+  transfer size is an input parameter for the test.
+
+
+4.5 STREAMS TESTS
+
+The tests in this test suite intended to test the streaming capability added by
+the SS USB  spec, thus they are applicable only to SS devices.
+
+4.5.1 Tests_streams_bulk_loopback
+  Test Suite: StreamsTests
+  Test Name: test_streams_bulk_loopback
+  Test Description:
+  This test initiates N bulk OUT transfers on N streams, and verifies reception
+  on bulk IN EP.
+
+
+4.6 UAS TESTS
+
+This tests are meant to run on a UAS supporting device. Their intention is to
+test various COMAND/TASK MANAGEMENT IUs handling as defined by the UAS spec.
+The COMMAND IUs include SCSI commands.
+Verification of all the test successful completion is done according to the
+SENCE IU received upon completion.
+The below tests are applicable to UAS device operating both in SS and in HS
+mode.
+
+4.6.1 exec_send_inquiry
+  Test Suite: UASTests
+  Test Name: exec_send_inquiry
+  Test Description:
+  This function sends the INQUIRY SCSI command (opCode = 0x12), encapsulated in
+  a COMMAND IU, to the device and verifies the correct reply from it.
+
+4.6.2 exec_send_request_sense
+  Test Suite: UASTests
+  Test Name: exec_send_request_sense
+  Test Description:
+  This function sends the REQUEST SENSE SCSI command (opCode = 0x03),
+  encapsulated in a COMMAND IU, to the device and verifies the correct reply
+  from it.
+
+4.6.3 exec_test_unit_ready
+  Test Suite: UASTests
+  Test Name: exec_test_unit_ready
+  Test Description:
+  This function sends the TEST UNIT READY SCSI command (opCode = 0x00),
+  encapsulated in a COMMAND IU, to the device and verifies the correct reply
+  from it.
+
+4.6.4 exec_send_read_capacity
+  Test Suite: UASTests
+  Test Name: exec_send_read_capacity
+  Test Description:
+  This function sends the READ CAPACITY SCSI command (opCode = 0x25),
+  encapsulated in a COMMAND IU, to the device and verifies the correct reply
+  from it.
+
+4.6.5 exec_send_mode_sense
+  Test Suite: UASTests
+  Test Name: exec_send_mode_sense
+  Test Description:
+  This function sends the MODE SENSE6 SCSI command (opCode = 0x01), encapsulated
+  in a COMMAND IU, to the device and verifies the correct reply from it.
+
+4.6.6 exec_send_mode_sense10
+  Test Suite: UASTests
+  Test Name: exec_send_mode_sense10
+  Test Description:
+  This function sends the MODE SENSE10 SCSI command (opCode = 0x5a),
+  encapsulated in a COMMAND IU, to the device and verifies the correct
+  completion of it.
+
+4.6.7 exec_send_prevent_allow_removal
+  Test Suite: UASTests
+  Test Name: exec_send_prevent_allow_removal
+  Test Description:
+  This function sends the ALLOW MEDIUM REMOVAL SCSI command (opCode = 0x1e),
+  encapsulated in a COMMAND IU, to the device and verifies the correct
+  completion of it.
+
+4.6.8 exec_test_read6
+  Test Suite: UASTests
+  Test Name: exec_test_read6
+  Test Description:
+  This function sends the READ6 SCSI command (opCode = 0x08), encapsulated in a
+  COMMAND IU, to the device and verifies the correct completion of it.
+  At the beginning of the test a verification buffer is written to the device.
+  The read data is compared to that buffer. Upon test completion the device data
+  file content is restored to its original state.
+
+4.6.9 exec_test_read10
+  Test Suite: UASTests
+  Test Name: exec_test_read10
+  Test Description:
+  This function sends the READ10 SCSI command (opCode = 0x28), encapsulated in
+  a COMMAND IU, to the device and verifies the correct completion of it.
+  At the beginning of the test a verification buffer is written to the device.
+  The read data is compared to that buffer. Upon test completion the device data
+  file content is restored to its original state.
+
+4.6.10 exec_test_read12
+  Test Suite: UASTests
+  Test Name: exec_test_read12
+  Test Description:
+  This function sends the READ12 SCSI command (opCode = 0xa8), encapsulated in
+  a COMMAND IU, to the device and verifies the correct completion of it.
+  At the beginning of the test a verification buffer is written to the device.
+  The read data is compared to that buffer. Upon test completion the device data
+  file content is restored to its original state.
+
+4.6.11 exec_test_write6
+  Test Suite: UASTests
+  Test Name: exec_test_write6
+  Test Description:
+  This function sends the WRITE6 SCSI command (opCode = 0x0a), encapsulated in
+  a COMMAND IU, to the device and verifies the correct completion of it.
+  Upon test completion the device data file content is restored to its original
+  state.
+  TODO: Add write verification
+
+4.6.12 exec_test_write10
+  Test Suite: UASTests
+  Test Name: exec_test_write10
+  Test Description:
+  This function sends the WRITE10 SCSI command (opCode = 0x2a), encapsulated in
+  a COMMAND IU, to the device and verifies the correct completion of it.
+  Upon test completion the device data file content is restored to its original
+  state.
+  TODO: Add write verification
+
+4.6.13 exec_test_write12
+  Test Suite: UASTests
+  Test Name: exec_test_write12
+  Test Description:
+  This function sends the WRITE12 SCSI command (opCode = 0xaa), encapsulated in
+  a COMMAND IU, to the device and verifies the correct completion of it.
+  Upon test completion the device data file content is restored to its original
+  state.
+  TODO: Add write verification
+
+4.6.14 exec_test_write_huge
+  Test Suite: UASTests
+  Test Name: exec_test_write_huge
+  Test Description:
+  This function sends the WRITE10 SCSI command (opCode = 0x2a), encapsulated in
+  a COMMAND IU, with a huge amount of data to write and verifies the correct
+  completion of it.
+  Upon test completion the device data file content is restored to its original
+  state.
+  TODO: Add write verification
+
+4.6.15 exec_test_read_format_capacities
+  Test Suite: UASTests
+  Test Name: exec_test_read_format_capacities
+  Test Description:
+  This function sends the READ FORMAT CAPACITIES SCSI command (opCode = 0x23),
+  encapsulated in a COMMAND IU and verifies the correct completion of it.
+
+4.6.16 exec_test_start_stop
+  Test Suite: UASTests
+  Test Name: exec_test_start_stop
+  Test Description:
+  This function sends the START STOP UNIT SCSI command (opCode = 0x1b),
+  encapsulated in a COMMAND IU and verifies the correct completion of it.
+  This test verifies several versions of the command:
+	a)(LoEj,Start) = 00 (stop motor)
+	b)(LoEj,Start) = 01 (start motor)
+	c)(LoEj,Start) = 10 (Eject media)
+  After the media is ejected the lun is closed. We need to re-open it manually
+  in order to be able to continue working with it. This is done by writing to
+  the file attribute the name of the file the module was loaded with.
+	d)(LoEj,Start) = 11 (LOAD media)
+
+4.6.17 exec_test_verify
+  Test Suite: UASTests
+  Test Name: exec_test_verify
+  Test Description:
+  This function sends the VERIFY SCSI command (opCode = 0x2f), encapsulated in
+  a COMMAND IU and verifies the correct completion of it.
+
+4.6.18 exec_test_synchronize_cache
+  Test Suite: UASTests
+  Test Name: exec_test_synchronize_cache
+  Test Description:
+  This function sends the SINCHRONIZE CACHE SCSI command (opCode = 0x35),
+  encapsulated in a COMMAND IU and verifies the correct completion of it.
+
+4.6.19 exec_test_tm_reset_lun
+  Test Suite: UASTests
+  Test Name: exec_test_tm_reset_lun
+  Test Description:
+  This function sends the LOGICAL UNIT RESET TASK MANAGEMENTcommand
+  (Code = 0x08), and verifies the correct completion of it according to the
+  RESPONSE IU.
+  At the beginning of the test 2 commands are issued to the device that should
+  be canceled by the RESET LUN TM.
+
+4.6.20 exec_test_tm_abort_task
+  Test Suite: UASTests
+  Test Name: exec_test_tm_abort_task
+  Test Description:
+  This function sends the ABORT TASK TASK MANAGEMENTcommand (Code = 0x01), and
+  verifies the correct completion of it according to the RESPONSE IU.
+  At the beginning of the test a command is issued to the device that should be
+  canceled by the ABORT TASK TM.
+
+4.6.21 exec_test_tm_abort_task_set
+  Test Suite: UASTests
+  Test Name: exec_test_tm_abort_task_set
+  Test Description:
+  This function sends the ABORT TASK SET TASK MANAGEMENTcommand (Code = 0x02),
+  and verifies the correct completion of it according to the RESPONSE IU.
+  At the beginning of the test 2 commands are issued to the device that should
+  be canceled by the ABORT TASK SET TM.
+
+4.6.22 exec_test_tm_reset_nexus
+  Test Suite: UASTests
+  Test Name: exec_test_tm_reset_nexus
+  Test Description:
+  This function sends the RESET NEXUS TASK MANAGEMENTcommand (Code = 0x10), and
+  verifies the correct completion of it according to the RESPONSE IU.
+  At the beginning of the test 2 commands are issued to the device that should
+  be canceled by the RESET NEXUS TM.
+
+4.6.23 exec_test_tm_query_async_ev
+  Test Suite: UASTests
+  Test Name: exec_test_tm_query_async_ev
+  Test Description:
+  This function sends the QUERY ASYNC EVENT TASK MANAGEMENTcommand
+  (Code = 0x82), and verifies the correct completion of it according to the
+  RESPONSE IU.
+
+4.6.24 exec_test_tm_query_task
+  Test Suite: UASTests
+  Test Name: exec_test_tm_query_task
+  Test Description:
+  This function sends the QUERY TASK TASK MANAGEMENTcommand (Code = 0x80), and
+  verifies the correct completion of it according to the RESPONSE IU.
+
+4.6.25 exec_test_tm_query_task_set
+  Test Suite: UASTests
+  Test Name: exec_test_tm_query_task_set
+  Test Description:
+  This function sends the QUERY TASK SET TASK MANAGEMENTcommand (Code = 0x81),
+  and verifies the correct completion of it according to the RESPONSE IU.
+
+4.6.26 exec_test_tm_overlapped_tag
+  Test Suite: UASTests
+  Test Name: exec_test_tm_overlapped_tag
+  Test Description:
+  This function verifies correct handling of tag overlapping. It issues 2
+  commands with the same tag id and verifies that both commands were handled
+  correctly, meaning aborted.
+  One of the commands issued is a COMMAND IU and the other is TM IU.
+
+4.6.27 exec_test_cmd_overlapped_tag
+  Test Suite: UASTests
+  Test Name: exec_test_cmd_overlapped_tag
+  Test Description:
+  This function verifies correct handling of tag overlapping. It issues 2
+  commands with the same tag id and verifies that both commands were handled
+  correctly, meaning aborted.
+  Both of the command issued are COMMAND IUs.
+
+--
+Created by a consultant of the Qualcomm Innovation Center, Inc.
+The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
\ No newline at end of file
diff --git a/tools/usb/unittests/Documentation/unittests-setup b/tools/usb/unittests/Documentation/unittests-setup
new file mode 100644
index 0000000..f336e3b
--- /dev/null
+++ b/tools/usb/unittests/Documentation/unittests-setup
@@ -0,0 +1,127 @@
+
+Questions can be refereed to tlinder@codeaurora.org.
+Copyright (C) 2011 Code Aurora Forum. All rights reserved
+
+USB device Unit test framework
+==============================
+
+Introduction
+-------------
+
+This document describes the SuperSpeed USB Unit tests including setup,
+environment and test cases.
+
+
+1: SETUP
+---------
+
+The Unit tests code consists of 4 parts:
+
+1. The usb-tests code that is part of the kernel usb code.
+2. Googletest code. Downloaded from the web.
+3. The user-space test code in this distribution
+4. libusb code that is part of the libusb git repository
+
+The Unit tests can be ran on any Linux machine with a device that has g_zero
+and dummy_hcd module loaded on it. If you wish to run the Unit tests on another
+device (one that doesn't support g_zero and dumm_hcd_ it's possible but not all
+of the bellow tests will pass. This is due to the fact that several proprietary
+control requests handling were implemented in the above modules in order to
+support some of the tests. For example: new control request handling was
+added to the dummy_hcd module to perform a connect/disconnect sequence.
+
+
+1.1: GETTING USB-TEST CODE FROM THE KERNEL REPOSITORY
+
+Get the kernel code from
+    git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
+The unit test kernel patches are released as part of kernel2.6.?? so you should
+work with this version of the kernel or later.
+
+Compiling the Kernel code:
+Export $KERNEL to point to the location of your kernel.
+mkdir out-32
+cd out-32
+make -C $KERNEL O=`pwd` ARCH=x86 defconfig
+
+Run the autoconfig.sh script to configure the kernel. Please refer to
+autoconfig_readme for details.
+
+Compilation:
+make -C $KERNEL O=`pwd` ARCH=x8
+
+
+1.2: LIBUSB CODE
+
+Get the libusb code from git://git.libusb.org/libusb.git
+The libusb related patches are merged into the libusb tree. (NOT YET!!!)
+
+1.2.1 Libusb Setup and compilation
+
+Install the following packages (from synaptic):
+a. autoconfig
+b.automake
+c. libtool
+
+Run: ./autogen.sh. –prefix=<output_folder>
+This script will generate the .config file and the Makefile
+
+Open the auto-generated Makefiles (there is one under libusb, one under
+libusb/libusb and another one under libusb/examples) and update the following:
+a)To CPPFLAGS add -m32 (CPPFLAGS = -m32)
+b)To CFLAGS add -m32 (CFLAGS = -g -O2 -m32)
+c)Change every x86_64 to i386
+
+run: make install
+The library and include files will be placed in . --prefix=<output_folder>
+
+
+1.3: GOOGLETEST CODE
+
+Download from
+http://code.google.com/p/googletest/downloads/list (gtest-1.5.0.tar.bz2) .
+Open the Makefile and add “-lpthread” to CXXFLAGS:
+CXXFLAGS += -g -Wall -Wextra -m32 -L/usr/lib32 -lstdc++ -L/usr/local/lib -lusb-1.0 -lpthread
+
+
+1.4 COMPILING USER SPACE TEST CODE (IN THIS PACKAGE)
+
+cd ../tools/usb/unittests/make/ (from your working area)
+
+Set the $KERNEL to your kernel source code, $GTEST to your Googletest directory
+and $LIBUSB to your libusb compilation output directory.
+
+make
+The make creates an executable called usb_tests
+
+
+1.5: VIRTUAL MACHINE
+
+If you wish to use the dummy_hcd module then it's best to run the Unit tests on
+a Virtual machine (VM).
+Debugging of the VM kernel is performed with insight.
+So you'll be required to install the following packages:
+1. qemu
+2. fuseext2
+3. insight
+
+Create gadjet.img. Refer to create-gadget-img for details.
+
+1.5.1 Initial setup of the VM:
+
+Copy usb_tests to the VM.
+Copy the libusb library files to the VM (from <output_folder>/lib)
+
+
+2: RUNNING THE UNIT TEST
+-----------------------
+
+On the VM (or other Linux host) do:
+export LD_LIBRARY_PATH=<libusb library files path on the VM>
+run the tests script: ./usb_tests with relevant input parameters. (Refer to
+unittests-info for additional information)
+
+--
+Created by a consultant of the Qualcomm Innovation Center, Inc.
+The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
+
diff --git a/tools/usb/unittests/libusb_patches/0001-Add-support-to-USB3-descriptors.patch b/tools/usb/unittests/libusb_patches/0001-Add-support-to-USB3-descriptors.patch
new file mode 100644
index 0000000..8c8aaf0
--- /dev/null
+++ b/tools/usb/unittests/libusb_patches/0001-Add-support-to-USB3-descriptors.patch
@@ -0,0 +1,420 @@
+From fcc8bb8ea6a326a2c84e92b29004e8e3896925b7 Mon Sep 17 00:00:00 2001
+From: Maya Erez <merez@codeaurora.org>
+Date: Sun, 13 Mar 2011 22:01:07 +0200
+Subject: [PATCH 1/4] Add support to USB3 descriptors
+
+Add definitions for Endpoint Companion and BOS descriptors.
+Add APIs for parsing the Endpoint Companion and BOS descriptors.
+
+Signed-off-by: Maya Erez <merez@codeaurora.org>
+
+---
+ libusb/descriptor.c |  160 +++++++++++++++++++++++++++++++++++++++++++++++---
+ libusb/libusb.h     |  115 ++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 264 insertions(+), 11 deletions(-)
+
+diff --git a/libusb/descriptor.c b/libusb/descriptor.c
+index 11480e8..0ce6975 100644
+--- a/libusb/descriptor.c
++++ b/libusb/descriptor.c
+@@ -22,6 +22,7 @@
+ #include <stdint.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <stdio.h>
+ 
+ #include "libusbi.h"
+ 
+@@ -45,6 +46,7 @@ int usbi_parse_descriptor(unsigned char *source, const char *descriptor,
+ 	unsigned char *sp = source, *dp = dest;
+ 	uint16_t w;
+ 	const char *cp;
++	uint32_t d;
+ 
+ 	for (cp = descriptor; *cp; cp++) {
+ 		switch (*cp) {
+@@ -63,6 +65,21 @@ int usbi_parse_descriptor(unsigned char *source, const char *descriptor,
+ 				sp += 2;
+ 				dp += 2;
+ 				break;
++			/* 32-bit word, convert from little endian to CPU */
++			case 'd':
++			/* Align to word boundary */
++				dp += ((unsigned long)dp & 1);
++
++				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;
+ 		}
+ 	}
+ 
+@@ -75,6 +92,39 @@ static void clear_endpoint(struct libusb_endpoint_descriptor *endpoint)
+ 		free((unsigned char *) endpoint->extra);
+ }
+ 
++static int parse_endpoint_comp(struct libusb_context *ctx,
++			       struct libusb_ss_ep_comp_descriptor *ep_comp,
++			       unsigned char *buffer, int size)
++{
++	struct usb_descriptor_header header;
++	int parsed = 0;
++
++	usbi_parse_descriptor(buffer, "bb", &header, 0);
++
++	/* Everything should be fine being passed into here, but we sanity */
++	/*  check JIC */
++	if (header.bLength > size) {
++		usbi_err(ctx, "ran out of descriptors parsing");
++		return LIBUSB_ERROR_NO_MEM;
++	}
++
++	if (header.bDescriptorType != LIBUSB_DT_SS_ENDPOINT_COMP) {
++		usbi_err(ctx, "unexpected descriptor %x (expected %x)",
++			header.bDescriptorType, LIBUSB_DT_SS_ENDPOINT_COMP);
++		return parsed;
++	}
++
++	if (header.bLength >= LIBUSB_DT_SS_EP_COMP_SIZE)
++		usbi_parse_descriptor(buffer, "bbbbw", ep_comp, 0);
++
++	buffer += header.bLength;
++	size -= header.bLength;
++	parsed += header.bLength;
++
++	return parsed;
++}
++
++
+ static int parse_endpoint(struct libusb_context *ctx,
+ 	struct libusb_endpoint_descriptor *endpoint, unsigned char *buffer,
+ 	int size, int host_endian)
+@@ -83,7 +133,7 @@ static int parse_endpoint(struct libusb_context *ctx,
+ 	unsigned char *extra;
+ 	unsigned char *begin;
+ 	int parsed = 0;
+-	int len;
++	int len, retval;
+ 
+ 	usbi_parse_descriptor(buffer, "bb", &header, 0);
+ 
+@@ -109,6 +159,28 @@ static int parse_endpoint(struct libusb_context *ctx,
+ 	size -= header.bLength;
+ 	parsed += header.bLength;
+ 
++	/* check if we have a Comapnion descriptor */
++	usbi_parse_descriptor(buffer, "bb", &header, 0);
++	if (header.bDescriptorType == LIBUSB_DT_SS_ENDPOINT_COMP) {
++		endpoint->ep_comp = (struct libusb_ss_ep_comp_descriptor *)
++			malloc(sizeof(struct libusb_ss_ep_comp_descriptor));
++		if (!endpoint->ep_comp) {
++			usbi_err(ctx, "couldn't allocate memory for ep_comp");
++			return LIBUSB_ERROR_NO_MEM;
++		}
++
++		memset(endpoint->ep_comp, 0,
++		       sizeof(struct libusb_ss_ep_comp_descriptor));
++		retval = parse_endpoint_comp(ctx, endpoint->ep_comp,
++					     buffer, size);
++		if (retval < 0)
++			return retval;
++
++		buffer += retval;
++		parsed += retval;
++		size -= retval;
++	}
++
+ 	/* Skip over the rest of the Class Specific or Vendor Specific */
+ 	/*  descriptors */
+ 	begin = buffer;
+@@ -122,9 +194,10 @@ static int parse_endpoint(struct libusb_context *ctx,
+ 
+ 		/* If we find another "proper" descriptor then we're done  */
+ 		if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
+-				(header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
+-				(header.bDescriptorType == LIBUSB_DT_CONFIG) ||
+-				(header.bDescriptorType == LIBUSB_DT_DEVICE))
++		    (header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
++		    (header.bDescriptorType == LIBUSB_DT_CONFIG) ||
++		    (header.bDescriptorType == LIBUSB_DT_DEVICE) ||
++		    (header.bDescriptorType == LIBUSB_DT_SS_ENDPOINT_COMP))
+ 			break;
+ 
+ 		usbi_dbg("skipping descriptor %x", header.bDescriptorType);
+@@ -233,9 +306,11 @@ static int parse_interface(libusb_context *ctx,
+ 
+ 			/* If we find another "proper" descriptor then we're done */
+ 			if ((header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
+-					(header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
+-					(header.bDescriptorType == LIBUSB_DT_CONFIG) ||
+-					(header.bDescriptorType == LIBUSB_DT_DEVICE))
++			    (header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
++			    (header.bDescriptorType == LIBUSB_DT_CONFIG) ||
++			    (header.bDescriptorType == LIBUSB_DT_DEVICE) ||
++			    (header.bDescriptorType ==
++			     LIBUSB_DT_SS_ENDPOINT_COMP))
+ 				break;
+ 
+ 			buffer += header.bLength;
+@@ -379,9 +454,11 @@ static int parse_configuration(struct libusb_context *ctx,
+ 
+ 			/* If we find another "proper" descriptor then we're done */
+ 			if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
+-					(header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
+-					(header.bDescriptorType == LIBUSB_DT_CONFIG) ||
+-					(header.bDescriptorType == LIBUSB_DT_DEVICE))
++			    (header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
++			    (header.bDescriptorType == LIBUSB_DT_CONFIG) ||
++			    (header.bDescriptorType == LIBUSB_DT_DEVICE) ||
++			    (header.bDescriptorType ==
++			     LIBUSB_DT_SS_ENDPOINT_COMP))
+ 				break;
+ 
+ 			usbi_dbg("skipping descriptor 0x%x\n", header.bDescriptorType);
+@@ -726,3 +803,66 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev,
+ 	return di;
+ }
+ 
++
++/** \ingroup desc
++ * Get the USB bos descriptor for a given device.
++ *
++ * \param dev the device
++ * \param bos output bos descriptor
++ * \returns 0 on success
++ */
++API_EXPORTED int libusb_parse_bos_desc(struct libusb_device *dev,
++					struct libusb_bos_descriptor *bos,
++					unsigned char *buf)
++{
++	int i;
++	int desc_begin = 0;
++
++	usbi_parse_descriptor(buf, "bbwb", bos, 0);
++	desc_begin = LIBUSB_DT_BOS_SIZE;
++
++	/* Get the device capability descriptors */
++	for (i = 0; i < bos->bNumDeviceCaps; ++i) {
++		if (buf[desc_begin+2] == LIBUSB_USB_CAP_TYPE_EXT) {
++			if (!bos->usb_ext_cap) {
++				bos->usb_ext_cap =
++				(struct libusb_usb_ext_cap_descriptor *)
++				malloc(sizeof(struct
++					      libusb_usb_ext_cap_descriptor));
++				usbi_parse_descriptor(buf+desc_begin, "bbbd",
++						      bos->usb_ext_cap, 0);
++			} else
++				usbi_warn(dev->ctx,
++					  "usb_ext_cap was already allocated");
++
++			/* move to the next device capability descriptor */
++			desc_begin += LIBUSB_DT_USB_CAP_TYPE_EXT_SIZE;
++		} else if (buf[desc_begin+2] == LIBUSB_SS_USB_CAP_TYPE) {
++			if (!bos->ss_usb_cap) {
++				bos->ss_usb_cap =
++				(struct libusb_ss_usb_cap_descriptor *)
++				malloc(sizeof(struct
++					      libusb_ss_usb_cap_descriptor));
++
++				usbi_parse_descriptor(buf+desc_begin,
++						      "bbbbwbbw",
++						      bos->ss_usb_cap, 0);
++			} else
++				usbi_warn(dev->ctx,
++					  "ss_usb_cap was already allocated");
++
++			/* move to the next device capability descriptor */
++			desc_begin += LIBUSB_DT_SS_USB_CAP_TYPE_SIZE;
++		} else {
++			usbi_info(dev->ctx,
++				  "wireless/container_id capability "
++				  "descriptor");
++
++			/* move to the next device capability descriptor */
++			desc_begin += buf[desc_begin];
++		}
++	}
++	return 0;
++}
++
++
+diff --git a/libusb/libusb.h b/libusb/libusb.h
+index 8dc3362..9f2243a 100644
+--- a/libusb/libusb.h
++++ b/libusb/libusb.h
+@@ -191,7 +191,16 @@ enum libusb_descriptor_type {
+ 	LIBUSB_DT_PHYSICAL = 0x23,
+ 
+ 	/** Hub descriptor */
+-	LIBUSB_DT_HUB = 0x29
++	LIBUSB_DT_HUB = 0x29,
++
++	/** BOS descriptor */
++	LIBUSB_DT_BOS = 0x0f,
++
++	/** Device Capability descriptor */
++	LIBUSB_DT_DEVICE_CAPABILITY = 0x10,
++
++	/** SuperSpeed Endpoint Companion descriptor */
++	LIBUSB_DT_SS_ENDPOINT_COMP = 0x30
+ };
+ 
+ /* Descriptor sizes per descriptor type */
+@@ -201,6 +210,13 @@ enum libusb_descriptor_type {
+ #define LIBUSB_DT_ENDPOINT_SIZE		7
+ #define LIBUSB_DT_ENDPOINT_AUDIO_SIZE	9	/* Audio extension */
+ #define LIBUSB_DT_HUB_NONVAR_SIZE		7
++#define LIBUSB_DT_SS_EP_COMP_SIZE		6
++#define LIBUSB_DT_BOS_SIZE			5
++#define LIBUSB_DT_USB_CAP_TYPE_EXT_SIZE	7
++#define LIBUSB_DT_SS_USB_CAP_TYPE_SIZE	10
++#define LIBUSB_DT_BOS_MAX_SIZE		((LIBUSB_DT_BOS_SIZE) + \
++					(LIBUSB_DT_USB_CAP_TYPE_EXT_SIZE) + \
++					(LIBUSB_DT_SS_USB_CAP_TYPE_SIZE))
+ 
+ #define LIBUSB_ENDPOINT_ADDRESS_MASK	0x0f    /* in bEndpointAddress */
+ #define LIBUSB_ENDPOINT_DIR_MASK		0x80
+@@ -407,6 +423,33 @@ struct libusb_device_descriptor {
+ 	uint8_t  bNumConfigurations;
+ };
+ 
++/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */
++struct libusb_ss_ep_comp_descriptor {
++
++	/** Size of this descriptor (in bytes) */
++	u_int8_t  bLength;
++
++	/** Descriptor type. Will have value
++	 * \ref libusb_descriptor_type::LIBUSB_DT_SS_ENDPOINT_COMP in
++	 * this context. */
++	u_int8_t  bDescriptorType;
++
++
++	/** The maximum number of packets the endpoint can send or
++	 *  recieve as part of a burst. */
++	u_int8_t  bMaxBurst;
++
++	/** In bulk EP:	bits 4:0 represents the	maximum	number of
++	 *  streams the	EP supports. In	isochronous EP:	bits 1:0
++	 *  represents the Mult	- a zero based value that determines
++	 *  the	maximum	number of packets within a service interval  */
++	u_int8_t  bmAttributes;
++
++	/** The	total number of bytes this EP will transfer every
++	 *  service interval. valid only for periodic EPs. */
++	u_int16_t wBytesPerInterval;
++};
++
+ /** \ingroup desc
+  * A structure representing the standard USB endpoint descriptor. This
+  * descriptor is documented in section 9.6.3 of the USB 2.0 specification.
+@@ -449,6 +492,9 @@ struct libusb_endpoint_descriptor {
+ 	/** For audio devices only: the address if the synch endpoint */
+ 	uint8_t  bSynchAddress;
+ 
++	/** The	EP companion descriptor */
++	struct libusb_ss_ep_comp_descriptor *ep_comp;
++
+ 	/** Extra descriptors. If libusb encounters unknown endpoint descriptors,
+ 	 * it will store them here, should you wish to parse them. */
+ 	const unsigned char *extra;
+@@ -457,6 +503,7 @@ struct libusb_endpoint_descriptor {
+ 	int extra_length;
+ };
+ 
++
+ /** \ingroup desc
+  * A structure representing the standard USB interface descriptor. This
+  * descriptor is documented in section 9.6.5 of the USB 2.0 specification.
+@@ -565,6 +612,60 @@ struct libusb_config_descriptor {
+ 	int extra_length;
+ };
+ 
++/** \ingroup desc
++ * A structure representing the BOS descriptor. This
++ * descriptor is documented in section 9.6.2 of the USB 3.0
++ * specification. All multiple-byte fields are represented in
++ * host-endian format.
++ */
++struct libusb_bos_descriptor {
++	u_int8_t  bLength;
++	u_int8_t  bDescriptorType;
++	u_int16_t wTotalLength;
++	u_int8_t  bNumDeviceCaps;
++
++	struct libusb_usb_ext_cap_descriptor *usb_ext_cap;
++	struct libusb_ss_usb_cap_descriptor *ss_usb_cap;
++};
++
++
++struct libusb_dev_cap_header {
++	u_int8_t  bLength;
++	u_int8_t  bDescriptorType;
++	u_int8_t  bDevCapabilityType;
++};
++
++
++#define	LIBUSB_USB_CAP_TYPE_EXT		2
++
++struct libusb_usb_ext_cap_descriptor {		/* Link Power Management */
++	u_int8_t  bLength;
++	u_int8_t  bDescriptorType;
++	u_int8_t  bDevCapabilityType;
++	u_int32_t  bmAttributes;
++#define LIBUSB_LPM_SUPPORT		(1 << 1)	/* supports LPM */
++};
++
++
++#define	LIBUSB_SS_USB_CAP_TYPE		3
++
++struct libusb_ss_usb_cap_descriptor {		/* Link Power Management */
++	u_int8_t  bLength;
++	u_int8_t  bDescriptorType;
++	u_int8_t  bDevCapabilityType;
++	u_int8_t  bmAttributes;
++#define LIBUSB_LPM_SUPPORT		(1 << 1)	/* supports LPM */
++	u_int16_t wSpeedSupported;
++#define LIBUSB_LOW_SPEED_OPERATION	(1)	/* Low speed operation */
++#define LIBUSB_FULL_SPEED_OPERATION	(1 << 1)/* Full speed operation */
++#define LIBUSB_HIGH_SPEED_OPERATION	(1 << 2)/* High speed operation */
++#define LIBUSB_5GBPS_OPERATION		(1 << 3)/* Operation at 5Gbps */
++	u_int8_t  bFunctionalitySupport;
++	u_int8_t  bU1devExitLat;
++	u_int16_t bU2DevExitLat;
++};
++
++
+ /** \ingroup asyncio
+  * Setup packet for control transfers. */
+ struct libusb_control_setup {
+@@ -1315,6 +1416,18 @@ void LIBUSB_CALL libusb_set_pollfd_notifiers(libusb_context *ctx,
+ 	libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb,
+ 	void *user_data);
+ 
++
++/** \ingroup desc
++ * Get the USB bos descriptor for a given device.
++ *
++ * \param dev the device
++ * \param bos output bos descriptor
++ * \returns 0 on success
++ */
++int libusb_parse_bos_desc(struct libusb_device *dev,
++			   struct libusb_bos_descriptor *bos,
++			   unsigned char *buf);
++
+ #ifdef __cplusplus
+ }
+ #endif
+-- 
+1.7.3.3
+
+--
+Sent by an employee of the Qualcomm Innovation Center, Inc.
+The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
\ No newline at end of file
diff --git a/tools/usb/unittests/libusb_patches/0002-Add-support-for-libusb_get_device_speed.patch b/tools/usb/unittests/libusb_patches/0002-Add-support-for-libusb_get_device_speed.patch
new file mode 100644
index 0000000..ca612bb
--- /dev/null
+++ b/tools/usb/unittests/libusb_patches/0002-Add-support-for-libusb_get_device_speed.patch
@@ -0,0 +1,172 @@
+From c5df8c1d47367d214c40bf932244f8b44f1f4caf Mon Sep 17 00:00:00 2001
+From: Tatyana Brokhman <tlinder@codeaurora.org>
+Date: Mon, 14 Mar 2011 16:18:26 +0200
+Subject: [PATCH 2/4] Add support for libusb_get_device_speed()
+
+This patch adds a new libusb function used to determine the connected USB
+device speed.
+
+Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>
+
+---
+ libusb/core.c           |   17 ++++++++++++++
+ libusb/libusb.h         |   11 +++++++++
+ libusb/libusbi.h        |    7 ++++++
+ libusb/os/linux_usbfs.c |   56 +++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 91 insertions(+), 0 deletions(-)
+
+diff --git a/libusb/core.c b/libusb/core.c
+index 64445ab..6d49fb3 100644
+--- a/libusb/core.c
++++ b/libusb/core.c
+@@ -745,6 +745,23 @@ int API_EXPORTED libusb_get_max_packet_size(libusb_device *dev,
+ }
+ 
+ /** \ingroup dev
++ * Convenience function to retrieve the speed of the connected
++ * device
++ *
++ * \param dev a device
++ * \returns the connected device speed
++ * \returns LIBUSB_ERROR_NOT_SUPPORTED if get_device_speed() cb
++ *  	    was not defined for the usbi_backend
++ * \returns LIBUSB_ERROR_OTHER on other failure
++ */
++API_EXPORTED int libusb_get_dev_speed(libusb_device *dev)
++{
++	if (usbi_backend->get_device_speed)
++		return usbi_backend->get_device_speed(dev);
++	return LIBUSB_ERROR_NOT_SUPPORTED;
++}
++
++/** \ingroup dev
+  * Calculate the maximum packet size which a specific endpoint is capable is
+  * sending or receiving in the duration of 1 microframe
+  *
+diff --git a/libusb/libusb.h b/libusb/libusb.h
+index 9f2243a..346f85f 100644
+--- a/libusb/libusb.h
++++ b/libusb/libusb.h
+@@ -89,6 +89,16 @@
+ extern "C" {
+ #endif
+ 
++/* USB 2.0 defines three speeds, here's how Linux identifies them */
++enum libusb_device_speed {
++	LIBUSB_SPEED_UNKNOWN = 0,			/* enumerating */
++	LIBUSB_SPEED_LOW, LIBUSB_SPEED_FULL,		/* usb 1.1 */
++	LIBUSB_SPEED_HIGH,				/* usb 2.0 */
++	LIBUSB_SPEED_VARIABLE,			/* wireless (usb 2.5) */
++	LIBUSB_SPEED_SUPER,			/* usb 3.0 */
++};
++
++
+ /** \def libusb_cpu_to_le16
+  * \ingroup misc
+  * Convert a 16-bit value from host-endian to little-endian format. On
+@@ -965,6 +975,7 @@ int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev,
+ 	unsigned char endpoint);
+ int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev,
+ 	unsigned char endpoint);
++int LIBUSB_CALL libusb_get_dev_speed(libusb_device *dev);
+ 
+ int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **handle);
+ void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle);
+diff --git a/libusb/libusbi.h b/libusb/libusbi.h
+index 974b108..87cd770 100644
+--- a/libusb/libusbi.h
++++ b/libusb/libusbi.h
+@@ -591,6 +591,13 @@ struct usbi_os_backend {
+ 		uint8_t config_index, unsigned char *buffer, size_t len,
+ 		int *host_endian);
+ 
++
++	/* Get the connected device speed
++	 *
++	 * Return 0 on success or a LIBUSB_ERROR_OTHER code on failure.
++	 */
++	int (*get_device_speed)(struct libusb_device *device);
++
+ 	/* Get the bConfigurationValue for the active configuration for a device.
+ 	 * Optional. This should only be implemented if you can retrieve it from
+ 	 * cache (don't generate I/O).
+diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
+index 867893c..430d773 100644
+--- a/libusb/os/linux_usbfs.c
++++ b/libusb/os/linux_usbfs.c
+@@ -333,6 +333,61 @@ static int sysfs_get_device_descriptor(struct libusb_device *dev,
+ 	return 0;
+ }
+ 
++static int sysfs_get_device_speed(struct libusb_device *dev)
++{
++	int fd;
++	ssize_t r;
++	unsigned char buffer[32];
++	char *tmp;
++
++	fd = __open_sysfs_attr(dev, "speed");
++	if (fd < 0)
++		return fd;
++
++	r = read(fd, &buffer, 32);
++	close(fd);
++	if (r < 0) {
++		usbi_err(DEVICE_CTX(dev), "read failed, ret=%d errno=%d", fd, errno);
++		return LIBUSB_ERROR_OTHER;
++	}
++
++	/*
++	 * The read string from sysfs terminates with a "new line" char
++	 * (A in ascii code) which we want to trim
++	 */
++	tmp = strchr(buffer,  10);
++	*tmp=0;
++
++	/* 
++	 * The spped is dumped in sysfs.c as follows:
++	 * case USB_SPEED_LOW: speed = "1.5";
++	 * case USB_SPEED_UNKNOWN/USB_SPEED_FULL: speed = "12";
++	 * case USB_SPEED_HIGH/USB_SPEED_WIRELESS:	speed = "480";
++	 * case USB_SPEED_SUPER: speed = "5000";
++	 */
++
++	if (!strcmp("1.5",buffer))
++		return LIBUSB_SPEED_LOW;
++
++	if (!strcmp("12",buffer))
++		return LIBUSB_SPEED_FULL;
++
++	if (!strcmp("480",buffer))
++		return LIBUSB_SPEED_HIGH;
++
++	if (!strcmp("5000",buffer))
++		return LIBUSB_SPEED_SUPER;
++
++	return LIBUSB_SPEED_UNKNOWN;
++}
++
++static int op_get_dev_speed(struct libusb_device *dev)
++{
++	if (sysfs_has_descriptors)
++		return sysfs_get_device_speed(dev);
++	return LIBUSB_SPEED_UNKNOWN;
++}
++
+ static int op_get_device_descriptor(struct libusb_device *dev,
+ 	unsigned char *buffer, int *host_endian)
+ {
+@@ -2210,6 +2265,7 @@ const struct usbi_os_backend linux_usbfs_backend = {
+ 	.get_device_descriptor = op_get_device_descriptor,
+ 	.get_active_config_descriptor = op_get_active_config_descriptor,
+ 	.get_config_descriptor = op_get_config_descriptor,
++	.get_device_speed = op_get_dev_speed,
+ 
+ 	.open = op_open,
+ 	.close = op_close,
+-- 
+1.7.3.3
+
+--
+Sent by an employee of the Qualcomm Innovation Center, Inc.
+The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
\ No newline at end of file
diff --git a/tools/usb/unittests/libusb_patches/0003-Add-UAS-defines.patch b/tools/usb/unittests/libusb_patches/0003-Add-UAS-defines.patch
new file mode 100644
index 0000000..a1abfd2
--- /dev/null
+++ b/tools/usb/unittests/libusb_patches/0003-Add-UAS-defines.patch
@@ -0,0 +1,56 @@
+From 45864135c176df8bf03bff05733acd8c8ec0579e Mon Sep 17 00:00:00 2001
+From: Tatyana Brokhman <tlinder@codeaurora.org>
+Date: Tue, 14 Jun 2011 13:25:37 +0300
+Subject: [PATCH 3/4] Add UAS defines
+
+This patch adds necessary definitions as defined by the UAS spec
+
+Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>
+
+---
+ libusb/libusb.h |   19 ++++++++++++++++++-
+ 1 files changed, 18 insertions(+), 1 deletions(-)
+
+diff --git a/libusb/libusb.h b/libusb/libusb.h
+index 346f85f..c5e2fbb 100644
+--- a/libusb/libusb.h
++++ b/libusb/libusb.h
+@@ -210,7 +210,12 @@ enum libusb_descriptor_type {
+ 	LIBUSB_DT_DEVICE_CAPABILITY = 0x10,
+ 
+ 	/** SuperSpeed Endpoint Companion descriptor */
+-	LIBUSB_DT_SS_ENDPOINT_COMP = 0x30
++	LIBUSB_DT_SS_ENDPOINT_COMP = 0x30,
++
++	/** UASP descriptors:   */
++	/** Pipe usage descriptor   */
++	LIBUSB_DT_PIPE_USAGE = 0x24
++
+ };
+ 
+ /* Descriptor sizes per descriptor type */
+@@ -675,6 +680,18 @@ struct libusb_ss_usb_cap_descriptor {		/* Link Power Management */
+ 	u_int16_t bU2DevExitLat;
+ };
+ 
++/* LIBUSB_DT_PIPE_USAGE descriptor */
++struct libusb_uasp_pipe_usage_desc {
++    u_int8_t  bLength;
++    u_int8_t  bDescriptorType;
++#define PIPE_ID_UNDEF       0x00
++#define PIPE_ID_CMD         0x01
++#define PIPE_ID_STS         0x02
++#define PIPE_ID_DATA_IN     0x03
++#define PIPE_ID_DATA_OUT    0x04
++    u_int8_t  bPipeID;
++    u_int8_t  reserved;
++};
+ 
+ /** \ingroup asyncio
+  * Setup packet for control transfers. */
+-- 
+1.7.3.3
+
+--
+Sent by an employee of the Qualcomm Innovation Center, Inc.
+The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
\ No newline at end of file
diff --git a/tools/usb/unittests/libusb_patches/0004-libusb-Add-stream-support-to-LIBUSB.patch b/tools/usb/unittests/libusb_patches/0004-libusb-Add-stream-support-to-LIBUSB.patch
new file mode 100644
index 0000000..a7059be
--- /dev/null
+++ b/tools/usb/unittests/libusb_patches/0004-libusb-Add-stream-support-to-LIBUSB.patch
@@ -0,0 +1,314 @@
+From 436bfafeefaa7f71252578b66394735f5d2da0c6 Mon Sep 17 00:00:00 2001
+From: Tatyana Brokhman <tlinder@codeaurora.org>
+Date: Sun, 12 Jun 2011 15:05:32 +0300
+Subject: [PATCH 4/4] libusb: Add stream support to LIBUSB
+
+1. Add stream ID to bulk transfer API
+2. Add stream alloc/free APIs
+
+Signed-off-by: Amit Blay <ablay@qualcomm.com>
+
+---
+ libusb/core.c           |   38 ++++++++++++++++++++++++++++++++++++++
+ libusb/libusb.h         |   13 +++++++++++++
+ libusb/libusbi.h        |   30 +++++++++++++++++++++++++++++-
+ libusb/os/linux_usbfs.c |   43 +++++++++++++++++++++++++++++++++++++++++++
+ libusb/os/linux_usbfs.h |    3 +++
+ libusb/sync.c           |   42 +++++++++++++++++++++++++++++++++++++++---
+ 6 files changed, 165 insertions(+), 4 deletions(-)
+
+diff --git a/libusb/core.c b/libusb/core.c
+index 6d49fb3..b8bd11c 100644
+--- a/libusb/core.c
++++ b/libusb/core.c
+@@ -1298,6 +1298,44 @@ out:
+ }
+ 
+ /** \ingroup dev
++ * Allocate streams for an EP.
++ *
++ * This is a blocking function.
++ *
++ * \param dev a device handle
++ * \param ep_map the endpoints to allocate streams for
++ * \returns 0 on success
++ * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist
++ * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
++ * \returns another LIBUSB_ERROR code on other failure
++ */
++API_EXPORTED int libusb_alloc_streams(libusb_device_handle *dev,
++	unsigned int ep_map)
++{
++	usbi_dbg("endpoint %x", ep_map);
++	return usbi_backend->alloc_streams(dev, ep_map);
++}
++
++/** \ingroup dev
++ * Free streams for an EP.
++ *
++ * This is a blocking function.
++ *
++ * \param dev a device handle
++ * \param endpoint the endpoint to free streams for
++ * \returns 0 on success
++ * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist
++ * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
++ * \returns another LIBUSB_ERROR code on other failure
++ */
++API_EXPORTED int libusb_free_streams(libusb_device_handle *dev,
++	unsigned int ep_map)
++{
++	usbi_dbg("endpoint %x", ep_map);
++	return usbi_backend->free_streams(dev, ep_map);
++}
++
++/** \ingroup dev
+  * Activate an alternate setting for an interface. The interface must have
+  * been previously claimed with libusb_claim_interface().
+  *
+diff --git a/libusb/libusb.h b/libusb/libusb.h
+index c5e2fbb..1c70139 100644
+--- a/libusb/libusb.h
++++ b/libusb/libusb.h
+@@ -952,6 +952,10 @@ struct libusb_transfer {
+ 	 * endpoints. */
+ 	int num_iso_packets;
+ 
++	/** Stream ID for the endpoint where the transfer will be
++	 *  sent. */
++	unsigned int stream_id;
++
+ 	/** Isochronous packet descriptors, for isochronous transfers only. */
+ 	struct libusb_iso_packet_descriptor iso_packet_desc
+ #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+@@ -1004,6 +1008,11 @@ int LIBUSB_CALL libusb_claim_interface(libusb_device_handle *dev,
+ 	int interface_number);
+ int LIBUSB_CALL libusb_release_interface(libusb_device_handle *dev,
+ 	int interface_number);
++int LIBUSB_CALL libusb_alloc_streams(libusb_device_handle *dev,
++	unsigned int ep_map);
++int LIBUSB_CALL libusb_free_streams(libusb_device_handle *dev,
++	unsigned int ep_map);
++
+ 
+ libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid(
+ 	libusb_context *ctx, uint16_t vendor_id, uint16_t product_id);
+@@ -1331,6 +1340,10 @@ int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev_handle,
+ 	unsigned char endpoint, unsigned char *data, int length,
+ 	int *actual_length, unsigned int timeout);
+ 
++int LIBUSB_CALL libusb_bulk_transfer_ex(libusb_device_handle *dev_handle,
++	unsigned char endpoint, unsigned char *data, int length,
++	int *actual_length, unsigned int timeout, unsigned int stream_id);
++
+ int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle,
+ 	unsigned char endpoint, unsigned char *data, int length,
+ 	int *actual_length, unsigned int timeout);
+diff --git a/libusb/libusbi.h b/libusb/libusbi.h
+index 87cd770..59c5e59 100644
+--- a/libusb/libusbi.h
++++ b/libusb/libusbi.h
+@@ -687,7 +687,35 @@ struct usbi_os_backend {
+ 	int (*set_interface_altsetting)(struct libusb_device_handle *handle,
+ 		int interface_number, int altsetting);
+ 
+-	/* Clear a halt/stall condition on an endpoint.
++	/* Allcoate streams for en EP.
++	 *
++	 * It's OK for this function to block.
++	 *
++	 * Return:
++	 * - 0 on success
++	 * - LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist
++	 * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it
++	 *   was opened
++	 * - another LIBUSB_ERROR code on other failure
++	 */
++	int (*alloc_streams)(struct libusb_device_handle *handle,
++		unsigned int ep_map);
++
++	/* Free allocated streams for en EP.
++	 *
++	 * It's OK for this function to block.
++	 *
++	 * Return:
++	 * - 0 on success
++	 * - LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist
++	 * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it
++	 *   was opened
++	 * - another LIBUSB_ERROR code on other failure
++	 */
++	int (*free_streams)(struct libusb_device_handle *handle,
++		unsigned int ep_map);
++
++    /* Clear a halt/stall condition on an endpoint.
+ 	 *
+ 	 * It's OK for this function to block.
+ 	 *
+diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
+index 430d773..ce62220 100644
+--- a/libusb/os/linux_usbfs.c
++++ b/libusb/os/linux_usbfs.c
+@@ -1215,6 +1215,46 @@ static int op_claim_interface(struct libusb_device_handle *handle, int iface)
+ 	return 0;
+ }
+ 
++static int op_alloc_streams(struct libusb_device_handle *handle,
++	unsigned int ep_map)
++{
++	int fd = __device_handle_priv(handle)->fd;
++	unsigned int _ep_map = ep_map;
++	int r = ioctl(fd, IOCTL_USBFS_ALLOC_STREAMS, &_ep_map);
++	if (r) {
++		if (errno == ENOENT)
++			return LIBUSB_ERROR_NOT_FOUND;
++		else if (errno == ENODEV)
++			return LIBUSB_ERROR_NO_DEVICE;
++
++		usbi_err(HANDLE_CTX(handle),
++			"alloc_streams failed error %d errno %d", r, errno);
++		return LIBUSB_ERROR_OTHER;
++	}
++
++	return 0;
++}
++
++static int op_free_streams(struct libusb_device_handle *handle,
++	unsigned int ep_map)
++{
++	int fd = __device_handle_priv(handle)->fd;
++	unsigned int _ep_map = ep_map;
++	int r = ioctl(fd, IOCTL_USBFS_FREE_STREAMS, &_ep_map);
++	if (r) {
++		if (errno == ENOENT)
++			return LIBUSB_ERROR_NOT_FOUND;
++		else if (errno == ENODEV)
++			return LIBUSB_ERROR_NO_DEVICE;
++
++		usbi_err(HANDLE_CTX(handle),
++			"free_streams failed error %d errno %d", r, errno);
++		return LIBUSB_ERROR_OTHER;
++	}
++
++	return 0;
++}
++
+ static int op_release_interface(struct libusb_device_handle *handle, int iface)
+ {
+ 	int fd = __device_handle_priv(handle)->fd;
+@@ -1450,6 +1490,7 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer,
+ 		urb->type = urb_type;
+ 		urb->endpoint = transfer->endpoint;
+ 		urb->buffer = transfer->buffer + (i * MAX_BULK_BUFFER_LENGTH);
++		urb->stream_id = transfer->stream_id;
+ 		if (supports_flag_bulk_continuation && !is_out)
+ 			urb->flags = USBFS_URB_SHORT_NOT_OK;
+ 		if (i == num_urbs - 1 && last_urb_partial)
+@@ -2273,6 +2314,8 @@ const struct usbi_os_backend linux_usbfs_backend = {
+ 	.set_configuration = op_set_configuration,
+ 	.claim_interface = op_claim_interface,
+ 	.release_interface = op_release_interface,
++	.alloc_streams = op_alloc_streams,
++	.free_streams = op_free_streams,
+ 
+ 	.set_interface_altsetting = op_set_interface,
+ 	.clear_halt = op_clear_halt,
+diff --git a/libusb/os/linux_usbfs.h b/libusb/os/linux_usbfs.h
+index bd02edc..9d5d4ca 100644
+--- a/libusb/os/linux_usbfs.h
++++ b/libusb/os/linux_usbfs.h
+@@ -96,6 +96,7 @@ struct usbfs_urb {
+ 	unsigned int signr;
+ 	void *usercontext;
+ 	struct usbfs_iso_packet_desc iso_frame_desc[0];
++	unsigned int stream_id;
+ };
+ 
+ struct usbfs_connectinfo {
+@@ -134,5 +135,7 @@ struct usbfs_hub_portinfo {
+ #define IOCTL_USBFS_CLEAR_HALT	_IOR('U', 21, unsigned int)
+ #define IOCTL_USBFS_DISCONNECT	_IO('U', 22)
+ #define IOCTL_USBFS_CONNECT	_IO('U', 23)
++#define IOCTL_USBFS_ALLOC_STREAMS	_IOR('U', 26, unsigned int)
++#define IOCTL_USBFS_FREE_STREAMS	_IOR('U', 27, unsigned int)
+ 
+ #endif
+diff --git a/libusb/sync.c b/libusb/sync.c
+index 3870f95..f4a6dc3 100644
+--- a/libusb/sync.c
++++ b/libusb/sync.c
+@@ -152,7 +152,8 @@ static void LIBUSB_CALL bulk_transfer_cb(struct libusb_transfer *transfer)
+ 
+ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle,
+ 	unsigned char endpoint, unsigned char *buffer, int length,
+-	int *transferred, unsigned int timeout, unsigned char type)
++	int *transferred, unsigned int timeout, unsigned char type,
++	unsigned int stream_id)
+ {
+ 	struct libusb_transfer *transfer = libusb_alloc_transfer(0);
+ 	int completed = 0;
+@@ -164,6 +165,7 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle,
+ 	libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length,
+ 		bulk_transfer_cb, &completed, timeout);
+ 	transfer->type = type;
++	transfer->stream_id = stream_id;
+ 
+ 	r = libusb_submit_transfer(transfer);
+ 	if (r < 0) {
+@@ -257,7 +259,41 @@ int API_EXPORTED libusb_bulk_transfer(struct libusb_device_handle *dev_handle,
+ 	unsigned int timeout)
+ {
+ 	return do_sync_bulk_transfer(dev_handle, endpoint, data, length,
+-		transferred, timeout, LIBUSB_TRANSFER_TYPE_BULK);
++		transferred, timeout, LIBUSB_TRANSFER_TYPE_BULK, 0);
++}
++
++/** \ingroup syncio
++ * Perform a USB bulk transfer with extended paramter list,
++ * which includes USB3 stream ID.
++ *
++ * \param dev_handle a handle for the device to communicate with
++ * \param endpoint the address of a valid endpoint to communicate with
++ * \param data a suitably-sized data buffer for either input or output
++ * (depending on endpoint)
++ * \param length for bulk writes, the number of bytes from data to be sent. for
++ * bulk reads, the maximum number of bytes to receive into the data buffer.
++ * \param transferred output location for the number of bytes actually
++ * transferred.
++ * \param timeout timeout (in millseconds) that this function should wait
++ * before giving up due to no response being received. For an unlimited
++ * timeout, use value 0.
++ *
++ * \returns 0 on success (and populates <tt>transferred</tt>)
++ * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out (and populates
++ * <tt>transferred</tt>)
++ * \returns LIBUSB_ERROR_PIPE if the endpoint halted
++ * \returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see
++ * \ref packetoverflow
++ * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
++ * \returns another LIBUSB_ERROR code on other failures
++ */
++API_EXPORTED int libusb_bulk_transfer_ex(
++	struct libusb_device_handle *dev_handle, unsigned char endpoint,
++	unsigned char *data, int length, int *transferred, unsigned int timeout,
++	unsigned int stream_id)
++{
++	return do_sync_bulk_transfer(dev_handle, endpoint, data, length,
++		transferred, timeout, LIBUSB_TRANSFER_TYPE_BULK, stream_id);
+ }
+ 
+ /** \ingroup syncio
+@@ -306,6 +342,6 @@ int API_EXPORTED libusb_interrupt_transfer(
+ 	unsigned char *data, int length, int *transferred, unsigned int timeout)
+ {
+ 	return do_sync_bulk_transfer(dev_handle, endpoint, data, length,
+-		transferred, timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT);
++		transferred, timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT, 0);
+ }
+ 
+-- 
+1.7.3.3
+
+--
+Sent by an employee of the Qualcomm Innovation Center, Inc.
+The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
\ No newline at end of file
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..599416b
--- /dev/null
+++ b/tools/usb/unittests/usb/composite_tests.cc
@@ -0,0 +1,1645 @@
+/*
+ * 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 or dummy_hcd).
+ * @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
+ *	 0x52 - start connect/disconnect sequence
+ * @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) and dummy_hcd modules
+ */
+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;
+	}
+
+	wValue = 0;
+	ret = soursesink_test_setup(udev, dev, CONN_DISCONN_TEST, wValue);
+
+	/*
+	 * 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..550e0cb
--- /dev/null
+++ b/tools/usb/unittests/usb/composite_tests.h
@@ -0,0 +1,293 @@
+/*
+ * 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"
+
+
+/**
+ * soursesink_test_setup() - Send a control request to setup/begin a spesific
+ * test (to be handled by f_soursesink or dummy_hcd).
+ * @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
+ *	 0x52 - start connect/disconnect sequence
+ * @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) and dummy_hcd modules
+ */
+int soursesink_test_setup(struct libusb_device_handle *udev,
+			  libusb_device *dev,
+			  uint8_t request,
+			  uint16_t wValue);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * test_hs_set_feature_suspend_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 hs interface in default
+ * state, to set the suspend capability
+ */
+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.3.3

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH/RFC 1/5] usb:tools: usb unittests framework
@ 2011-06-16 13:31 ` Tatyana Brokhman
  0 siblings, 0 replies; 54+ messages in thread
From: Tatyana Brokhman @ 2011-06-16 13:31 UTC (permalink / raw)
  To: greg; +Cc: linux-usb, linux-arm-msm, balbi, ablay, Tatyana Brokhman, open list

This patch introduces a user-space framework for developing unit tests in
order to test the USB functionality of a connected device.
These tests communicate with the USB device via libusb interface.
They are meant to run with the g_zero and dummy_hcd module since several
proprietary control messages were added to those modules. But a smaller
subset of the tests can be run on any USB device and on real UDCs.

Implemented tests:
1. Test device descriptors - this test is applicable both for HS and SS
   devices
2. Test the SET_FEATURE requests
3. Test bulk in
4. Test bulk out
5. Test connect/disconnect
6. Streams capability testing
7. UAS test suite

This patch also includes patches that should be applied to libusb.
Some of them were already sent upstream for approval but not yet accepted.
Other will be sent in the near future.

For more info please read the files under Documentation.

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

---
 .../usb/unittests/Documentation/autoconfig_readme  |   20 +
 .../usb/unittests/Documentation/create-gadget-img  |   47 +
 tools/usb/unittests/Documentation/unittests-info   |  526 +++++
 tools/usb/unittests/Documentation/unittests-setup  |  127 ++
 .../0001-Add-support-to-USB3-descriptors.patch     |  420 ++++
 ...2-Add-support-for-libusb_get_device_speed.patch |  172 ++
 .../libusb_patches/0003-Add-UAS-defines.patch      |   56 +
 .../0004-libusb-Add-stream-support-to-LIBUSB.patch |  314 +++
 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         | 1645 +++++++++++++++
 tools/usb/unittests/usb/composite_tests.h          |  293 +++
 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 +
 29 files changed, 10377 insertions(+), 0 deletions(-)
 create mode 100644 tools/usb/unittests/Documentation/autoconfig_readme
 create mode 100644 tools/usb/unittests/Documentation/create-gadget-img
 create mode 100644 tools/usb/unittests/Documentation/unittests-info
 create mode 100644 tools/usb/unittests/Documentation/unittests-setup
 create mode 100644 tools/usb/unittests/libusb_patches/0001-Add-support-to-USB3-descriptors.patch
 create mode 100644 tools/usb/unittests/libusb_patches/0002-Add-support-for-libusb_get_device_speed.patch
 create mode 100644 tools/usb/unittests/libusb_patches/0003-Add-UAS-defines.patch
 create mode 100644 tools/usb/unittests/libusb_patches/0004-libusb-Add-stream-support-to-LIBUSB.patch
 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/Documentation/autoconfig_readme b/tools/usb/unittests/Documentation/autoconfig_readme
new file mode 100644
index 0000000..07112e1
--- /dev/null
+++ b/tools/usb/unittests/Documentation/autoconfig_readme
@@ -0,0 +1,20 @@
+
+Questions can be refereed to tlinder@codeaurora.org.
+Copyright (C) 2011 Code Aurora Forum. All rights reserved
+
+Description
+-----------
+This script is used to automatically configure the kernel .config file
+(instead of using menuconfig).
+This script should be ran after using defconfig.
+
+Please note that the script modifies the .config file under out-32 (and
+should be executed in the out-32 directory).
+
+The script activates the dummy_HCD controller and configures the gadget
+to operate in  a SS mode.
+
+--
+Created by a consultant of the Qualcomm Innovation Center, Inc.
+The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
+
diff --git a/tools/usb/unittests/Documentation/create-gadget-img b/tools/usb/unittests/Documentation/create-gadget-img
new file mode 100644
index 0000000..edb34a7
--- /dev/null
+++ b/tools/usb/unittests/Documentation/create-gadget-img
@@ -0,0 +1,47 @@
+
+Questions can be refereed to tlinder@codeaurora.org.
+Copyright (C) 2011 Code Aurora Forum. All rights reserved
+
+
+This is how disk is built:
+-------------------------
+VM points to the location of the Virtual Machine
+
+cd $VM
+mkdir rootfs
+# create unformatted image
+qemu-img create -f raw gadget.img 600M
+# format it with ext2
+mkfs.ext2 -F gadget.img
+# mount
+fuseext2 gadget.img rootfs -o rw+
+# populate disk with basic Linux installation
+debootstrap --arch=i386 karmic rootfs
+
+#prepare image for real life
+echo "proc            /proc           proc    defaults        0       0" >> rootfs/etc/fstab
+echo "/dev/sda        /               ext2    defaults        0       0" >> rootfs/etc/fstab
+
+echo "user    ALL=(ALL) ALL" >> rootfs/etc/sudoers
+
+echo "auto lo" >> rootfs/etc/network/interfaces
+echo "iface lo inet loopback" >> rootfs/etc/network/interfaces
+echo "auto eth0" >> rootfs/etc/network/interfaces
+echo "iface eth0 inet dhcp" >> rootfs/etc/network/interfaces
+
+#unmount it
+fusermount -u rootfs
+
+Boot in a single mode (use -append "root=/dev/sda single"); in the VM, execute:
+
+useradd user
+passwd -d user
+echo "root:root00" | chpasswd
+apt-get --yes install openssh-server
+halt
+
+NOTE: instructions are incomplete
+
+--
+Created by a consultant of the Qualcomm Innovation Center, Inc.
+The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
\ No newline at end of file
diff --git a/tools/usb/unittests/Documentation/unittests-info b/tools/usb/unittests/Documentation/unittests-info
new file mode 100644
index 0000000..163b270
--- /dev/null
+++ b/tools/usb/unittests/Documentation/unittests-info
@@ -0,0 +1,526 @@
+
+Questions can be refereed to tlinder@codeaurora.org.
+Copyright (C) 2011 Code Aurora Forum. All rights reserved
+
+1: INPUT PARAMETERS
+-------------------
+
+Usb_test receives the following input parameters:
+1.int busnum - the bus number of the USB device to run the tests on
+2.int devnum - the device number of the USB device to run the tests on
+3.int productid - the product id of the USB device to run the tests on
+4.int vendorid - the vendor id of the USB device to run the tests on
+The above data can be retrieved by running lsusb command on the VM/Linux host
+the USB device is connected to.
+Note: You should provide either busnum and devnum or productid and vendorid
+as an input.
+5.int num_expected_strms_in_ep - the number of expected streams for IN EP's
+  ep_comp desc
+6.int num_expected_strms_out_ep - the number of expected streams for OUT EP's
+  ep_comp desc
+7.int intr_num - the number of the interface to run the test on
+8.int devel - set this flag to 1 if you wish to run in development mode.
+  (Refer to section 3 for more details)
+9.int uasp_dev - set this flag to 1 if running the test on a UAS Gadget driver
+10.int debug - this flag indicates if debug information will be printed or not.
+  The default is that no debug info will be printed (debug = 0). You can change
+  that by setting debug = 1 (optional)
+11.int streams_dev - Setting this flag to 1 will result in running only streams
+  tests
+12.char gadget_sysfs_path[MAX_STRING_LEN] - Gadget sysfs path. The default is:
+  "/sys/devices/platform/dummy_udc/gadget/"
+
+Example:
+./usb_tests --busnum=2 --devnum=3 --debug=1
+
+
+2: RUNNING A SUBSET OF THE TESTS (ACCORDING TO DEVICE SPEED)
+------------------------------------------------------------
+
+On Unittests initialization the speed of the connected device is read and the
+appropriate test suite is excluded from the tests to run. Meaning if it's a
+HS/SS device CompositeSSTests/ CompositeHSTests won't be run.
+Beside this exception GoogleTest will run all the test suites.
+
+
+3. RUNNING IN DEVELOPMENT MODE
+------------------------------
+
+It's possible to choose a test to run. In order to do so run the test in
+development mode, meaning
+	./usb_tests --busnum=2 --devnum=3 -devel=1
+This will open a list of test for you to choose which test to run.
+At the moment this option is developed for UAS tests only but other tests can be
+easily added to this menu.
+
+4: IMPLEMENTED TESTS
+--------------
+
+4.1: DUMMY TESTS
+
+4.1.1 test_connect_disconnect
+  Test Suite: DummyTests
+  Test Name: test_connect_disconnect
+  Test Description:
+  This test verifies the connect&disconnect sequence.
+  Verification is done by testing the correct enumeration descriptors were sent
+  (according to speed).
+
+
+4.2: COMPOSITE HS TESTS
+
+This test suite is applicable only for a HS device. The test in this suite
+verify chapter 9 requests that are applicable only to HS device.
+For example: HS descriptors.
+
+4.2.1 Test_hs_descriptors
+  Test Suite: CompositeHSTests
+  Test Name: test_hs_descriptors
+  Test Description:
+  This test verifies the validity of the HS device and interface descriptors
+  returned as part of the enumeration sequence.
+  Verification is done according to the expected descriptors defined in
+  hs_expected_desc.h
+
+4.2.2 Test_hs_get_status_default_device
+  Test Suite: CompositeHSTests
+  Test Name: test_hs_get_status_default_device
+  Test Description:
+  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)
+
+4.2.3 Test_hs_get_status_default_interface
+  Test Suite: CompositeHSTests
+  Test Name: test_hs_get_status_default_interface
+  Test Description:
+  This function sends a GET_STATUS request to the hs interface in default state
+  (section 9.4.5 in the USB2 standard)
+
+4.2.4 Test_hs_get_status_default_endpoint
+  Test Suite: CompositeHSTests
+  Test Name: test_hs_get_status_default_endpoint
+  Test Description:
+  This function sends a GET_STATUS request to the hs endpoint in default state
+  (section 9.4.5 in the USB2 standard)
+
+4.2.5 Test_hs_set_feature_suspend_interface
+  Test Suite: CompositeHSTests
+  Test Name: test_hs_set_feature_suspend_interface
+  Test Description:
+  This function sends a SET_FEATURE request to the ss interface in default
+  state, to set the suspend functionality for remote wakeup.
+
+4.2.6 Test_hs_set_feature_halt_ep
+  Test Suite: CompositeHSTests
+  Test Name: test_hs_set_feature_halt_ep
+  Test Description:
+  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.
+
+
+4.3: COMPOSITE SS TESTS
+
+This test suite is applicable only for a SS device. The test in this suite
+verify chapter 9 modifications that were made/added by the USB 3.0 spec.
+
+4.3.1 Test_ss_descriptors
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_descriptors
+  Test Description:
+  This test verifies the validity of the HS device, interface and BOS
+  descriptors returned as part of the enumeration sequence.
+  Verification is done according to the expected descriptors defined in
+  ss_expected_desc.h
+
+4.3.2 Test_ss_get_status_default_device
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_get_status_default_device
+  Test Description:
+  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)
+  Verification of the GetStatus() request is done by the SetFeature()
+  (with bmRequestType = 0x80H) request sent prior to the GetStatus() request.
+
+4.3.3 Test_ss_get_status_default_interface
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_get_status_default_interface
+  Test Description:
+  This function sends a GET_STATUS request to the ss interface in default state
+  (section 9.4.5 in the USB3 standard)
+  Verification of the GetStatus() request is done by the SetFeature()
+  (with bmRequestType = 0x81H) request sent prior to the GetStatus() request.
+  Refer to Section 9.4.5 of the USB 3.0 spec for details on GetStatus request.
+
+4.3.4 Test_ss_get_status_default_ep
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_get_status_default_ep
+  Test Description:
+  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.
+  Verification of the GetStatus() request is done by the SetFeature()
+  (with bmRequestType = 0x81H) request sent prior to the GetStatus() request.
+  Refer to Section 9.4.5 of the USB 3.0 spec for details on GetStatus request.
+
+4.3.5 Test_ss_set_feature_u1_device
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_set_feature_u1_device
+  Test Description:
+  This function sends a SET_FEATURE request to the ss device in default state,
+  to set the U1 power level capability.
+  Verification that the SetFeature request was successful is done by GetStatus()
+  request with bmRequestType = 0x81H. Refer to Section 9.4.5 of the USB 3.0 spec
+  for details on GetStatus request.
+  Refer to section 9.4.9 and Table 9-6 of the USB 3.0 spec for more details on
+  the SetFeature request.
+
+4.3.6 Test_ss_set_feature_u2_device
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_set_feature_u2_device
+  Test Description:
+  This function sends a SET_FEATURE request to the ss device in default state,
+  to set the U2 power level capability.
+  Verification that the SetFeature request was successful is done by GetStatus()
+  request with bmRequestType = 0x81H. Refer to Section 9.4.5 of the USB 3.0
+  spec for details on GetStatus request.
+  Refer to section 9.4.9 and Table 9-6 of the USB 3.0 spec for more details on
+  the SetFeature request.
+
+4.3.7 Test_ss_set_feature_ltm_device
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_set_feature_u2_device
+  Test Description:
+  This function sends a SET_FEATURE request to the ss device in default state,
+  to set the LTM capability.
+  Verification that the SetFeature request was successful is done by GetStatus()
+  request with bmRequestType = 0x81H. Refer to Section 9.4.5 of the USB 3.0
+  spec for details on GetStatus request.
+  Refer to section 9.4.9 and Table 9-6 of the USB 3.0 spec for more details on
+  the SetFeature request.
+
+4.3.8 Test_ss_set_feature_halt_ep
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_set_feature_halt_ep
+  Test Description:
+  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.
+  Verification that the SetFeature request was successful is done by GetStatus()
+  request with bmRequestType = 0x81H. Refer to Section 9.4.5 of the USB 3.0
+  spec for details on GetStatus request.
+  Refer to section 9.4.9 and Table 9-6 of the USB 3.0 spec for more details on
+  the SetFeature request.
+
+4.3.9 Test_ss_set_feature_suspend_low_power_interface
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_set_feature_suspend_low_power_interface
+  Test Description:
+  This function sends a SET_FEATURE request to the ss interface in default
+  state, to set the suspend functionality for low power.
+  Verification that the SetFeature request was successful is done by GetStatus()
+  request with bmRequestType = 0x81H. Refer to Section 9.4.5 of the USB 3.0
+  spec for details on GetStatus request.
+  Refer to section 9.4.9 and Table 9-6 of the USB 3.0 spec for more details on
+  the SetFeature request.
+
+4.3.10 Test_ss_set_feature_suspend_remote_wakeup_interface
+  Test Suite: CompositeSSTests
+  Test Name: test_ss_set_feature_suspend_remote_wakeup_interface
+  Test Description:
+  This function sends a SET_FEATURE request to the ss interface in default
+  state, to set the suspend functionality for remote wakeup.
+  Verification that the SetFeature request was successful is done by GetStatus()
+  request with bmRequestType = 0x81H. Refer to Section 9.4.5 of the USB 3.0
+  spec for details on GetStatus request.
+  Refer to section 9.4.9 and Table 9-6 of the USB 3.0 spec for more details on
+  the SetFeature request.
+
+
+4.4: SERIAL TESTS
+
+The tests in this test suite are general data transfer tests that are applicable
+to all devices (HS and SS) and test the data transfers in the Gadget framework,
+not in a specific FD. The test in this test suite should be performed on the
+g_zero module using f_sourcesink gadget.
+
+4.4.1 Test_single_bulk_in
+  Test Suite: SerialTests
+  Test Name: test_single_bulk_in
+  Test Description:
+  This test verifies a single BULK transfer on a BULK IN endpoint. Data transfer
+  size is an input parameter for the test.
+
+4.4.2 Test_single_bulk_out
+  Test Suite: SerialTests
+  Test Name: test_single_bulk_out
+  Test Description:
+  This test verifies a single BULK transfer on a BULK OUT endpoint. Data
+  transfer size is an input parameter for the test.
+
+
+4.5 STREAMS TESTS
+
+The tests in this test suite intended to test the streaming capability added by
+the SS USB  spec, thus they are applicable only to SS devices.
+
+4.5.1 Tests_streams_bulk_loopback
+  Test Suite: StreamsTests
+  Test Name: test_streams_bulk_loopback
+  Test Description:
+  This test initiates N bulk OUT transfers on N streams, and verifies reception
+  on bulk IN EP.
+
+
+4.6 UAS TESTS
+
+This tests are meant to run on a UAS supporting device. Their intention is to
+test various COMAND/TASK MANAGEMENT IUs handling as defined by the UAS spec.
+The COMMAND IUs include SCSI commands.
+Verification of all the test successful completion is done according to the
+SENCE IU received upon completion.
+The below tests are applicable to UAS device operating both in SS and in HS
+mode.
+
+4.6.1 exec_send_inquiry
+  Test Suite: UASTests
+  Test Name: exec_send_inquiry
+  Test Description:
+  This function sends the INQUIRY SCSI command (opCode = 0x12), encapsulated in
+  a COMMAND IU, to the device and verifies the correct reply from it.
+
+4.6.2 exec_send_request_sense
+  Test Suite: UASTests
+  Test Name: exec_send_request_sense
+  Test Description:
+  This function sends the REQUEST SENSE SCSI command (opCode = 0x03),
+  encapsulated in a COMMAND IU, to the device and verifies the correct reply
+  from it.
+
+4.6.3 exec_test_unit_ready
+  Test Suite: UASTests
+  Test Name: exec_test_unit_ready
+  Test Description:
+  This function sends the TEST UNIT READY SCSI command (opCode = 0x00),
+  encapsulated in a COMMAND IU, to the device and verifies the correct reply
+  from it.
+
+4.6.4 exec_send_read_capacity
+  Test Suite: UASTests
+  Test Name: exec_send_read_capacity
+  Test Description:
+  This function sends the READ CAPACITY SCSI command (opCode = 0x25),
+  encapsulated in a COMMAND IU, to the device and verifies the correct reply
+  from it.
+
+4.6.5 exec_send_mode_sense
+  Test Suite: UASTests
+  Test Name: exec_send_mode_sense
+  Test Description:
+  This function sends the MODE SENSE6 SCSI command (opCode = 0x01), encapsulated
+  in a COMMAND IU, to the device and verifies the correct reply from it.
+
+4.6.6 exec_send_mode_sense10
+  Test Suite: UASTests
+  Test Name: exec_send_mode_sense10
+  Test Description:
+  This function sends the MODE SENSE10 SCSI command (opCode = 0x5a),
+  encapsulated in a COMMAND IU, to the device and verifies the correct
+  completion of it.
+
+4.6.7 exec_send_prevent_allow_removal
+  Test Suite: UASTests
+  Test Name: exec_send_prevent_allow_removal
+  Test Description:
+  This function sends the ALLOW MEDIUM REMOVAL SCSI command (opCode = 0x1e),
+  encapsulated in a COMMAND IU, to the device and verifies the correct
+  completion of it.
+
+4.6.8 exec_test_read6
+  Test Suite: UASTests
+  Test Name: exec_test_read6
+  Test Description:
+  This function sends the READ6 SCSI command (opCode = 0x08), encapsulated in a
+  COMMAND IU, to the device and verifies the correct completion of it.
+  At the beginning of the test a verification buffer is written to the device.
+  The read data is compared to that buffer. Upon test completion the device data
+  file content is restored to its original state.
+
+4.6.9 exec_test_read10
+  Test Suite: UASTests
+  Test Name: exec_test_read10
+  Test Description:
+  This function sends the READ10 SCSI command (opCode = 0x28), encapsulated in
+  a COMMAND IU, to the device and verifies the correct completion of it.
+  At the beginning of the test a verification buffer is written to the device.
+  The read data is compared to that buffer. Upon test completion the device data
+  file content is restored to its original state.
+
+4.6.10 exec_test_read12
+  Test Suite: UASTests
+  Test Name: exec_test_read12
+  Test Description:
+  This function sends the READ12 SCSI command (opCode = 0xa8), encapsulated in
+  a COMMAND IU, to the device and verifies the correct completion of it.
+  At the beginning of the test a verification buffer is written to the device.
+  The read data is compared to that buffer. Upon test completion the device data
+  file content is restored to its original state.
+
+4.6.11 exec_test_write6
+  Test Suite: UASTests
+  Test Name: exec_test_write6
+  Test Description:
+  This function sends the WRITE6 SCSI command (opCode = 0x0a), encapsulated in
+  a COMMAND IU, to the device and verifies the correct completion of it.
+  Upon test completion the device data file content is restored to its original
+  state.
+  TODO: Add write verification
+
+4.6.12 exec_test_write10
+  Test Suite: UASTests
+  Test Name: exec_test_write10
+  Test Description:
+  This function sends the WRITE10 SCSI command (opCode = 0x2a), encapsulated in
+  a COMMAND IU, to the device and verifies the correct completion of it.
+  Upon test completion the device data file content is restored to its original
+  state.
+  TODO: Add write verification
+
+4.6.13 exec_test_write12
+  Test Suite: UASTests
+  Test Name: exec_test_write12
+  Test Description:
+  This function sends the WRITE12 SCSI command (opCode = 0xaa), encapsulated in
+  a COMMAND IU, to the device and verifies the correct completion of it.
+  Upon test completion the device data file content is restored to its original
+  state.
+  TODO: Add write verification
+
+4.6.14 exec_test_write_huge
+  Test Suite: UASTests
+  Test Name: exec_test_write_huge
+  Test Description:
+  This function sends the WRITE10 SCSI command (opCode = 0x2a), encapsulated in
+  a COMMAND IU, with a huge amount of data to write and verifies the correct
+  completion of it.
+  Upon test completion the device data file content is restored to its original
+  state.
+  TODO: Add write verification
+
+4.6.15 exec_test_read_format_capacities
+  Test Suite: UASTests
+  Test Name: exec_test_read_format_capacities
+  Test Description:
+  This function sends the READ FORMAT CAPACITIES SCSI command (opCode = 0x23),
+  encapsulated in a COMMAND IU and verifies the correct completion of it.
+
+4.6.16 exec_test_start_stop
+  Test Suite: UASTests
+  Test Name: exec_test_start_stop
+  Test Description:
+  This function sends the START STOP UNIT SCSI command (opCode = 0x1b),
+  encapsulated in a COMMAND IU and verifies the correct completion of it.
+  This test verifies several versions of the command:
+	a)(LoEj,Start) = 00 (stop motor)
+	b)(LoEj,Start) = 01 (start motor)
+	c)(LoEj,Start) = 10 (Eject media)
+  After the media is ejected the lun is closed. We need to re-open it manually
+  in order to be able to continue working with it. This is done by writing to
+  the file attribute the name of the file the module was loaded with.
+	d)(LoEj,Start) = 11 (LOAD media)
+
+4.6.17 exec_test_verify
+  Test Suite: UASTests
+  Test Name: exec_test_verify
+  Test Description:
+  This function sends the VERIFY SCSI command (opCode = 0x2f), encapsulated in
+  a COMMAND IU and verifies the correct completion of it.
+
+4.6.18 exec_test_synchronize_cache
+  Test Suite: UASTests
+  Test Name: exec_test_synchronize_cache
+  Test Description:
+  This function sends the SINCHRONIZE CACHE SCSI command (opCode = 0x35),
+  encapsulated in a COMMAND IU and verifies the correct completion of it.
+
+4.6.19 exec_test_tm_reset_lun
+  Test Suite: UASTests
+  Test Name: exec_test_tm_reset_lun
+  Test Description:
+  This function sends the LOGICAL UNIT RESET TASK MANAGEMENTcommand
+  (Code = 0x08), and verifies the correct completion of it according to the
+  RESPONSE IU.
+  At the beginning of the test 2 commands are issued to the device that should
+  be canceled by the RESET LUN TM.
+
+4.6.20 exec_test_tm_abort_task
+  Test Suite: UASTests
+  Test Name: exec_test_tm_abort_task
+  Test Description:
+  This function sends the ABORT TASK TASK MANAGEMENTcommand (Code = 0x01), and
+  verifies the correct completion of it according to the RESPONSE IU.
+  At the beginning of the test a command is issued to the device that should be
+  canceled by the ABORT TASK TM.
+
+4.6.21 exec_test_tm_abort_task_set
+  Test Suite: UASTests
+  Test Name: exec_test_tm_abort_task_set
+  Test Description:
+  This function sends the ABORT TASK SET TASK MANAGEMENTcommand (Code = 0x02),
+  and verifies the correct completion of it according to the RESPONSE IU.
+  At the beginning of the test 2 commands are issued to the device that should
+  be canceled by the ABORT TASK SET TM.
+
+4.6.22 exec_test_tm_reset_nexus
+  Test Suite: UASTests
+  Test Name: exec_test_tm_reset_nexus
+  Test Description:
+  This function sends the RESET NEXUS TASK MANAGEMENTcommand (Code = 0x10), and
+  verifies the correct completion of it according to the RESPONSE IU.
+  At the beginning of the test 2 commands are issued to the device that should
+  be canceled by the RESET NEXUS TM.
+
+4.6.23 exec_test_tm_query_async_ev
+  Test Suite: UASTests
+  Test Name: exec_test_tm_query_async_ev
+  Test Description:
+  This function sends the QUERY ASYNC EVENT TASK MANAGEMENTcommand
+  (Code = 0x82), and verifies the correct completion of it according to the
+  RESPONSE IU.
+
+4.6.24 exec_test_tm_query_task
+  Test Suite: UASTests
+  Test Name: exec_test_tm_query_task
+  Test Description:
+  This function sends the QUERY TASK TASK MANAGEMENTcommand (Code = 0x80), and
+  verifies the correct completion of it according to the RESPONSE IU.
+
+4.6.25 exec_test_tm_query_task_set
+  Test Suite: UASTests
+  Test Name: exec_test_tm_query_task_set
+  Test Description:
+  This function sends the QUERY TASK SET TASK MANAGEMENTcommand (Code = 0x81),
+  and verifies the correct completion of it according to the RESPONSE IU.
+
+4.6.26 exec_test_tm_overlapped_tag
+  Test Suite: UASTests
+  Test Name: exec_test_tm_overlapped_tag
+  Test Description:
+  This function verifies correct handling of tag overlapping. It issues 2
+  commands with the same tag id and verifies that both commands were handled
+  correctly, meaning aborted.
+  One of the commands issued is a COMMAND IU and the other is TM IU.
+
+4.6.27 exec_test_cmd_overlapped_tag
+  Test Suite: UASTests
+  Test Name: exec_test_cmd_overlapped_tag
+  Test Description:
+  This function verifies correct handling of tag overlapping. It issues 2
+  commands with the same tag id and verifies that both commands were handled
+  correctly, meaning aborted.
+  Both of the command issued are COMMAND IUs.
+
+--
+Created by a consultant of the Qualcomm Innovation Center, Inc.
+The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
\ No newline at end of file
diff --git a/tools/usb/unittests/Documentation/unittests-setup b/tools/usb/unittests/Documentation/unittests-setup
new file mode 100644
index 0000000..f336e3b
--- /dev/null
+++ b/tools/usb/unittests/Documentation/unittests-setup
@@ -0,0 +1,127 @@
+
+Questions can be refereed to tlinder@codeaurora.org.
+Copyright (C) 2011 Code Aurora Forum. All rights reserved
+
+USB device Unit test framework
+==============================
+
+Introduction
+-------------
+
+This document describes the SuperSpeed USB Unit tests including setup,
+environment and test cases.
+
+
+1: SETUP
+---------
+
+The Unit tests code consists of 4 parts:
+
+1. The usb-tests code that is part of the kernel usb code.
+2. Googletest code. Downloaded from the web.
+3. The user-space test code in this distribution
+4. libusb code that is part of the libusb git repository
+
+The Unit tests can be ran on any Linux machine with a device that has g_zero
+and dummy_hcd module loaded on it. If you wish to run the Unit tests on another
+device (one that doesn't support g_zero and dumm_hcd_ it's possible but not all
+of the bellow tests will pass. This is due to the fact that several proprietary
+control requests handling were implemented in the above modules in order to
+support some of the tests. For example: new control request handling was
+added to the dummy_hcd module to perform a connect/disconnect sequence.
+
+
+1.1: GETTING USB-TEST CODE FROM THE KERNEL REPOSITORY
+
+Get the kernel code from
+    git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
+The unit test kernel patches are released as part of kernel2.6.?? so you should
+work with this version of the kernel or later.
+
+Compiling the Kernel code:
+Export $KERNEL to point to the location of your kernel.
+mkdir out-32
+cd out-32
+make -C $KERNEL O=`pwd` ARCH=x86 defconfig
+
+Run the autoconfig.sh script to configure the kernel. Please refer to
+autoconfig_readme for details.
+
+Compilation:
+make -C $KERNEL O=`pwd` ARCH=x8
+
+
+1.2: LIBUSB CODE
+
+Get the libusb code from git://git.libusb.org/libusb.git
+The libusb related patches are merged into the libusb tree. (NOT YET!!!)
+
+1.2.1 Libusb Setup and compilation
+
+Install the following packages (from synaptic):
+a. autoconfig
+b.automake
+c. libtool
+
+Run: ./autogen.sh. –prefix=<output_folder>
+This script will generate the .config file and the Makefile
+
+Open the auto-generated Makefiles (there is one under libusb, one under
+libusb/libusb and another one under libusb/examples) and update the following:
+a)To CPPFLAGS add -m32 (CPPFLAGS = -m32)
+b)To CFLAGS add -m32 (CFLAGS = -g -O2 -m32)
+c)Change every x86_64 to i386
+
+run: make install
+The library and include files will be placed in . --prefix=<output_folder>
+
+
+1.3: GOOGLETEST CODE
+
+Download from
+http://code.google.com/p/googletest/downloads/list (gtest-1.5.0.tar.bz2) .
+Open the Makefile and add “-lpthread” to CXXFLAGS:
+CXXFLAGS += -g -Wall -Wextra -m32 -L/usr/lib32 -lstdc++ -L/usr/local/lib -lusb-1.0 -lpthread
+
+
+1.4 COMPILING USER SPACE TEST CODE (IN THIS PACKAGE)
+
+cd ../tools/usb/unittests/make/ (from your working area)
+
+Set the $KERNEL to your kernel source code, $GTEST to your Googletest directory
+and $LIBUSB to your libusb compilation output directory.
+
+make
+The make creates an executable called usb_tests
+
+
+1.5: VIRTUAL MACHINE
+
+If you wish to use the dummy_hcd module then it's best to run the Unit tests on
+a Virtual machine (VM).
+Debugging of the VM kernel is performed with insight.
+So you'll be required to install the following packages:
+1. qemu
+2. fuseext2
+3. insight
+
+Create gadjet.img. Refer to create-gadget-img for details.
+
+1.5.1 Initial setup of the VM:
+
+Copy usb_tests to the VM.
+Copy the libusb library files to the VM (from <output_folder>/lib)
+
+
+2: RUNNING THE UNIT TEST
+-----------------------
+
+On the VM (or other Linux host) do:
+export LD_LIBRARY_PATH=<libusb library files path on the VM>
+run the tests script: ./usb_tests with relevant input parameters. (Refer to
+unittests-info for additional information)
+
+--
+Created by a consultant of the Qualcomm Innovation Center, Inc.
+The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
+
diff --git a/tools/usb/unittests/libusb_patches/0001-Add-support-to-USB3-descriptors.patch b/tools/usb/unittests/libusb_patches/0001-Add-support-to-USB3-descriptors.patch
new file mode 100644
index 0000000..8c8aaf0
--- /dev/null
+++ b/tools/usb/unittests/libusb_patches/0001-Add-support-to-USB3-descriptors.patch
@@ -0,0 +1,420 @@
+From fcc8bb8ea6a326a2c84e92b29004e8e3896925b7 Mon Sep 17 00:00:00 2001
+From: Maya Erez <merez@codeaurora.org>
+Date: Sun, 13 Mar 2011 22:01:07 +0200
+Subject: [PATCH 1/4] Add support to USB3 descriptors
+
+Add definitions for Endpoint Companion and BOS descriptors.
+Add APIs for parsing the Endpoint Companion and BOS descriptors.
+
+Signed-off-by: Maya Erez <merez@codeaurora.org>
+
+---
+ libusb/descriptor.c |  160 +++++++++++++++++++++++++++++++++++++++++++++++---
+ libusb/libusb.h     |  115 ++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 264 insertions(+), 11 deletions(-)
+
+diff --git a/libusb/descriptor.c b/libusb/descriptor.c
+index 11480e8..0ce6975 100644
+--- a/libusb/descriptor.c
++++ b/libusb/descriptor.c
+@@ -22,6 +22,7 @@
+ #include <stdint.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <stdio.h>
+ 
+ #include "libusbi.h"
+ 
+@@ -45,6 +46,7 @@ int usbi_parse_descriptor(unsigned char *source, const char *descriptor,
+ 	unsigned char *sp = source, *dp = dest;
+ 	uint16_t w;
+ 	const char *cp;
++	uint32_t d;
+ 
+ 	for (cp = descriptor; *cp; cp++) {
+ 		switch (*cp) {
+@@ -63,6 +65,21 @@ int usbi_parse_descriptor(unsigned char *source, const char *descriptor,
+ 				sp += 2;
+ 				dp += 2;
+ 				break;
++			/* 32-bit word, convert from little endian to CPU */
++			case 'd':
++			/* Align to word boundary */
++				dp += ((unsigned long)dp & 1);
++
++				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;
+ 		}
+ 	}
+ 
+@@ -75,6 +92,39 @@ static void clear_endpoint(struct libusb_endpoint_descriptor *endpoint)
+ 		free((unsigned char *) endpoint->extra);
+ }
+ 
++static int parse_endpoint_comp(struct libusb_context *ctx,
++			       struct libusb_ss_ep_comp_descriptor *ep_comp,
++			       unsigned char *buffer, int size)
++{
++	struct usb_descriptor_header header;
++	int parsed = 0;
++
++	usbi_parse_descriptor(buffer, "bb", &header, 0);
++
++	/* Everything should be fine being passed into here, but we sanity */
++	/*  check JIC */
++	if (header.bLength > size) {
++		usbi_err(ctx, "ran out of descriptors parsing");
++		return LIBUSB_ERROR_NO_MEM;
++	}
++
++	if (header.bDescriptorType != LIBUSB_DT_SS_ENDPOINT_COMP) {
++		usbi_err(ctx, "unexpected descriptor %x (expected %x)",
++			header.bDescriptorType, LIBUSB_DT_SS_ENDPOINT_COMP);
++		return parsed;
++	}
++
++	if (header.bLength >= LIBUSB_DT_SS_EP_COMP_SIZE)
++		usbi_parse_descriptor(buffer, "bbbbw", ep_comp, 0);
++
++	buffer += header.bLength;
++	size -= header.bLength;
++	parsed += header.bLength;
++
++	return parsed;
++}
++
++
+ static int parse_endpoint(struct libusb_context *ctx,
+ 	struct libusb_endpoint_descriptor *endpoint, unsigned char *buffer,
+ 	int size, int host_endian)
+@@ -83,7 +133,7 @@ static int parse_endpoint(struct libusb_context *ctx,
+ 	unsigned char *extra;
+ 	unsigned char *begin;
+ 	int parsed = 0;
+-	int len;
++	int len, retval;
+ 
+ 	usbi_parse_descriptor(buffer, "bb", &header, 0);
+ 
+@@ -109,6 +159,28 @@ static int parse_endpoint(struct libusb_context *ctx,
+ 	size -= header.bLength;
+ 	parsed += header.bLength;
+ 
++	/* check if we have a Comapnion descriptor */
++	usbi_parse_descriptor(buffer, "bb", &header, 0);
++	if (header.bDescriptorType == LIBUSB_DT_SS_ENDPOINT_COMP) {
++		endpoint->ep_comp = (struct libusb_ss_ep_comp_descriptor *)
++			malloc(sizeof(struct libusb_ss_ep_comp_descriptor));
++		if (!endpoint->ep_comp) {
++			usbi_err(ctx, "couldn't allocate memory for ep_comp");
++			return LIBUSB_ERROR_NO_MEM;
++		}
++
++		memset(endpoint->ep_comp, 0,
++		       sizeof(struct libusb_ss_ep_comp_descriptor));
++		retval = parse_endpoint_comp(ctx, endpoint->ep_comp,
++					     buffer, size);
++		if (retval < 0)
++			return retval;
++
++		buffer += retval;
++		parsed += retval;
++		size -= retval;
++	}
++
+ 	/* Skip over the rest of the Class Specific or Vendor Specific */
+ 	/*  descriptors */
+ 	begin = buffer;
+@@ -122,9 +194,10 @@ static int parse_endpoint(struct libusb_context *ctx,
+ 
+ 		/* If we find another "proper" descriptor then we're done  */
+ 		if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
+-				(header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
+-				(header.bDescriptorType == LIBUSB_DT_CONFIG) ||
+-				(header.bDescriptorType == LIBUSB_DT_DEVICE))
++		    (header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
++		    (header.bDescriptorType == LIBUSB_DT_CONFIG) ||
++		    (header.bDescriptorType == LIBUSB_DT_DEVICE) ||
++		    (header.bDescriptorType == LIBUSB_DT_SS_ENDPOINT_COMP))
+ 			break;
+ 
+ 		usbi_dbg("skipping descriptor %x", header.bDescriptorType);
+@@ -233,9 +306,11 @@ static int parse_interface(libusb_context *ctx,
+ 
+ 			/* If we find another "proper" descriptor then we're done */
+ 			if ((header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
+-					(header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
+-					(header.bDescriptorType == LIBUSB_DT_CONFIG) ||
+-					(header.bDescriptorType == LIBUSB_DT_DEVICE))
++			    (header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
++			    (header.bDescriptorType == LIBUSB_DT_CONFIG) ||
++			    (header.bDescriptorType == LIBUSB_DT_DEVICE) ||
++			    (header.bDescriptorType ==
++			     LIBUSB_DT_SS_ENDPOINT_COMP))
+ 				break;
+ 
+ 			buffer += header.bLength;
+@@ -379,9 +454,11 @@ static int parse_configuration(struct libusb_context *ctx,
+ 
+ 			/* If we find another "proper" descriptor then we're done */
+ 			if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
+-					(header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
+-					(header.bDescriptorType == LIBUSB_DT_CONFIG) ||
+-					(header.bDescriptorType == LIBUSB_DT_DEVICE))
++			    (header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
++			    (header.bDescriptorType == LIBUSB_DT_CONFIG) ||
++			    (header.bDescriptorType == LIBUSB_DT_DEVICE) ||
++			    (header.bDescriptorType ==
++			     LIBUSB_DT_SS_ENDPOINT_COMP))
+ 				break;
+ 
+ 			usbi_dbg("skipping descriptor 0x%x\n", header.bDescriptorType);
+@@ -726,3 +803,66 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev,
+ 	return di;
+ }
+ 
++
++/** \ingroup desc
++ * Get the USB bos descriptor for a given device.
++ *
++ * \param dev the device
++ * \param bos output bos descriptor
++ * \returns 0 on success
++ */
++API_EXPORTED int libusb_parse_bos_desc(struct libusb_device *dev,
++					struct libusb_bos_descriptor *bos,
++					unsigned char *buf)
++{
++	int i;
++	int desc_begin = 0;
++
++	usbi_parse_descriptor(buf, "bbwb", bos, 0);
++	desc_begin = LIBUSB_DT_BOS_SIZE;
++
++	/* Get the device capability descriptors */
++	for (i = 0; i < bos->bNumDeviceCaps; ++i) {
++		if (buf[desc_begin+2] == LIBUSB_USB_CAP_TYPE_EXT) {
++			if (!bos->usb_ext_cap) {
++				bos->usb_ext_cap =
++				(struct libusb_usb_ext_cap_descriptor *)
++				malloc(sizeof(struct
++					      libusb_usb_ext_cap_descriptor));
++				usbi_parse_descriptor(buf+desc_begin, "bbbd",
++						      bos->usb_ext_cap, 0);
++			} else
++				usbi_warn(dev->ctx,
++					  "usb_ext_cap was already allocated");
++
++			/* move to the next device capability descriptor */
++			desc_begin += LIBUSB_DT_USB_CAP_TYPE_EXT_SIZE;
++		} else if (buf[desc_begin+2] == LIBUSB_SS_USB_CAP_TYPE) {
++			if (!bos->ss_usb_cap) {
++				bos->ss_usb_cap =
++				(struct libusb_ss_usb_cap_descriptor *)
++				malloc(sizeof(struct
++					      libusb_ss_usb_cap_descriptor));
++
++				usbi_parse_descriptor(buf+desc_begin,
++						      "bbbbwbbw",
++						      bos->ss_usb_cap, 0);
++			} else
++				usbi_warn(dev->ctx,
++					  "ss_usb_cap was already allocated");
++
++			/* move to the next device capability descriptor */
++			desc_begin += LIBUSB_DT_SS_USB_CAP_TYPE_SIZE;
++		} else {
++			usbi_info(dev->ctx,
++				  "wireless/container_id capability "
++				  "descriptor");
++
++			/* move to the next device capability descriptor */
++			desc_begin += buf[desc_begin];
++		}
++	}
++	return 0;
++}
++
++
+diff --git a/libusb/libusb.h b/libusb/libusb.h
+index 8dc3362..9f2243a 100644
+--- a/libusb/libusb.h
++++ b/libusb/libusb.h
+@@ -191,7 +191,16 @@ enum libusb_descriptor_type {
+ 	LIBUSB_DT_PHYSICAL = 0x23,
+ 
+ 	/** Hub descriptor */
+-	LIBUSB_DT_HUB = 0x29
++	LIBUSB_DT_HUB = 0x29,
++
++	/** BOS descriptor */
++	LIBUSB_DT_BOS = 0x0f,
++
++	/** Device Capability descriptor */
++	LIBUSB_DT_DEVICE_CAPABILITY = 0x10,
++
++	/** SuperSpeed Endpoint Companion descriptor */
++	LIBUSB_DT_SS_ENDPOINT_COMP = 0x30
+ };
+ 
+ /* Descriptor sizes per descriptor type */
+@@ -201,6 +210,13 @@ enum libusb_descriptor_type {
+ #define LIBUSB_DT_ENDPOINT_SIZE		7
+ #define LIBUSB_DT_ENDPOINT_AUDIO_SIZE	9	/* Audio extension */
+ #define LIBUSB_DT_HUB_NONVAR_SIZE		7
++#define LIBUSB_DT_SS_EP_COMP_SIZE		6
++#define LIBUSB_DT_BOS_SIZE			5
++#define LIBUSB_DT_USB_CAP_TYPE_EXT_SIZE	7
++#define LIBUSB_DT_SS_USB_CAP_TYPE_SIZE	10
++#define LIBUSB_DT_BOS_MAX_SIZE		((LIBUSB_DT_BOS_SIZE) + \
++					(LIBUSB_DT_USB_CAP_TYPE_EXT_SIZE) + \
++					(LIBUSB_DT_SS_USB_CAP_TYPE_SIZE))
+ 
+ #define LIBUSB_ENDPOINT_ADDRESS_MASK	0x0f    /* in bEndpointAddress */
+ #define LIBUSB_ENDPOINT_DIR_MASK		0x80
+@@ -407,6 +423,33 @@ struct libusb_device_descriptor {
+ 	uint8_t  bNumConfigurations;
+ };
+ 
++/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */
++struct libusb_ss_ep_comp_descriptor {
++
++	/** Size of this descriptor (in bytes) */
++	u_int8_t  bLength;
++
++	/** Descriptor type. Will have value
++	 * \ref libusb_descriptor_type::LIBUSB_DT_SS_ENDPOINT_COMP in
++	 * this context. */
++	u_int8_t  bDescriptorType;
++
++
++	/** The maximum number of packets the endpoint can send or
++	 *  recieve as part of a burst. */
++	u_int8_t  bMaxBurst;
++
++	/** In bulk EP:	bits 4:0 represents the	maximum	number of
++	 *  streams the	EP supports. In	isochronous EP:	bits 1:0
++	 *  represents the Mult	- a zero based value that determines
++	 *  the	maximum	number of packets within a service interval  */
++	u_int8_t  bmAttributes;
++
++	/** The	total number of bytes this EP will transfer every
++	 *  service interval. valid only for periodic EPs. */
++	u_int16_t wBytesPerInterval;
++};
++
+ /** \ingroup desc
+  * A structure representing the standard USB endpoint descriptor. This
+  * descriptor is documented in section 9.6.3 of the USB 2.0 specification.
+@@ -449,6 +492,9 @@ struct libusb_endpoint_descriptor {
+ 	/** For audio devices only: the address if the synch endpoint */
+ 	uint8_t  bSynchAddress;
+ 
++	/** The	EP companion descriptor */
++	struct libusb_ss_ep_comp_descriptor *ep_comp;
++
+ 	/** Extra descriptors. If libusb encounters unknown endpoint descriptors,
+ 	 * it will store them here, should you wish to parse them. */
+ 	const unsigned char *extra;
+@@ -457,6 +503,7 @@ struct libusb_endpoint_descriptor {
+ 	int extra_length;
+ };
+ 
++
+ /** \ingroup desc
+  * A structure representing the standard USB interface descriptor. This
+  * descriptor is documented in section 9.6.5 of the USB 2.0 specification.
+@@ -565,6 +612,60 @@ struct libusb_config_descriptor {
+ 	int extra_length;
+ };
+ 
++/** \ingroup desc
++ * A structure representing the BOS descriptor. This
++ * descriptor is documented in section 9.6.2 of the USB 3.0
++ * specification. All multiple-byte fields are represented in
++ * host-endian format.
++ */
++struct libusb_bos_descriptor {
++	u_int8_t  bLength;
++	u_int8_t  bDescriptorType;
++	u_int16_t wTotalLength;
++	u_int8_t  bNumDeviceCaps;
++
++	struct libusb_usb_ext_cap_descriptor *usb_ext_cap;
++	struct libusb_ss_usb_cap_descriptor *ss_usb_cap;
++};
++
++
++struct libusb_dev_cap_header {
++	u_int8_t  bLength;
++	u_int8_t  bDescriptorType;
++	u_int8_t  bDevCapabilityType;
++};
++
++
++#define	LIBUSB_USB_CAP_TYPE_EXT		2
++
++struct libusb_usb_ext_cap_descriptor {		/* Link Power Management */
++	u_int8_t  bLength;
++	u_int8_t  bDescriptorType;
++	u_int8_t  bDevCapabilityType;
++	u_int32_t  bmAttributes;
++#define LIBUSB_LPM_SUPPORT		(1 << 1)	/* supports LPM */
++};
++
++
++#define	LIBUSB_SS_USB_CAP_TYPE		3
++
++struct libusb_ss_usb_cap_descriptor {		/* Link Power Management */
++	u_int8_t  bLength;
++	u_int8_t  bDescriptorType;
++	u_int8_t  bDevCapabilityType;
++	u_int8_t  bmAttributes;
++#define LIBUSB_LPM_SUPPORT		(1 << 1)	/* supports LPM */
++	u_int16_t wSpeedSupported;
++#define LIBUSB_LOW_SPEED_OPERATION	(1)	/* Low speed operation */
++#define LIBUSB_FULL_SPEED_OPERATION	(1 << 1)/* Full speed operation */
++#define LIBUSB_HIGH_SPEED_OPERATION	(1 << 2)/* High speed operation */
++#define LIBUSB_5GBPS_OPERATION		(1 << 3)/* Operation at 5Gbps */
++	u_int8_t  bFunctionalitySupport;
++	u_int8_t  bU1devExitLat;
++	u_int16_t bU2DevExitLat;
++};
++
++
+ /** \ingroup asyncio
+  * Setup packet for control transfers. */
+ struct libusb_control_setup {
+@@ -1315,6 +1416,18 @@ void LIBUSB_CALL libusb_set_pollfd_notifiers(libusb_context *ctx,
+ 	libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb,
+ 	void *user_data);
+ 
++
++/** \ingroup desc
++ * Get the USB bos descriptor for a given device.
++ *
++ * \param dev the device
++ * \param bos output bos descriptor
++ * \returns 0 on success
++ */
++int libusb_parse_bos_desc(struct libusb_device *dev,
++			   struct libusb_bos_descriptor *bos,
++			   unsigned char *buf);
++
+ #ifdef __cplusplus
+ }
+ #endif
+-- 
+1.7.3.3
+
+--
+Sent by an employee of the Qualcomm Innovation Center, Inc.
+The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
\ No newline at end of file
diff --git a/tools/usb/unittests/libusb_patches/0002-Add-support-for-libusb_get_device_speed.patch b/tools/usb/unittests/libusb_patches/0002-Add-support-for-libusb_get_device_speed.patch
new file mode 100644
index 0000000..ca612bb
--- /dev/null
+++ b/tools/usb/unittests/libusb_patches/0002-Add-support-for-libusb_get_device_speed.patch
@@ -0,0 +1,172 @@
+From c5df8c1d47367d214c40bf932244f8b44f1f4caf Mon Sep 17 00:00:00 2001
+From: Tatyana Brokhman <tlinder@codeaurora.org>
+Date: Mon, 14 Mar 2011 16:18:26 +0200
+Subject: [PATCH 2/4] Add support for libusb_get_device_speed()
+
+This patch adds a new libusb function used to determine the connected USB
+device speed.
+
+Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>
+
+---
+ libusb/core.c           |   17 ++++++++++++++
+ libusb/libusb.h         |   11 +++++++++
+ libusb/libusbi.h        |    7 ++++++
+ libusb/os/linux_usbfs.c |   56 +++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 91 insertions(+), 0 deletions(-)
+
+diff --git a/libusb/core.c b/libusb/core.c
+index 64445ab..6d49fb3 100644
+--- a/libusb/core.c
++++ b/libusb/core.c
+@@ -745,6 +745,23 @@ int API_EXPORTED libusb_get_max_packet_size(libusb_device *dev,
+ }
+ 
+ /** \ingroup dev
++ * Convenience function to retrieve the speed of the connected
++ * device
++ *
++ * \param dev a device
++ * \returns the connected device speed
++ * \returns LIBUSB_ERROR_NOT_SUPPORTED if get_device_speed() cb
++ *  	    was not defined for the usbi_backend
++ * \returns LIBUSB_ERROR_OTHER on other failure
++ */
++API_EXPORTED int libusb_get_dev_speed(libusb_device *dev)
++{
++	if (usbi_backend->get_device_speed)
++		return usbi_backend->get_device_speed(dev);
++	return LIBUSB_ERROR_NOT_SUPPORTED;
++}
++
++/** \ingroup dev
+  * Calculate the maximum packet size which a specific endpoint is capable is
+  * sending or receiving in the duration of 1 microframe
+  *
+diff --git a/libusb/libusb.h b/libusb/libusb.h
+index 9f2243a..346f85f 100644
+--- a/libusb/libusb.h
++++ b/libusb/libusb.h
+@@ -89,6 +89,16 @@
+ extern "C" {
+ #endif
+ 
++/* USB 2.0 defines three speeds, here's how Linux identifies them */
++enum libusb_device_speed {
++	LIBUSB_SPEED_UNKNOWN = 0,			/* enumerating */
++	LIBUSB_SPEED_LOW, LIBUSB_SPEED_FULL,		/* usb 1.1 */
++	LIBUSB_SPEED_HIGH,				/* usb 2.0 */
++	LIBUSB_SPEED_VARIABLE,			/* wireless (usb 2.5) */
++	LIBUSB_SPEED_SUPER,			/* usb 3.0 */
++};
++
++
+ /** \def libusb_cpu_to_le16
+  * \ingroup misc
+  * Convert a 16-bit value from host-endian to little-endian format. On
+@@ -965,6 +975,7 @@ int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev,
+ 	unsigned char endpoint);
+ int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev,
+ 	unsigned char endpoint);
++int LIBUSB_CALL libusb_get_dev_speed(libusb_device *dev);
+ 
+ int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **handle);
+ void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle);
+diff --git a/libusb/libusbi.h b/libusb/libusbi.h
+index 974b108..87cd770 100644
+--- a/libusb/libusbi.h
++++ b/libusb/libusbi.h
+@@ -591,6 +591,13 @@ struct usbi_os_backend {
+ 		uint8_t config_index, unsigned char *buffer, size_t len,
+ 		int *host_endian);
+ 
++
++	/* Get the connected device speed
++	 *
++	 * Return 0 on success or a LIBUSB_ERROR_OTHER code on failure.
++	 */
++	int (*get_device_speed)(struct libusb_device *device);
++
+ 	/* Get the bConfigurationValue for the active configuration for a device.
+ 	 * Optional. This should only be implemented if you can retrieve it from
+ 	 * cache (don't generate I/O).
+diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
+index 867893c..430d773 100644
+--- a/libusb/os/linux_usbfs.c
++++ b/libusb/os/linux_usbfs.c
+@@ -333,6 +333,61 @@ static int sysfs_get_device_descriptor(struct libusb_device *dev,
+ 	return 0;
+ }
+ 
++static int sysfs_get_device_speed(struct libusb_device *dev)
++{
++	int fd;
++	ssize_t r;
++	unsigned char buffer[32];
++	char *tmp;
++
++	fd = __open_sysfs_attr(dev, "speed");
++	if (fd < 0)
++		return fd;
++
++	r = read(fd, &buffer, 32);
++	close(fd);
++	if (r < 0) {
++		usbi_err(DEVICE_CTX(dev), "read failed, ret=%d errno=%d", fd, errno);
++		return LIBUSB_ERROR_OTHER;
++	}
++
++	/*
++	 * The read string from sysfs terminates with a "new line" char
++	 * (A in ascii code) which we want to trim
++	 */
++	tmp = strchr(buffer,  10);
++	*tmp=0;
++
++	/* 
++	 * The spped is dumped in sysfs.c as follows:
++	 * case USB_SPEED_LOW: speed = "1.5";
++	 * case USB_SPEED_UNKNOWN/USB_SPEED_FULL: speed = "12";
++	 * case USB_SPEED_HIGH/USB_SPEED_WIRELESS:	speed = "480";
++	 * case USB_SPEED_SUPER: speed = "5000";
++	 */
++
++	if (!strcmp("1.5",buffer))
++		return LIBUSB_SPEED_LOW;
++
++	if (!strcmp("12",buffer))
++		return LIBUSB_SPEED_FULL;
++
++	if (!strcmp("480",buffer))
++		return LIBUSB_SPEED_HIGH;
++
++	if (!strcmp("5000",buffer))
++		return LIBUSB_SPEED_SUPER;
++
++	return LIBUSB_SPEED_UNKNOWN;
++}
++
++static int op_get_dev_speed(struct libusb_device *dev)
++{
++	if (sysfs_has_descriptors)
++		return sysfs_get_device_speed(dev);
++	return LIBUSB_SPEED_UNKNOWN;
++}
++
+ static int op_get_device_descriptor(struct libusb_device *dev,
+ 	unsigned char *buffer, int *host_endian)
+ {
+@@ -2210,6 +2265,7 @@ const struct usbi_os_backend linux_usbfs_backend = {
+ 	.get_device_descriptor = op_get_device_descriptor,
+ 	.get_active_config_descriptor = op_get_active_config_descriptor,
+ 	.get_config_descriptor = op_get_config_descriptor,
++	.get_device_speed = op_get_dev_speed,
+ 
+ 	.open = op_open,
+ 	.close = op_close,
+-- 
+1.7.3.3
+
+--
+Sent by an employee of the Qualcomm Innovation Center, Inc.
+The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
\ No newline at end of file
diff --git a/tools/usb/unittests/libusb_patches/0003-Add-UAS-defines.patch b/tools/usb/unittests/libusb_patches/0003-Add-UAS-defines.patch
new file mode 100644
index 0000000..a1abfd2
--- /dev/null
+++ b/tools/usb/unittests/libusb_patches/0003-Add-UAS-defines.patch
@@ -0,0 +1,56 @@
+From 45864135c176df8bf03bff05733acd8c8ec0579e Mon Sep 17 00:00:00 2001
+From: Tatyana Brokhman <tlinder@codeaurora.org>
+Date: Tue, 14 Jun 2011 13:25:37 +0300
+Subject: [PATCH 3/4] Add UAS defines
+
+This patch adds necessary definitions as defined by the UAS spec
+
+Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>
+
+---
+ libusb/libusb.h |   19 ++++++++++++++++++-
+ 1 files changed, 18 insertions(+), 1 deletions(-)
+
+diff --git a/libusb/libusb.h b/libusb/libusb.h
+index 346f85f..c5e2fbb 100644
+--- a/libusb/libusb.h
++++ b/libusb/libusb.h
+@@ -210,7 +210,12 @@ enum libusb_descriptor_type {
+ 	LIBUSB_DT_DEVICE_CAPABILITY = 0x10,
+ 
+ 	/** SuperSpeed Endpoint Companion descriptor */
+-	LIBUSB_DT_SS_ENDPOINT_COMP = 0x30
++	LIBUSB_DT_SS_ENDPOINT_COMP = 0x30,
++
++	/** UASP descriptors:   */
++	/** Pipe usage descriptor   */
++	LIBUSB_DT_PIPE_USAGE = 0x24
++
+ };
+ 
+ /* Descriptor sizes per descriptor type */
+@@ -675,6 +680,18 @@ struct libusb_ss_usb_cap_descriptor {		/* Link Power Management */
+ 	u_int16_t bU2DevExitLat;
+ };
+ 
++/* LIBUSB_DT_PIPE_USAGE descriptor */
++struct libusb_uasp_pipe_usage_desc {
++    u_int8_t  bLength;
++    u_int8_t  bDescriptorType;
++#define PIPE_ID_UNDEF       0x00
++#define PIPE_ID_CMD         0x01
++#define PIPE_ID_STS         0x02
++#define PIPE_ID_DATA_IN     0x03
++#define PIPE_ID_DATA_OUT    0x04
++    u_int8_t  bPipeID;
++    u_int8_t  reserved;
++};
+ 
+ /** \ingroup asyncio
+  * Setup packet for control transfers. */
+-- 
+1.7.3.3
+
+--
+Sent by an employee of the Qualcomm Innovation Center, Inc.
+The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
\ No newline at end of file
diff --git a/tools/usb/unittests/libusb_patches/0004-libusb-Add-stream-support-to-LIBUSB.patch b/tools/usb/unittests/libusb_patches/0004-libusb-Add-stream-support-to-LIBUSB.patch
new file mode 100644
index 0000000..a7059be
--- /dev/null
+++ b/tools/usb/unittests/libusb_patches/0004-libusb-Add-stream-support-to-LIBUSB.patch
@@ -0,0 +1,314 @@
+From 436bfafeefaa7f71252578b66394735f5d2da0c6 Mon Sep 17 00:00:00 2001
+From: Tatyana Brokhman <tlinder@codeaurora.org>
+Date: Sun, 12 Jun 2011 15:05:32 +0300
+Subject: [PATCH 4/4] libusb: Add stream support to LIBUSB
+
+1. Add stream ID to bulk transfer API
+2. Add stream alloc/free APIs
+
+Signed-off-by: Amit Blay <ablay@qualcomm.com>
+
+---
+ libusb/core.c           |   38 ++++++++++++++++++++++++++++++++++++++
+ libusb/libusb.h         |   13 +++++++++++++
+ libusb/libusbi.h        |   30 +++++++++++++++++++++++++++++-
+ libusb/os/linux_usbfs.c |   43 +++++++++++++++++++++++++++++++++++++++++++
+ libusb/os/linux_usbfs.h |    3 +++
+ libusb/sync.c           |   42 +++++++++++++++++++++++++++++++++++++++---
+ 6 files changed, 165 insertions(+), 4 deletions(-)
+
+diff --git a/libusb/core.c b/libusb/core.c
+index 6d49fb3..b8bd11c 100644
+--- a/libusb/core.c
++++ b/libusb/core.c
+@@ -1298,6 +1298,44 @@ out:
+ }
+ 
+ /** \ingroup dev
++ * Allocate streams for an EP.
++ *
++ * This is a blocking function.
++ *
++ * \param dev a device handle
++ * \param ep_map the endpoints to allocate streams for
++ * \returns 0 on success
++ * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist
++ * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
++ * \returns another LIBUSB_ERROR code on other failure
++ */
++API_EXPORTED int libusb_alloc_streams(libusb_device_handle *dev,
++	unsigned int ep_map)
++{
++	usbi_dbg("endpoint %x", ep_map);
++	return usbi_backend->alloc_streams(dev, ep_map);
++}
++
++/** \ingroup dev
++ * Free streams for an EP.
++ *
++ * This is a blocking function.
++ *
++ * \param dev a device handle
++ * \param endpoint the endpoint to free streams for
++ * \returns 0 on success
++ * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist
++ * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
++ * \returns another LIBUSB_ERROR code on other failure
++ */
++API_EXPORTED int libusb_free_streams(libusb_device_handle *dev,
++	unsigned int ep_map)
++{
++	usbi_dbg("endpoint %x", ep_map);
++	return usbi_backend->free_streams(dev, ep_map);
++}
++
++/** \ingroup dev
+  * Activate an alternate setting for an interface. The interface must have
+  * been previously claimed with libusb_claim_interface().
+  *
+diff --git a/libusb/libusb.h b/libusb/libusb.h
+index c5e2fbb..1c70139 100644
+--- a/libusb/libusb.h
++++ b/libusb/libusb.h
+@@ -952,6 +952,10 @@ struct libusb_transfer {
+ 	 * endpoints. */
+ 	int num_iso_packets;
+ 
++	/** Stream ID for the endpoint where the transfer will be
++	 *  sent. */
++	unsigned int stream_id;
++
+ 	/** Isochronous packet descriptors, for isochronous transfers only. */
+ 	struct libusb_iso_packet_descriptor iso_packet_desc
+ #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+@@ -1004,6 +1008,11 @@ int LIBUSB_CALL libusb_claim_interface(libusb_device_handle *dev,
+ 	int interface_number);
+ int LIBUSB_CALL libusb_release_interface(libusb_device_handle *dev,
+ 	int interface_number);
++int LIBUSB_CALL libusb_alloc_streams(libusb_device_handle *dev,
++	unsigned int ep_map);
++int LIBUSB_CALL libusb_free_streams(libusb_device_handle *dev,
++	unsigned int ep_map);
++
+ 
+ libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid(
+ 	libusb_context *ctx, uint16_t vendor_id, uint16_t product_id);
+@@ -1331,6 +1340,10 @@ int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev_handle,
+ 	unsigned char endpoint, unsigned char *data, int length,
+ 	int *actual_length, unsigned int timeout);
+ 
++int LIBUSB_CALL libusb_bulk_transfer_ex(libusb_device_handle *dev_handle,
++	unsigned char endpoint, unsigned char *data, int length,
++	int *actual_length, unsigned int timeout, unsigned int stream_id);
++
+ int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle,
+ 	unsigned char endpoint, unsigned char *data, int length,
+ 	int *actual_length, unsigned int timeout);
+diff --git a/libusb/libusbi.h b/libusb/libusbi.h
+index 87cd770..59c5e59 100644
+--- a/libusb/libusbi.h
++++ b/libusb/libusbi.h
+@@ -687,7 +687,35 @@ struct usbi_os_backend {
+ 	int (*set_interface_altsetting)(struct libusb_device_handle *handle,
+ 		int interface_number, int altsetting);
+ 
+-	/* Clear a halt/stall condition on an endpoint.
++	/* Allcoate streams for en EP.
++	 *
++	 * It's OK for this function to block.
++	 *
++	 * Return:
++	 * - 0 on success
++	 * - LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist
++	 * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it
++	 *   was opened
++	 * - another LIBUSB_ERROR code on other failure
++	 */
++	int (*alloc_streams)(struct libusb_device_handle *handle,
++		unsigned int ep_map);
++
++	/* Free allocated streams for en EP.
++	 *
++	 * It's OK for this function to block.
++	 *
++	 * Return:
++	 * - 0 on success
++	 * - LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist
++	 * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it
++	 *   was opened
++	 * - another LIBUSB_ERROR code on other failure
++	 */
++	int (*free_streams)(struct libusb_device_handle *handle,
++		unsigned int ep_map);
++
++    /* Clear a halt/stall condition on an endpoint.
+ 	 *
+ 	 * It's OK for this function to block.
+ 	 *
+diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
+index 430d773..ce62220 100644
+--- a/libusb/os/linux_usbfs.c
++++ b/libusb/os/linux_usbfs.c
+@@ -1215,6 +1215,46 @@ static int op_claim_interface(struct libusb_device_handle *handle, int iface)
+ 	return 0;
+ }
+ 
++static int op_alloc_streams(struct libusb_device_handle *handle,
++	unsigned int ep_map)
++{
++	int fd = __device_handle_priv(handle)->fd;
++	unsigned int _ep_map = ep_map;
++	int r = ioctl(fd, IOCTL_USBFS_ALLOC_STREAMS, &_ep_map);
++	if (r) {
++		if (errno == ENOENT)
++			return LIBUSB_ERROR_NOT_FOUND;
++		else if (errno == ENODEV)
++			return LIBUSB_ERROR_NO_DEVICE;
++
++		usbi_err(HANDLE_CTX(handle),
++			"alloc_streams failed error %d errno %d", r, errno);
++		return LIBUSB_ERROR_OTHER;
++	}
++
++	return 0;
++}
++
++static int op_free_streams(struct libusb_device_handle *handle,
++	unsigned int ep_map)
++{
++	int fd = __device_handle_priv(handle)->fd;
++	unsigned int _ep_map = ep_map;
++	int r = ioctl(fd, IOCTL_USBFS_FREE_STREAMS, &_ep_map);
++	if (r) {
++		if (errno == ENOENT)
++			return LIBUSB_ERROR_NOT_FOUND;
++		else if (errno == ENODEV)
++			return LIBUSB_ERROR_NO_DEVICE;
++
++		usbi_err(HANDLE_CTX(handle),
++			"free_streams failed error %d errno %d", r, errno);
++		return LIBUSB_ERROR_OTHER;
++	}
++
++	return 0;
++}
++
+ static int op_release_interface(struct libusb_device_handle *handle, int iface)
+ {
+ 	int fd = __device_handle_priv(handle)->fd;
+@@ -1450,6 +1490,7 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer,
+ 		urb->type = urb_type;
+ 		urb->endpoint = transfer->endpoint;
+ 		urb->buffer = transfer->buffer + (i * MAX_BULK_BUFFER_LENGTH);
++		urb->stream_id = transfer->stream_id;
+ 		if (supports_flag_bulk_continuation && !is_out)
+ 			urb->flags = USBFS_URB_SHORT_NOT_OK;
+ 		if (i == num_urbs - 1 && last_urb_partial)
+@@ -2273,6 +2314,8 @@ const struct usbi_os_backend linux_usbfs_backend = {
+ 	.set_configuration = op_set_configuration,
+ 	.claim_interface = op_claim_interface,
+ 	.release_interface = op_release_interface,
++	.alloc_streams = op_alloc_streams,
++	.free_streams = op_free_streams,
+ 
+ 	.set_interface_altsetting = op_set_interface,
+ 	.clear_halt = op_clear_halt,
+diff --git a/libusb/os/linux_usbfs.h b/libusb/os/linux_usbfs.h
+index bd02edc..9d5d4ca 100644
+--- a/libusb/os/linux_usbfs.h
++++ b/libusb/os/linux_usbfs.h
+@@ -96,6 +96,7 @@ struct usbfs_urb {
+ 	unsigned int signr;
+ 	void *usercontext;
+ 	struct usbfs_iso_packet_desc iso_frame_desc[0];
++	unsigned int stream_id;
+ };
+ 
+ struct usbfs_connectinfo {
+@@ -134,5 +135,7 @@ struct usbfs_hub_portinfo {
+ #define IOCTL_USBFS_CLEAR_HALT	_IOR('U', 21, unsigned int)
+ #define IOCTL_USBFS_DISCONNECT	_IO('U', 22)
+ #define IOCTL_USBFS_CONNECT	_IO('U', 23)
++#define IOCTL_USBFS_ALLOC_STREAMS	_IOR('U', 26, unsigned int)
++#define IOCTL_USBFS_FREE_STREAMS	_IOR('U', 27, unsigned int)
+ 
+ #endif
+diff --git a/libusb/sync.c b/libusb/sync.c
+index 3870f95..f4a6dc3 100644
+--- a/libusb/sync.c
++++ b/libusb/sync.c
+@@ -152,7 +152,8 @@ static void LIBUSB_CALL bulk_transfer_cb(struct libusb_transfer *transfer)
+ 
+ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle,
+ 	unsigned char endpoint, unsigned char *buffer, int length,
+-	int *transferred, unsigned int timeout, unsigned char type)
++	int *transferred, unsigned int timeout, unsigned char type,
++	unsigned int stream_id)
+ {
+ 	struct libusb_transfer *transfer = libusb_alloc_transfer(0);
+ 	int completed = 0;
+@@ -164,6 +165,7 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle,
+ 	libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length,
+ 		bulk_transfer_cb, &completed, timeout);
+ 	transfer->type = type;
++	transfer->stream_id = stream_id;
+ 
+ 	r = libusb_submit_transfer(transfer);
+ 	if (r < 0) {
+@@ -257,7 +259,41 @@ int API_EXPORTED libusb_bulk_transfer(struct libusb_device_handle *dev_handle,
+ 	unsigned int timeout)
+ {
+ 	return do_sync_bulk_transfer(dev_handle, endpoint, data, length,
+-		transferred, timeout, LIBUSB_TRANSFER_TYPE_BULK);
++		transferred, timeout, LIBUSB_TRANSFER_TYPE_BULK, 0);
++}
++
++/** \ingroup syncio
++ * Perform a USB bulk transfer with extended paramter list,
++ * which includes USB3 stream ID.
++ *
++ * \param dev_handle a handle for the device to communicate with
++ * \param endpoint the address of a valid endpoint to communicate with
++ * \param data a suitably-sized data buffer for either input or output
++ * (depending on endpoint)
++ * \param length for bulk writes, the number of bytes from data to be sent. for
++ * bulk reads, the maximum number of bytes to receive into the data buffer.
++ * \param transferred output location for the number of bytes actually
++ * transferred.
++ * \param timeout timeout (in millseconds) that this function should wait
++ * before giving up due to no response being received. For an unlimited
++ * timeout, use value 0.
++ *
++ * \returns 0 on success (and populates <tt>transferred</tt>)
++ * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out (and populates
++ * <tt>transferred</tt>)
++ * \returns LIBUSB_ERROR_PIPE if the endpoint halted
++ * \returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see
++ * \ref packetoverflow
++ * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
++ * \returns another LIBUSB_ERROR code on other failures
++ */
++API_EXPORTED int libusb_bulk_transfer_ex(
++	struct libusb_device_handle *dev_handle, unsigned char endpoint,
++	unsigned char *data, int length, int *transferred, unsigned int timeout,
++	unsigned int stream_id)
++{
++	return do_sync_bulk_transfer(dev_handle, endpoint, data, length,
++		transferred, timeout, LIBUSB_TRANSFER_TYPE_BULK, stream_id);
+ }
+ 
+ /** \ingroup syncio
+@@ -306,6 +342,6 @@ int API_EXPORTED libusb_interrupt_transfer(
+ 	unsigned char *data, int length, int *transferred, unsigned int timeout)
+ {
+ 	return do_sync_bulk_transfer(dev_handle, endpoint, data, length,
+-		transferred, timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT);
++		transferred, timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT, 0);
+ }
+ 
+-- 
+1.7.3.3
+
+--
+Sent by an employee of the Qualcomm Innovation Center, Inc.
+The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
\ No newline at end of file
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..599416b
--- /dev/null
+++ b/tools/usb/unittests/usb/composite_tests.cc
@@ -0,0 +1,1645 @@
+/*
+ * 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 or dummy_hcd).
+ * @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
+ *	 0x52 - start connect/disconnect sequence
+ * @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) and dummy_hcd modules
+ */
+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;
+	}
+
+	wValue = 0;
+	ret = soursesink_test_setup(udev, dev, CONN_DISCONN_TEST, wValue);
+
+	/*
+	 * 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..550e0cb
--- /dev/null
+++ b/tools/usb/unittests/usb/composite_tests.h
@@ -0,0 +1,293 @@
+/*
+ * 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"
+
+
+/**
+ * soursesink_test_setup() - Send a control request to setup/begin a spesific
+ * test (to be handled by f_soursesink or dummy_hcd).
+ * @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
+ *	 0x52 - start connect/disconnect sequence
+ * @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) and dummy_hcd modules
+ */
+int soursesink_test_setup(struct libusb_device_handle *udev,
+			  libusb_device *dev,
+			  uint8_t request,
+			  uint16_t wValue);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * test_hs_set_feature_suspend_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 hs interface in default
+ * state, to set the suspend capability
+ */
+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.3.3

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH/RFC 2/5] usb:dummy_hcd: connect/disconnect test support
  2011-06-16 13:31 ` Tatyana Brokhman
@ 2011-06-16 13:31     ` Tatyana Brokhman
  -1 siblings, 0 replies; 54+ messages in thread
From: Tatyana Brokhman @ 2011-06-16 13:31 UTC (permalink / raw)
  To: greg-U8xfFu+wG4EAvxtiuMwx3w
  Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, balbi-l0cyMroinI0,
	ablay-sgV2jX0FEOL9JmXXK+q4OQ, Tatyana Brokhman, open list

This implementation adds a new proprietary device control requests (to be
handled by the dummy_hcd) that initiates a connect/disconnect sequence.
The bRequest value of the new control request is 0x52.
It is used by the user-space Unit testing application.

Signed-off-by: Tatyana Linder <tlinder-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

---
 drivers/usb/gadget/dummy_hcd.c |   48 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 48 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 74b7655..7d0a6fe 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -179,6 +179,7 @@ struct dummy_hcd {
 	unsigned			active:1;
 	unsigned			old_active:1;
 	unsigned			resuming:1;
+	struct work_struct		conn_disc_work;
 };
 
 struct dummy {
@@ -1362,6 +1363,43 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
 #define Ep_Request	(USB_TYPE_STANDARD | USB_RECIP_ENDPOINT)
 #define Ep_InRequest	(Ep_Request | USB_DIR_IN)
 
+/**
+ * dummy_hcd_conn_disc_work() - performs a disconnect/connect sequence.
+ * @data: pointer to the sceduled work_struct
+ */
+static void dummy_hcd_conn_disc_work(struct work_struct *data)
+{
+	struct dummy_hcd *dum_hcd =
+		container_of(data, struct dummy_hcd, conn_disc_work);
+	int ret_val;
+
+	if (!dum_hcd->dum->driver) {
+		dev_err(dummy_dev(dum_hcd),
+			"dummy_hcd_conn_disc_work called without connected "
+			"device\n");
+		return;
+	}
+
+	dev_info(dummy_dev(dum_hcd), "disconnecting device...\n");
+	ret_val = dummy_pullup(&dum_hcd->dum->gadget, 0);
+	if (ret_val) {
+		dev_err(dummy_dev(dum_hcd), "dummy_hcd_conn_disc_work:"
+					    " couldn't disconnect device:"
+					    " ret_val=%d\n",
+				ret_val);
+		return;
+	}
+
+	dev_info(dummy_dev(dum_hcd), "re-connecting device...\n");
+	/* We have to let the hub task to update the device disconnect state */
+	msleep_interruptible(1000);
+	ret_val = dummy_pullup(&dum_hcd->dum->gadget, 1);
+	if (ret_val)
+		dev_err(dummy_dev(dum_hcd), "dummy_hcd_conn_disc_work:"
+					    " couldn't re-connect device:"
+					    " ret_val=%d\n",
+				ret_val);
+}
 
 /**
  * handle_control_request() - handles all control transfers
@@ -1534,6 +1572,10 @@ static int handle_control_request(struct dummy_hcd *dum_hcd, struct urb *urb,
 			*status = 0;
 		}
 		break;
+	case 0x52:	/* UT: Connect/disconnect the device */
+		schedule_work(&dum_hcd->conn_disc_work);
+		ret_val = 0;
+		break;
 	}
 	return ret_val;
 }
@@ -2249,6 +2291,8 @@ static int dummy_setup(struct usb_hcd *hcd)
 	if (usb_hcd_is_primary_hcd(hcd)) {
 		the_controller.hs_hcd = hcd_to_dummy_hcd(hcd);
 		the_controller.hs_hcd->dum = &the_controller;
+		INIT_WORK(&the_controller.hs_hcd->conn_disc_work,
+			  dummy_hcd_conn_disc_work);
 		/*
 		 * Mark the first roothub as being USB 2.0.
 		 * The USB 3.0 roothub will be registered later by
@@ -2259,6 +2303,8 @@ static int dummy_setup(struct usb_hcd *hcd)
 	} else {
 		the_controller.ss_hcd = hcd_to_dummy_hcd(hcd);
 		the_controller.ss_hcd->dum = &the_controller;
+		INIT_WORK(&the_controller.ss_hcd->conn_disc_work,
+			  dummy_hcd_conn_disc_work);
 		hcd->speed = HCD_USB3;
 		hcd->self.root_hub->speed = USB_SPEED_SUPER;
 	}
@@ -2364,9 +2410,11 @@ static int dummy_hcd_remove (struct platform_device *pdev)
 	if (dum->ss_hcd) {
 		usb_remove_hcd(dummy_hcd_to_hcd(dum->ss_hcd));
 		usb_put_hcd(dummy_hcd_to_hcd(dum->ss_hcd));
+		cancel_work_sync(&dum->ss_hcd->conn_disc_work);
 	}
 	usb_remove_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
 	usb_put_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
+	cancel_work_sync(&dum->hs_hcd->conn_disc_work);
 	the_controller.ss_hcd = the_controller.hs_hcd = NULL;
 	return 0;
 }
-- 
1.7.3.3

--
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-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH/RFC 2/5] usb:dummy_hcd: connect/disconnect test support
@ 2011-06-16 13:31     ` Tatyana Brokhman
  0 siblings, 0 replies; 54+ messages in thread
From: Tatyana Brokhman @ 2011-06-16 13:31 UTC (permalink / raw)
  To: greg; +Cc: linux-usb, linux-arm-msm, balbi, ablay, Tatyana Brokhman, open list

This implementation adds a new proprietary device control requests (to be
handled by the dummy_hcd) that initiates a connect/disconnect sequence.
The bRequest value of the new control request is 0x52.
It is used by the user-space Unit testing application.

Signed-off-by: Tatyana Linder <tlinder@codeaurora.org>

---
 drivers/usb/gadget/dummy_hcd.c |   48 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 48 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 74b7655..7d0a6fe 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -179,6 +179,7 @@ struct dummy_hcd {
 	unsigned			active:1;
 	unsigned			old_active:1;
 	unsigned			resuming:1;
+	struct work_struct		conn_disc_work;
 };
 
 struct dummy {
@@ -1362,6 +1363,43 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
 #define Ep_Request	(USB_TYPE_STANDARD | USB_RECIP_ENDPOINT)
 #define Ep_InRequest	(Ep_Request | USB_DIR_IN)
 
+/**
+ * dummy_hcd_conn_disc_work() - performs a disconnect/connect sequence.
+ * @data: pointer to the sceduled work_struct
+ */
+static void dummy_hcd_conn_disc_work(struct work_struct *data)
+{
+	struct dummy_hcd *dum_hcd =
+		container_of(data, struct dummy_hcd, conn_disc_work);
+	int ret_val;
+
+	if (!dum_hcd->dum->driver) {
+		dev_err(dummy_dev(dum_hcd),
+			"dummy_hcd_conn_disc_work called without connected "
+			"device\n");
+		return;
+	}
+
+	dev_info(dummy_dev(dum_hcd), "disconnecting device...\n");
+	ret_val = dummy_pullup(&dum_hcd->dum->gadget, 0);
+	if (ret_val) {
+		dev_err(dummy_dev(dum_hcd), "dummy_hcd_conn_disc_work:"
+					    " couldn't disconnect device:"
+					    " ret_val=%d\n",
+				ret_val);
+		return;
+	}
+
+	dev_info(dummy_dev(dum_hcd), "re-connecting device...\n");
+	/* We have to let the hub task to update the device disconnect state */
+	msleep_interruptible(1000);
+	ret_val = dummy_pullup(&dum_hcd->dum->gadget, 1);
+	if (ret_val)
+		dev_err(dummy_dev(dum_hcd), "dummy_hcd_conn_disc_work:"
+					    " couldn't re-connect device:"
+					    " ret_val=%d\n",
+				ret_val);
+}
 
 /**
  * handle_control_request() - handles all control transfers
@@ -1534,6 +1572,10 @@ static int handle_control_request(struct dummy_hcd *dum_hcd, struct urb *urb,
 			*status = 0;
 		}
 		break;
+	case 0x52:	/* UT: Connect/disconnect the device */
+		schedule_work(&dum_hcd->conn_disc_work);
+		ret_val = 0;
+		break;
 	}
 	return ret_val;
 }
@@ -2249,6 +2291,8 @@ static int dummy_setup(struct usb_hcd *hcd)
 	if (usb_hcd_is_primary_hcd(hcd)) {
 		the_controller.hs_hcd = hcd_to_dummy_hcd(hcd);
 		the_controller.hs_hcd->dum = &the_controller;
+		INIT_WORK(&the_controller.hs_hcd->conn_disc_work,
+			  dummy_hcd_conn_disc_work);
 		/*
 		 * Mark the first roothub as being USB 2.0.
 		 * The USB 3.0 roothub will be registered later by
@@ -2259,6 +2303,8 @@ static int dummy_setup(struct usb_hcd *hcd)
 	} else {
 		the_controller.ss_hcd = hcd_to_dummy_hcd(hcd);
 		the_controller.ss_hcd->dum = &the_controller;
+		INIT_WORK(&the_controller.ss_hcd->conn_disc_work,
+			  dummy_hcd_conn_disc_work);
 		hcd->speed = HCD_USB3;
 		hcd->self.root_hub->speed = USB_SPEED_SUPER;
 	}
@@ -2364,9 +2410,11 @@ static int dummy_hcd_remove (struct platform_device *pdev)
 	if (dum->ss_hcd) {
 		usb_remove_hcd(dummy_hcd_to_hcd(dum->ss_hcd));
 		usb_put_hcd(dummy_hcd_to_hcd(dum->ss_hcd));
+		cancel_work_sync(&dum->ss_hcd->conn_disc_work);
 	}
 	usb_remove_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
 	usb_put_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
+	cancel_work_sync(&dum->hs_hcd->conn_disc_work);
 	the_controller.ss_hcd = the_controller.hs_hcd = NULL;
 	return 0;
 }
-- 
1.7.3.3

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH/RFC 3/5] usb:g_zero: bulk in/out unittest support
  2011-06-16 13:31 ` Tatyana Brokhman
@ 2011-06-16 13:31   ` Tatyana Brokhman
  -1 siblings, 0 replies; 54+ messages in thread
From: Tatyana Brokhman @ 2011-06-16 13:31 UTC (permalink / raw)
  To: greg; +Cc: linux-usb, linux-arm-msm, balbi, ablay, Tatyana Brokhman, open list

This commit adds a new vendor specific request to be handled by the
g_zero module in it's sourcesink configuration. The purpose if this
request is to update the length of the BULK transfer to a given value.
The bRequest value of the new control request is 0x5e.
It is used by the user-space Unit testing application for bulk in/out
tests.

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

---
 drivers/usb/gadget/f_sourcesink.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c
index caf2f95..d417b8a 100644
--- a/drivers/usb/gadget/f_sourcesink.c
+++ b/drivers/usb/gadget/f_sourcesink.c
@@ -70,6 +70,7 @@ static unsigned pattern;
 module_param(pattern, uint, 0);
 MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63 ");
 
+static struct f_sourcesink	*the_sourcesink;
 /*-------------------------------------------------------------------------*/
 
 static struct usb_interface_descriptor source_sink_intf = {
@@ -197,6 +198,7 @@ static void
 sourcesink_unbind(struct usb_configuration *c, struct usb_function *f)
 {
 	kfree(func_to_ss(f));
+	the_sourcesink = NULL;
 }
 
 /* optionally require specific source/sink data patterns  */
@@ -425,6 +427,7 @@ static int __init sourcesink_bind_config(struct usb_configuration *c)
 	status = usb_add_function(c, &ss->function);
 	if (status)
 		kfree(ss);
+	the_sourcesink = ss;
 	return status;
 }
 
@@ -472,6 +475,15 @@ static int sourcesink_setup(struct usb_configuration *c,
 		value = w_length;
 		break;
 
+	case 0x5e:
+		/*
+		 * Change bulk ep buffer size. buflen is the length of
+		 * the BULK transfer (req->length=buflen). Defined in g_zero.h
+		 */
+		disable_source_sink(the_sourcesink);
+		buflen = w_value;
+		value = enable_source_sink(c->cdev, the_sourcesink);
+		break;
 	default:
 unknown:
 		VDBG(c->cdev,
-- 
1.7.3.3

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH/RFC 3/5] usb:g_zero: bulk in/out unittest support
@ 2011-06-16 13:31   ` Tatyana Brokhman
  0 siblings, 0 replies; 54+ messages in thread
From: Tatyana Brokhman @ 2011-06-16 13:31 UTC (permalink / raw)
  To: greg; +Cc: linux-usb, linux-arm-msm, balbi, ablay, Tatyana Brokhman, open list

This commit adds a new vendor specific request to be handled by the
g_zero module in it's sourcesink configuration. The purpose if this
request is to update the length of the BULK transfer to a given value.
The bRequest value of the new control request is 0x5e.
It is used by the user-space Unit testing application for bulk in/out
tests.

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

---
 drivers/usb/gadget/f_sourcesink.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c
index caf2f95..d417b8a 100644
--- a/drivers/usb/gadget/f_sourcesink.c
+++ b/drivers/usb/gadget/f_sourcesink.c
@@ -70,6 +70,7 @@ static unsigned pattern;
 module_param(pattern, uint, 0);
 MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63 ");
 
+static struct f_sourcesink	*the_sourcesink;
 /*-------------------------------------------------------------------------*/
 
 static struct usb_interface_descriptor source_sink_intf = {
@@ -197,6 +198,7 @@ static void
 sourcesink_unbind(struct usb_configuration *c, struct usb_function *f)
 {
 	kfree(func_to_ss(f));
+	the_sourcesink = NULL;
 }
 
 /* optionally require specific source/sink data patterns  */
@@ -425,6 +427,7 @@ static int __init sourcesink_bind_config(struct usb_configuration *c)
 	status = usb_add_function(c, &ss->function);
 	if (status)
 		kfree(ss);
+	the_sourcesink = ss;
 	return status;
 }
 
@@ -472,6 +475,15 @@ static int sourcesink_setup(struct usb_configuration *c,
 		value = w_length;
 		break;
 
+	case 0x5e:
+		/*
+		 * Change bulk ep buffer size. buflen is the length of
+		 * the BULK transfer (req->length=buflen). Defined in g_zero.h
+		 */
+		disable_source_sink(the_sourcesink);
+		buflen = w_value;
+		value = enable_source_sink(c->cdev, the_sourcesink);
+		break;
 	default:
 unknown:
 		VDBG(c->cdev,
-- 
1.7.3.3

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH/RFC 4/5] usb:dummy_hcd: Disable single-request fifo in dummy hcd
  2011-06-16 13:31 ` Tatyana Brokhman
@ 2011-06-16 13:31     ` Tatyana Brokhman
  -1 siblings, 0 replies; 54+ messages in thread
From: Tatyana Brokhman @ 2011-06-16 13:31 UTC (permalink / raw)
  To: greg-U8xfFu+wG4EAvxtiuMwx3w
  Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, balbi-l0cyMroinI0,
	ablay-sgV2jX0FEOL9JmXXK+q4OQ, Tatyana Brokhman, open list

This is not the actual behavior of the udc, thus it's removed.

This patch is needed for several of UAS test to pass.

Signed-off-by: Tatyana Brokhman <tlinder-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

---
 drivers/usb/gadget/dummy_hcd.c |   26 +-------------------------
 1 files changed, 1 insertions(+), 25 deletions(-)

diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 7d0a6fe..41c7961 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -608,11 +608,6 @@ dummy_free_request (struct usb_ep *_ep, struct usb_request *_req)
 	kfree (req);
 }
 
-static void
-fifo_complete (struct usb_ep *ep, struct usb_request *req)
-{
-}
-
 static int
 dummy_queue (struct usb_ep *_ep, struct usb_request *_req,
 		gfp_t mem_flags)
@@ -648,26 +643,7 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req,
 	_req->actual = 0;
 	spin_lock_irqsave (&dum->lock, flags);
 
-	/* implement an emulated single-request FIFO */
-	if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) &&
-			list_empty (&dum->fifo_req.queue) &&
-			list_empty (&ep->queue) &&
-			_req->length <= FIFO_SIZE) {
-		req = &dum->fifo_req;
-		req->req = *_req;
-		req->req.buf = dum->fifo_buf;
-		memcpy (dum->fifo_buf, _req->buf, _req->length);
-		req->req.context = dum;
-		req->req.complete = fifo_complete;

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH/RFC 4/5] usb:dummy_hcd: Disable single-request fifo in dummy hcd
@ 2011-06-16 13:31     ` Tatyana Brokhman
  0 siblings, 0 replies; 54+ messages in thread
From: Tatyana Brokhman @ 2011-06-16 13:31 UTC (permalink / raw)
  To: greg; +Cc: linux-usb, linux-arm-msm, balbi, ablay, Tatyana Brokhman, open list

This is not the actual behavior of the udc, thus it's removed.

This patch is needed for several of UAS test to pass.

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

---
 drivers/usb/gadget/dummy_hcd.c |   26 +-------------------------
 1 files changed, 1 insertions(+), 25 deletions(-)

diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 7d0a6fe..41c7961 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -608,11 +608,6 @@ dummy_free_request (struct usb_ep *_ep, struct usb_request *_req)
 	kfree (req);
 }
 
-static void
-fifo_complete (struct usb_ep *ep, struct usb_request *req)
-{
-}
-
 static int
 dummy_queue (struct usb_ep *_ep, struct usb_request *_req,
 		gfp_t mem_flags)
@@ -648,26 +643,7 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req,
 	_req->actual = 0;
 	spin_lock_irqsave (&dum->lock, flags);
 
-	/* implement an emulated single-request FIFO */
-	if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) &&
-			list_empty (&dum->fifo_req.queue) &&
-			list_empty (&ep->queue) &&
-			_req->length <= FIFO_SIZE) {
-		req = &dum->fifo_req;
-		req->req = *_req;
-		req->req.buf = dum->fifo_buf;
-		memcpy (dum->fifo_buf, _req->buf, _req->length);
-		req->req.context = dum;
-		req->req.complete = fifo_complete;
-
-		list_add_tail(&req->queue, &ep->queue);
-		spin_unlock (&dum->lock);
-		_req->actual = _req->length;
-		_req->status = 0;
-		_req->complete (_ep, _req);
-		spin_lock (&dum->lock);
-	}  else
-		list_add_tail(&req->queue, &ep->queue);
+	list_add_tail(&req->queue, &ep->queue);
 	spin_unlock_irqrestore (&dum->lock, flags);
 
 	/* real hardware would likely enable transfers here, in case
-- 
1.7.3.3

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-06-16 13:31 ` Tatyana Brokhman
@ 2011-06-16 13:31   ` Tatyana Brokhman
  -1 siblings, 0 replies; 54+ messages in thread
From: Tatyana Brokhman @ 2011-06-16 13:31 UTC (permalink / raw)
  To: greg
  Cc: linux-usb, linux-arm-msm, balbi, ablay, Tatyana Brokhman,
	Amit Blay, open list

Allow user space applications such as LIBUSB, to request
streams alloc/dealloc from HCD that implements XHCI.

Signed-off-by: Amit Blay <ablay@qualcomm.com>
Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>

---
 drivers/usb/core/devio.c     |  128 +++++++++++++++++++++++++++++++++++++++++-
 include/linux/usbdevice_fs.h |    5 ++
 2 files changed, 132 insertions(+), 1 deletions(-)

diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 37518df..7e73e35 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -943,6 +943,115 @@ static int proc_clearhalt(struct dev_state *ps, void __user *arg)
 	return usb_clear_halt(ps->dev, pipe);
 }
 
+static int proc_allocstreams(struct dev_state *ps, void __user *arg)
+{
+	unsigned int ep_map;
+	int ret;
+	int intf_num;
+	struct usb_interface *intf = NULL;
+	const int max_eps = 32;
+	int max_streams = 0;
+	struct usb_host_endpoint *eps[max_eps];
+	int num_eps = 0;
+	int i;
+	unsigned int ep;
+
+	if (get_user(ep_map, (unsigned int __user *)arg))
+		return -EFAULT;
+
+	for (i = 0; i < max_eps; i++) {
+		if (ep_map & (0x1 << i)) {
+			/* Convert from i to ep address */
+			if (i < 16) /* IN EP */
+				ep = i | USB_ENDPOINT_DIR_MASK;
+			else /* OUT EP */
+				ep = (i - 16);
+
+			intf_num = findintfep(ps->dev, ep);
+			if (intf_num < 0)
+				return intf_num;
+			ret = checkintf(ps, intf_num);
+			if (ret)
+				return ret;
+			intf = usb_ifnum_to_if(ps->dev, intf_num);
+			if (!intf)
+				return -ENOENT;
+
+			if (ep & USB_ENDPOINT_DIR_MASK)
+				eps[num_eps] = ps->dev->ep_in[ep &
+					USB_ENDPOINT_NUMBER_MASK];
+			else
+				eps[num_eps] = ps->dev->ep_out[ep &
+					USB_ENDPOINT_NUMBER_MASK];
+
+			if (!max_streams)
+				max_streams = USB_SS_MAX_STREAMS(
+					eps[num_eps]->ss_ep_comp.bmAttributes);
+
+			num_eps++;
+		}
+	}
+
+	if (!intf || !max_streams)
+		return -ENOENT;
+
+	ret = usb_alloc_streams(intf, eps, num_eps, max_streams, GFP_KERNEL);
+	if (ret > 0)
+		return 0;
+	return ret;
+}
+
+static int proc_freestreams(struct dev_state *ps, void __user *arg)
+{
+	unsigned int ep_map;
+	int ret;
+	int intf_num;
+	struct usb_interface *intf = NULL;
+	const int max_eps = 32;
+	struct usb_host_endpoint *eps[max_eps];
+	int num_eps = 0;
+	int i;
+	unsigned int ep;
+
+	if (get_user(ep_map, (unsigned int __user *)arg))
+		return -EFAULT;
+
+	for (i = 0; i < max_eps; i++) {
+		if (ep_map & (0x1 << i)) {
+			/* Convert from i to ep address */
+			if (i < 16) /* IN EP */
+				ep = i | USB_ENDPOINT_DIR_MASK;
+			else /* OUT EP */
+				ep = (i - 16);
+
+			intf_num = findintfep(ps->dev, ep);
+			if (intf_num < 0)
+				return intf_num;
+			ret = checkintf(ps, intf_num);
+			if (ret)
+				return ret;
+			intf = usb_ifnum_to_if(ps->dev, intf_num);
+			if (!intf)
+				return -ENOENT;
+
+			if (ep & USB_ENDPOINT_DIR_MASK)
+				eps[num_eps] = ps->dev->ep_in[ep &
+					USB_ENDPOINT_NUMBER_MASK];
+			else
+				eps[num_eps] = ps->dev->ep_out[ep &
+					USB_ENDPOINT_NUMBER_MASK];
+
+			num_eps++;
+		}
+	}
+
+	if (!intf)
+		return -ENOENT;
+
+	usb_free_streams(intf, eps, num_eps, GFP_KERNEL);
+	return 0;
+}
+
 static int proc_getdriver(struct dev_state *ps, void __user *arg)
 {
 	struct usbdevfs_getdriver gd;
@@ -1236,6 +1345,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 		u |= URB_NO_INTERRUPT;
 	as->urb->transfer_flags = u;
 
+	as->urb->stream_id = (uurb->type == USBDEVFS_URB_TYPE_BULK) ?
+		uurb->stream_id : 0;
 	as->urb->transfer_buffer_length = uurb->buffer_length;
 	as->urb->setup_packet = (unsigned char *)dr;
 	as->urb->start_frame = uurb->start_frame;
@@ -1491,7 +1602,8 @@ static int get_urb32(struct usbdevfs_urb *kurb,
 	    __get_user(kurb->start_frame, &uurb->start_frame) ||
 	    __get_user(kurb->number_of_packets, &uurb->number_of_packets) ||
 	    __get_user(kurb->error_count, &uurb->error_count) ||
-	    __get_user(kurb->signr, &uurb->signr))
+	    __get_user(kurb->signr, &uurb->signr) ||
+	    __get_user(kurb->stream_id, &uurb->stream_id))
 		return -EFAULT;
 
 	if (__get_user(uptr, &uurb->buffer))
@@ -1795,6 +1907,20 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
 			inode->i_mtime = CURRENT_TIME;
 		break;
 
+	case USBDEVFS_ALLOC_STREAMS:
+		snoop(&dev->dev, "%s: ALLOC_STREAMS\n", __func__);
+		ret = proc_allocstreams(ps, p);
+		if (ret >= 0)
+			inode->i_mtime = CURRENT_TIME;
+		break;
+
+	case USBDEVFS_FREE_STREAMS:
+		snoop(&dev->dev, "%s: FREE_STREAMS\n", __func__);
+		ret = proc_freestreams(ps, p);
+		if (ret >= 0)
+			inode->i_mtime = CURRENT_TIME;
+		break;
+
 	case USBDEVFS_GETDRIVER:
 		snoop(&dev->dev, "%s: GETDRIVER\n", __func__);
 		ret = proc_getdriver(ps, p);
diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
index 15591d2..133c216 100644
--- a/include/linux/usbdevice_fs.h
+++ b/include/linux/usbdevice_fs.h
@@ -108,6 +108,7 @@ struct usbdevfs_urb {
 				  or 0 if none should be sent. */
 	void __user *usercontext;
 	struct usbdevfs_iso_packet_desc iso_frame_desc[0];
+	unsigned int stream_id;
 };
 
 /* ioctls for talking directly to drivers */
@@ -165,6 +166,7 @@ struct usbdevfs_urb32 {
 	compat_uint_t signr;
 	compat_caddr_t usercontext; /* unused */
 	struct usbdevfs_iso_packet_desc iso_frame_desc[0];
+	compat_uint_t stream_id;
 };
 
 struct usbdevfs_ioctl32 {
@@ -204,4 +206,7 @@ struct usbdevfs_ioctl32 {
 #define USBDEVFS_CONNECT           _IO('U', 23)
 #define USBDEVFS_CLAIM_PORT        _IOR('U', 24, unsigned int)
 #define USBDEVFS_RELEASE_PORT      _IOR('U', 25, unsigned int)
+#define USBDEVFS_ALLOC_STREAMS     _IOR('U', 26, unsigned int)
+#define USBDEVFS_FREE_STREAMS      _IOR('U', 27, unsigned int)
+
 #endif /* _LINUX_USBDEVICE_FS_H */
-- 
1.7.3.3

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
@ 2011-06-16 13:31   ` Tatyana Brokhman
  0 siblings, 0 replies; 54+ messages in thread
From: Tatyana Brokhman @ 2011-06-16 13:31 UTC (permalink / raw)
  To: greg
  Cc: linux-usb, linux-arm-msm, balbi, ablay, Tatyana Brokhman,
	Amit Blay, open list

Allow user space applications such as LIBUSB, to request
streams alloc/dealloc from HCD that implements XHCI.

Signed-off-by: Amit Blay <ablay@qualcomm.com>
Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>

---
 drivers/usb/core/devio.c     |  128 +++++++++++++++++++++++++++++++++++++++++-
 include/linux/usbdevice_fs.h |    5 ++
 2 files changed, 132 insertions(+), 1 deletions(-)

diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 37518df..7e73e35 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -943,6 +943,115 @@ static int proc_clearhalt(struct dev_state *ps, void __user *arg)
 	return usb_clear_halt(ps->dev, pipe);
 }
 
+static int proc_allocstreams(struct dev_state *ps, void __user *arg)
+{
+	unsigned int ep_map;
+	int ret;
+	int intf_num;
+	struct usb_interface *intf = NULL;
+	const int max_eps = 32;
+	int max_streams = 0;
+	struct usb_host_endpoint *eps[max_eps];
+	int num_eps = 0;
+	int i;
+	unsigned int ep;
+
+	if (get_user(ep_map, (unsigned int __user *)arg))
+		return -EFAULT;
+
+	for (i = 0; i < max_eps; i++) {
+		if (ep_map & (0x1 << i)) {
+			/* Convert from i to ep address */
+			if (i < 16) /* IN EP */
+				ep = i | USB_ENDPOINT_DIR_MASK;
+			else /* OUT EP */
+				ep = (i - 16);
+
+			intf_num = findintfep(ps->dev, ep);
+			if (intf_num < 0)
+				return intf_num;
+			ret = checkintf(ps, intf_num);
+			if (ret)
+				return ret;
+			intf = usb_ifnum_to_if(ps->dev, intf_num);
+			if (!intf)
+				return -ENOENT;
+
+			if (ep & USB_ENDPOINT_DIR_MASK)
+				eps[num_eps] = ps->dev->ep_in[ep &
+					USB_ENDPOINT_NUMBER_MASK];
+			else
+				eps[num_eps] = ps->dev->ep_out[ep &
+					USB_ENDPOINT_NUMBER_MASK];
+
+			if (!max_streams)
+				max_streams = USB_SS_MAX_STREAMS(
+					eps[num_eps]->ss_ep_comp.bmAttributes);
+
+			num_eps++;
+		}
+	}
+
+	if (!intf || !max_streams)
+		return -ENOENT;
+
+	ret = usb_alloc_streams(intf, eps, num_eps, max_streams, GFP_KERNEL);
+	if (ret > 0)
+		return 0;
+	return ret;
+}
+
+static int proc_freestreams(struct dev_state *ps, void __user *arg)
+{
+	unsigned int ep_map;
+	int ret;
+	int intf_num;
+	struct usb_interface *intf = NULL;
+	const int max_eps = 32;
+	struct usb_host_endpoint *eps[max_eps];
+	int num_eps = 0;
+	int i;
+	unsigned int ep;
+
+	if (get_user(ep_map, (unsigned int __user *)arg))
+		return -EFAULT;
+
+	for (i = 0; i < max_eps; i++) {
+		if (ep_map & (0x1 << i)) {
+			/* Convert from i to ep address */
+			if (i < 16) /* IN EP */
+				ep = i | USB_ENDPOINT_DIR_MASK;
+			else /* OUT EP */
+				ep = (i - 16);
+
+			intf_num = findintfep(ps->dev, ep);
+			if (intf_num < 0)
+				return intf_num;
+			ret = checkintf(ps, intf_num);
+			if (ret)
+				return ret;
+			intf = usb_ifnum_to_if(ps->dev, intf_num);
+			if (!intf)
+				return -ENOENT;
+
+			if (ep & USB_ENDPOINT_DIR_MASK)
+				eps[num_eps] = ps->dev->ep_in[ep &
+					USB_ENDPOINT_NUMBER_MASK];
+			else
+				eps[num_eps] = ps->dev->ep_out[ep &
+					USB_ENDPOINT_NUMBER_MASK];
+
+			num_eps++;
+		}
+	}
+
+	if (!intf)
+		return -ENOENT;
+
+	usb_free_streams(intf, eps, num_eps, GFP_KERNEL);
+	return 0;
+}
+
 static int proc_getdriver(struct dev_state *ps, void __user *arg)
 {
 	struct usbdevfs_getdriver gd;
@@ -1236,6 +1345,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 		u |= URB_NO_INTERRUPT;
 	as->urb->transfer_flags = u;
 
+	as->urb->stream_id = (uurb->type == USBDEVFS_URB_TYPE_BULK) ?
+		uurb->stream_id : 0;
 	as->urb->transfer_buffer_length = uurb->buffer_length;
 	as->urb->setup_packet = (unsigned char *)dr;
 	as->urb->start_frame = uurb->start_frame;
@@ -1491,7 +1602,8 @@ static int get_urb32(struct usbdevfs_urb *kurb,
 	    __get_user(kurb->start_frame, &uurb->start_frame) ||
 	    __get_user(kurb->number_of_packets, &uurb->number_of_packets) ||
 	    __get_user(kurb->error_count, &uurb->error_count) ||
-	    __get_user(kurb->signr, &uurb->signr))
+	    __get_user(kurb->signr, &uurb->signr) ||
+	    __get_user(kurb->stream_id, &uurb->stream_id))
 		return -EFAULT;
 
 	if (__get_user(uptr, &uurb->buffer))
@@ -1795,6 +1907,20 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
 			inode->i_mtime = CURRENT_TIME;
 		break;
 
+	case USBDEVFS_ALLOC_STREAMS:
+		snoop(&dev->dev, "%s: ALLOC_STREAMS\n", __func__);
+		ret = proc_allocstreams(ps, p);
+		if (ret >= 0)
+			inode->i_mtime = CURRENT_TIME;
+		break;
+
+	case USBDEVFS_FREE_STREAMS:
+		snoop(&dev->dev, "%s: FREE_STREAMS\n", __func__);
+		ret = proc_freestreams(ps, p);
+		if (ret >= 0)
+			inode->i_mtime = CURRENT_TIME;
+		break;
+
 	case USBDEVFS_GETDRIVER:
 		snoop(&dev->dev, "%s: GETDRIVER\n", __func__);
 		ret = proc_getdriver(ps, p);
diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
index 15591d2..133c216 100644
--- a/include/linux/usbdevice_fs.h
+++ b/include/linux/usbdevice_fs.h
@@ -108,6 +108,7 @@ struct usbdevfs_urb {
 				  or 0 if none should be sent. */
 	void __user *usercontext;
 	struct usbdevfs_iso_packet_desc iso_frame_desc[0];
+	unsigned int stream_id;
 };
 
 /* ioctls for talking directly to drivers */
@@ -165,6 +166,7 @@ struct usbdevfs_urb32 {
 	compat_uint_t signr;
 	compat_caddr_t usercontext; /* unused */
 	struct usbdevfs_iso_packet_desc iso_frame_desc[0];
+	compat_uint_t stream_id;
 };
 
 struct usbdevfs_ioctl32 {
@@ -204,4 +206,7 @@ struct usbdevfs_ioctl32 {
 #define USBDEVFS_CONNECT           _IO('U', 23)
 #define USBDEVFS_CLAIM_PORT        _IOR('U', 24, unsigned int)
 #define USBDEVFS_RELEASE_PORT      _IOR('U', 25, unsigned int)
+#define USBDEVFS_ALLOC_STREAMS     _IOR('U', 26, unsigned int)
+#define USBDEVFS_FREE_STREAMS      _IOR('U', 27, unsigned int)
+
 #endif /* _LINUX_USBDEVICE_FS_H */
-- 
1.7.3.3

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 2/5] usb:dummy_hcd: connect/disconnect test support
  2011-06-16 13:31     ` Tatyana Brokhman
@ 2011-06-16 15:06       ` Alan Stern
  -1 siblings, 0 replies; 54+ messages in thread
From: Alan Stern @ 2011-06-16 15:06 UTC (permalink / raw)
  To: Tatyana Brokhman; +Cc: greg, linux-usb, linux-arm-msm, balbi, ablay, open list

On Thu, 16 Jun 2011, Tatyana Brokhman wrote:

> This implementation adds a new proprietary device control requests (to be
> handled by the dummy_hcd) that initiates a connect/disconnect sequence.
> The bRequest value of the new control request is 0x52.
> It is used by the user-space Unit testing application.

This is not a bad idea.  On the other hand, it is slightly peculiar -- 
it you're testing with real UDC hardware, you would do the 
disconnect/reconnect sequence by hand (unplug and replug the USB 
cable), not in software.

> Signed-off-by: Tatyana Linder <tlinder@codeaurora.org>
> 
> ---
>  drivers/usb/gadget/dummy_hcd.c |   48 ++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 48 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
> index 74b7655..7d0a6fe 100644
> --- a/drivers/usb/gadget/dummy_hcd.c
> +++ b/drivers/usb/gadget/dummy_hcd.c
> @@ -179,6 +179,7 @@ struct dummy_hcd {
>  	unsigned			active:1;
>  	unsigned			old_active:1;
>  	unsigned			resuming:1;
> +	struct work_struct		conn_disc_work;
>  };
>  
>  struct dummy {
> @@ -1362,6 +1363,43 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
>  #define Ep_Request	(USB_TYPE_STANDARD | USB_RECIP_ENDPOINT)
>  #define Ep_InRequest	(Ep_Request | USB_DIR_IN)
>  
> +/**
> + * dummy_hcd_conn_disc_work() - performs a disconnect/connect sequence.
> + * @data: pointer to the sceduled work_struct

Spelling error.

> + */
> +static void dummy_hcd_conn_disc_work(struct work_struct *data)
> +{
> +	struct dummy_hcd *dum_hcd =
> +		container_of(data, struct dummy_hcd, conn_disc_work);
> +	int ret_val;
> +
> +	if (!dum_hcd->dum->driver) {
> +		dev_err(dummy_dev(dum_hcd),
> +			"dummy_hcd_conn_disc_work called without connected "
> +			"device\n");
> +		return;
> +	}
> +
> +	dev_info(dummy_dev(dum_hcd), "disconnecting device...\n");
> +	ret_val = dummy_pullup(&dum_hcd->dum->gadget, 0);
> +	if (ret_val) {
> +		dev_err(dummy_dev(dum_hcd), "dummy_hcd_conn_disc_work:"
> +					    " couldn't disconnect device:"
> +					    " ret_val=%d\n",
> +				ret_val);
> +		return;
> +	}
> +
> +	dev_info(dummy_dev(dum_hcd), "re-connecting device...\n");
> +	/* We have to let the hub task to update the device disconnect state */
> +	msleep_interruptible(1000);

These two lines should come before the "re-connecting" message.

> +	ret_val = dummy_pullup(&dum_hcd->dum->gadget, 1);
> +	if (ret_val)
> +		dev_err(dummy_dev(dum_hcd), "dummy_hcd_conn_disc_work:"
> +					    " couldn't re-connect device:"
> +					    " ret_val=%d\n",
> +				ret_val);
> +}
>  
>  /**
>   * handle_control_request() - handles all control transfers
> @@ -1534,6 +1572,10 @@ static int handle_control_request(struct dummy_hcd *dum_hcd, struct urb *urb,
>  			*status = 0;
>  		}
>  		break;
> +	case 0x52:	/* UT: Connect/disconnect the device */

Please define a symbolic constant for this.  Also, nobody is going to 
know what "UT:" is supposed to mean.

The rest is okay.

Alan Stern

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 2/5] usb:dummy_hcd: connect/disconnect test support
@ 2011-06-16 15:06       ` Alan Stern
  0 siblings, 0 replies; 54+ messages in thread
From: Alan Stern @ 2011-06-16 15:06 UTC (permalink / raw)
  To: Tatyana Brokhman; +Cc: greg, linux-usb, linux-arm-msm, balbi, ablay, open list

On Thu, 16 Jun 2011, Tatyana Brokhman wrote:

> This implementation adds a new proprietary device control requests (to be
> handled by the dummy_hcd) that initiates a connect/disconnect sequence.
> The bRequest value of the new control request is 0x52.
> It is used by the user-space Unit testing application.

This is not a bad idea.  On the other hand, it is slightly peculiar -- 
it you're testing with real UDC hardware, you would do the 
disconnect/reconnect sequence by hand (unplug and replug the USB 
cable), not in software.

> Signed-off-by: Tatyana Linder <tlinder@codeaurora.org>
> 
> ---
>  drivers/usb/gadget/dummy_hcd.c |   48 ++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 48 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
> index 74b7655..7d0a6fe 100644
> --- a/drivers/usb/gadget/dummy_hcd.c
> +++ b/drivers/usb/gadget/dummy_hcd.c
> @@ -179,6 +179,7 @@ struct dummy_hcd {
>  	unsigned			active:1;
>  	unsigned			old_active:1;
>  	unsigned			resuming:1;
> +	struct work_struct		conn_disc_work;
>  };
>  
>  struct dummy {
> @@ -1362,6 +1363,43 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
>  #define Ep_Request	(USB_TYPE_STANDARD | USB_RECIP_ENDPOINT)
>  #define Ep_InRequest	(Ep_Request | USB_DIR_IN)
>  
> +/**
> + * dummy_hcd_conn_disc_work() - performs a disconnect/connect sequence.
> + * @data: pointer to the sceduled work_struct

Spelling error.

> + */
> +static void dummy_hcd_conn_disc_work(struct work_struct *data)
> +{
> +	struct dummy_hcd *dum_hcd =
> +		container_of(data, struct dummy_hcd, conn_disc_work);
> +	int ret_val;
> +
> +	if (!dum_hcd->dum->driver) {
> +		dev_err(dummy_dev(dum_hcd),
> +			"dummy_hcd_conn_disc_work called without connected "
> +			"device\n");
> +		return;
> +	}
> +
> +	dev_info(dummy_dev(dum_hcd), "disconnecting device...\n");
> +	ret_val = dummy_pullup(&dum_hcd->dum->gadget, 0);
> +	if (ret_val) {
> +		dev_err(dummy_dev(dum_hcd), "dummy_hcd_conn_disc_work:"
> +					    " couldn't disconnect device:"
> +					    " ret_val=%d\n",
> +				ret_val);
> +		return;
> +	}
> +
> +	dev_info(dummy_dev(dum_hcd), "re-connecting device...\n");
> +	/* We have to let the hub task to update the device disconnect state */
> +	msleep_interruptible(1000);

These two lines should come before the "re-connecting" message.

> +	ret_val = dummy_pullup(&dum_hcd->dum->gadget, 1);
> +	if (ret_val)
> +		dev_err(dummy_dev(dum_hcd), "dummy_hcd_conn_disc_work:"
> +					    " couldn't re-connect device:"
> +					    " ret_val=%d\n",
> +				ret_val);
> +}
>  
>  /**
>   * handle_control_request() - handles all control transfers
> @@ -1534,6 +1572,10 @@ static int handle_control_request(struct dummy_hcd *dum_hcd, struct urb *urb,
>  			*status = 0;
>  		}
>  		break;
> +	case 0x52:	/* UT: Connect/disconnect the device */

Please define a symbolic constant for this.  Also, nobody is going to 
know what "UT:" is supposed to mean.

The rest is okay.

Alan Stern


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 4/5] usb:dummy_hcd: Disable single-request fifo in dummy hcd
  2011-06-16 13:31     ` Tatyana Brokhman
@ 2011-06-16 15:09       ` Alan Stern
  -1 siblings, 0 replies; 54+ messages in thread
From: Alan Stern @ 2011-06-16 15:09 UTC (permalink / raw)
  To: Tatyana Brokhman; +Cc: greg, linux-usb, linux-arm-msm, balbi, ablay, open list

On Thu, 16 Jun 2011, Tatyana Brokhman wrote:

> This is not the actual behavior of the udc, thus it's removed.

I don't understand.  What UDC are you talking about?  This _is_ the 
actual behavior of the net2280 (depending on which endpoint you're 
looking at and how the device is configured).

> This patch is needed for several of UAS test to pass.

Then the tests are broken.  NAK.

Alan Stern

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 4/5] usb:dummy_hcd: Disable single-request fifo in dummy hcd
@ 2011-06-16 15:09       ` Alan Stern
  0 siblings, 0 replies; 54+ messages in thread
From: Alan Stern @ 2011-06-16 15:09 UTC (permalink / raw)
  To: Tatyana Brokhman; +Cc: greg, linux-usb, linux-arm-msm, balbi, ablay, open list

On Thu, 16 Jun 2011, Tatyana Brokhman wrote:

> This is not the actual behavior of the udc, thus it's removed.

I don't understand.  What UDC are you talking about?  This _is_ the 
actual behavior of the net2280 (depending on which endpoint you're 
looking at and how the device is configured).

> This patch is needed for several of UAS test to pass.

Then the tests are broken.  NAK.

Alan Stern


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 2/5] usb:dummy_hcd: connect/disconnect test support
  2011-06-16 13:31     ` Tatyana Brokhman
@ 2011-06-16 15:17       ` Alan Stern
  -1 siblings, 0 replies; 54+ messages in thread
From: Alan Stern @ 2011-06-16 15:17 UTC (permalink / raw)
  To: Tatyana Brokhman; +Cc: greg, linux-usb, linux-arm-msm, balbi, ablay, open list

On Thu, 16 Jun 2011, Tatyana Brokhman wrote:

> This implementation adds a new proprietary device control requests (to be
> handled by the dummy_hcd) that initiates a connect/disconnect sequence.
> The bRequest value of the new control request is 0x52.
> It is used by the user-space Unit testing application.
> 
> Signed-off-by: Tatyana Linder <tlinder@codeaurora.org>

> @@ -1534,6 +1572,10 @@ static int handle_control_request(struct dummy_hcd *dum_hcd, struct urb *urb,
>  			*status = 0;
>  		}
>  		break;
> +	case 0x52:	/* UT: Connect/disconnect the device */
> +		schedule_work(&dum_hcd->conn_disc_work);
> +		ret_val = 0;
> +		break;
>  	}
>  	return ret_val;
>  }

I forgot to mention...  You need to test setup->bRequestType.

Alan Stern

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 2/5] usb:dummy_hcd: connect/disconnect test support
@ 2011-06-16 15:17       ` Alan Stern
  0 siblings, 0 replies; 54+ messages in thread
From: Alan Stern @ 2011-06-16 15:17 UTC (permalink / raw)
  To: Tatyana Brokhman; +Cc: greg, linux-usb, linux-arm-msm, balbi, ablay, open list

On Thu, 16 Jun 2011, Tatyana Brokhman wrote:

> This implementation adds a new proprietary device control requests (to be
> handled by the dummy_hcd) that initiates a connect/disconnect sequence.
> The bRequest value of the new control request is 0x52.
> It is used by the user-space Unit testing application.
> 
> Signed-off-by: Tatyana Linder <tlinder@codeaurora.org>

> @@ -1534,6 +1572,10 @@ static int handle_control_request(struct dummy_hcd *dum_hcd, struct urb *urb,
>  			*status = 0;
>  		}
>  		break;
> +	case 0x52:	/* UT: Connect/disconnect the device */
> +		schedule_work(&dum_hcd->conn_disc_work);
> +		ret_val = 0;
> +		break;
>  	}
>  	return ret_val;
>  }

I forgot to mention...  You need to test setup->bRequestType.

Alan Stern


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-06-16 13:31   ` Tatyana Brokhman
@ 2011-06-16 15:20       ` Alan Stern
  -1 siblings, 0 replies; 54+ messages in thread
From: Alan Stern @ 2011-06-16 15:20 UTC (permalink / raw)
  To: Tatyana Brokhman
  Cc: greg-U8xfFu+wG4EAvxtiuMwx3w, linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, balbi-l0cyMroinI0,
	ablay-sgV2jX0FEOL9JmXXK+q4OQ, Amit Blay, open list

On Thu, 16 Jun 2011, Tatyana Brokhman wrote:

> Allow user space applications such as LIBUSB, to request
> streams alloc/dealloc from HCD that implements XHCI.
> 
> Signed-off-by: Amit Blay <ablay-zC7DfRvBq/JWk0Htik3J/w@public.gmane.org>
> Signed-off-by: Tatyana Brokhman <tlinder-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

...

> diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
> index 15591d2..133c216 100644
> --- a/include/linux/usbdevice_fs.h
> +++ b/include/linux/usbdevice_fs.h
> @@ -108,6 +108,7 @@ struct usbdevfs_urb {
>  				  or 0 if none should be sent. */
>  	void __user *usercontext;
>  	struct usbdevfs_iso_packet_desc iso_frame_desc[0];
> +	unsigned int stream_id;
>  };
>  
>  /* ioctls for talking directly to drivers */
> @@ -165,6 +166,7 @@ struct usbdevfs_urb32 {
>  	compat_uint_t signr;
>  	compat_caddr_t usercontext; /* unused */
>  	struct usbdevfs_iso_packet_desc iso_frame_desc[0];
> +	compat_uint_t stream_id;
>  };

It would be nice if we could do this, but we can't.  We are not allowed 
to change an established ABI.  Every copy of libusb would have to be 
rebuilt.

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
@ 2011-06-16 15:20       ` Alan Stern
  0 siblings, 0 replies; 54+ messages in thread
From: Alan Stern @ 2011-06-16 15:20 UTC (permalink / raw)
  To: Tatyana Brokhman
  Cc: greg, linux-usb, linux-arm-msm, balbi, ablay, Amit Blay, open list

On Thu, 16 Jun 2011, Tatyana Brokhman wrote:

> Allow user space applications such as LIBUSB, to request
> streams alloc/dealloc from HCD that implements XHCI.
> 
> Signed-off-by: Amit Blay <ablay@qualcomm.com>
> Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>

...

> diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
> index 15591d2..133c216 100644
> --- a/include/linux/usbdevice_fs.h
> +++ b/include/linux/usbdevice_fs.h
> @@ -108,6 +108,7 @@ struct usbdevfs_urb {
>  				  or 0 if none should be sent. */
>  	void __user *usercontext;
>  	struct usbdevfs_iso_packet_desc iso_frame_desc[0];
> +	unsigned int stream_id;
>  };
>  
>  /* ioctls for talking directly to drivers */
> @@ -165,6 +166,7 @@ struct usbdevfs_urb32 {
>  	compat_uint_t signr;
>  	compat_caddr_t usercontext; /* unused */
>  	struct usbdevfs_iso_packet_desc iso_frame_desc[0];
> +	compat_uint_t stream_id;
>  };

It would be nice if we could do this, but we can't.  We are not allowed 
to change an established ABI.  Every copy of libusb would have to be 
rebuilt.

Alan Stern


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 2/5] usb:dummy_hcd: connect/disconnect test support
  2011-06-16 15:06       ` Alan Stern
  (?)
@ 2011-06-16 16:16       ` Felipe Balbi
  2011-06-16 17:06           ` Alan Stern
  -1 siblings, 1 reply; 54+ messages in thread
From: Felipe Balbi @ 2011-06-16 16:16 UTC (permalink / raw)
  To: Alan Stern
  Cc: Tatyana Brokhman, greg, linux-usb, linux-arm-msm, balbi, ablay,
	open list

[-- Attachment #1: Type: text/plain, Size: 1094 bytes --]

Hi,

On Thu, Jun 16, 2011 at 11:06:47AM -0400, Alan Stern wrote:
> On Thu, 16 Jun 2011, Tatyana Brokhman wrote:
> 
> > This implementation adds a new proprietary device control requests (to be
> > handled by the dummy_hcd) that initiates a connect/disconnect sequence.
> > The bRequest value of the new control request is 0x52.
> > It is used by the user-space Unit testing application.
> 
> This is not a bad idea.  On the other hand, it is slightly peculiar -- 
> it you're testing with real UDC hardware, you would do the 
> disconnect/reconnect sequence by hand (unplug and replug the USB 
> cable), not in software.

actually, this is quite useful. Specially for the controllers which
_can_ do soft-connect by toggling data pullups. I would rather have
these sort of thing maybe in composite.c, so that we can build tests
with all gadget drivers/controllers, not only dummy_hcd.

That said, I think now it's not the time to fiddle too much with these
details right now. So best to keep this in dummy_hcd until we know the
test tools are actually good.

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 2/5] usb:dummy_hcd: connect/disconnect test support
  2011-06-16 13:31     ` Tatyana Brokhman
                       ` (2 preceding siblings ...)
  (?)
@ 2011-06-16 16:18     ` Felipe Balbi
  -1 siblings, 0 replies; 54+ messages in thread
From: Felipe Balbi @ 2011-06-16 16:18 UTC (permalink / raw)
  To: Tatyana Brokhman; +Cc: greg, linux-usb, linux-arm-msm, balbi, ablay, open list

[-- Attachment #1: Type: text/plain, Size: 1682 bytes --]

Hi,

On Thu, Jun 16, 2011 at 04:31:04PM +0300, Tatyana Brokhman wrote:
> @@ -1362,6 +1363,43 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
>  #define Ep_Request	(USB_TYPE_STANDARD | USB_RECIP_ENDPOINT)
>  #define Ep_InRequest	(Ep_Request | USB_DIR_IN)
>  
> +/**
> + * dummy_hcd_conn_disc_work() - performs a disconnect/connect sequence.
> + * @data: pointer to the sceduled work_struct
> + */
> +static void dummy_hcd_conn_disc_work(struct work_struct *data)
> +{
> +	struct dummy_hcd *dum_hcd =
> +		container_of(data, struct dummy_hcd, conn_disc_work);
> +	int ret_val;
> +
> +	if (!dum_hcd->dum->driver) {
> +		dev_err(dummy_dev(dum_hcd),
> +			"dummy_hcd_conn_disc_work called without connected "
> +			"device\n");
> +		return;
> +	}
> +
> +	dev_info(dummy_dev(dum_hcd), "disconnecting device...\n");
> +	ret_val = dummy_pullup(&dum_hcd->dum->gadget, 0);
> +	if (ret_val) {
> +		dev_err(dummy_dev(dum_hcd), "dummy_hcd_conn_disc_work:"
> +					    " couldn't disconnect device:"
> +					    " ret_val=%d\n",
> +				ret_val);
> +		return;
> +	}
> +
> +	dev_info(dummy_dev(dum_hcd), "re-connecting device...\n");
> +	/* We have to let the hub task to update the device disconnect state */
> +	msleep_interruptible(1000);
> +	ret_val = dummy_pullup(&dum_hcd->dum->gadget, 1);
> +	if (ret_val)
> +		dev_err(dummy_dev(dum_hcd), "dummy_hcd_conn_disc_work:"
> +					    " couldn't re-connect device:"
> +					    " ret_val=%d\n",
> +				ret_val);

this print is quite ugly. How about something like:

	dev_err(dummy_dev(dum_hcd), "%s: couldn't re-connect --> %d\n",
		__func__, ret_val);

???

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 3/5] usb:g_zero: bulk in/out unittest support
  2011-06-16 13:31   ` Tatyana Brokhman
  (?)
@ 2011-06-16 16:25   ` Felipe Balbi
  -1 siblings, 0 replies; 54+ messages in thread
From: Felipe Balbi @ 2011-06-16 16:25 UTC (permalink / raw)
  To: Tatyana Brokhman; +Cc: greg, linux-usb, linux-arm-msm, balbi, ablay, open list

[-- Attachment #1: Type: text/plain, Size: 2431 bytes --]

Hi,

On Thu, Jun 16, 2011 at 04:31:05PM +0300, Tatyana Brokhman wrote:
> This commit adds a new vendor specific request to be handled by the
> g_zero module in it's sourcesink configuration. The purpose if this
> request is to update the length of the BULK transfer to a given value.
> The bRequest value of the new control request is 0x5e.
> It is used by the user-space Unit testing application for bulk in/out
> tests.
> 
> Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>
> 
> ---
>  drivers/usb/gadget/f_sourcesink.c |   12 ++++++++++++
>  1 files changed, 12 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c
> index caf2f95..d417b8a 100644
> --- a/drivers/usb/gadget/f_sourcesink.c
> +++ b/drivers/usb/gadget/f_sourcesink.c
> @@ -70,6 +70,7 @@ static unsigned pattern;
>  module_param(pattern, uint, 0);
>  MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63 ");
>  
> +static struct f_sourcesink	*the_sourcesink;

this is a big no-no. f_*.c should always be able to be instantiated as
many times as we need.

>  /*-------------------------------------------------------------------------*/
>  
>  static struct usb_interface_descriptor source_sink_intf = {
> @@ -197,6 +198,7 @@ static void
>  sourcesink_unbind(struct usb_configuration *c, struct usb_function *f)
>  {
>  	kfree(func_to_ss(f));
> +	the_sourcesink = NULL;
>  }
>  
>  /* optionally require specific source/sink data patterns  */
> @@ -425,6 +427,7 @@ static int __init sourcesink_bind_config(struct usb_configuration *c)
>  	status = usb_add_function(c, &ss->function);
>  	if (status)
>  		kfree(ss);
> +	the_sourcesink = ss;
>  	return status;
>  }
>  
> @@ -472,6 +475,15 @@ static int sourcesink_setup(struct usb_configuration *c,
>  		value = w_length;
>  		break;
>  
> +	case 0x5e:
> +		/*
> +		 * Change bulk ep buffer size. buflen is the length of
> +		 * the BULK transfer (req->length=buflen). Defined in g_zero.h
> +		 */
> +		disable_source_sink(the_sourcesink);
> +		buflen = w_value;
> +		value = enable_source_sink(c->cdev, the_sourcesink);
> +		break;
>  	default:

I think this request, should be handled by the f_sourcesink interface.
Meaning you'd need to introduce another f_sourcesink_setup(); to be
added to the function, rather then the configuration.

Please change that.

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-06-16 13:31   ` Tatyana Brokhman
  (?)
  (?)
@ 2011-06-16 16:28   ` Felipe Balbi
  2011-06-16 18:21     ` Greg KH
  -1 siblings, 1 reply; 54+ messages in thread
From: Felipe Balbi @ 2011-06-16 16:28 UTC (permalink / raw)
  To: Tatyana Brokhman
  Cc: greg, linux-usb, linux-arm-msm, balbi, ablay, Amit Blay, open list

[-- Attachment #1: Type: text/plain, Size: 484 bytes --]

On Thu, Jun 16, 2011 at 04:31:07PM +0300, Tatyana Brokhman wrote:
> Allow user space applications such as LIBUSB, to request
> streams alloc/dealloc from HCD that implements XHCI.
> 
> Signed-off-by: Amit Blay <ablay@qualcomm.com>
> Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>

other than what Alan said, this needs major splitting. This patch is too
big. First we need to discuss the ABI details with the guys at
libusb-devel, then we implement.

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 2/5] usb:dummy_hcd: connect/disconnect test support
  2011-06-16 16:16       ` Felipe Balbi
@ 2011-06-16 17:06           ` Alan Stern
  0 siblings, 0 replies; 54+ messages in thread
From: Alan Stern @ 2011-06-16 17:06 UTC (permalink / raw)
  To: Felipe Balbi
  Cc: Tatyana Brokhman, greg, linux-usb, linux-arm-msm, ablay, open list

On Thu, 16 Jun 2011, Felipe Balbi wrote:

> Hi,
> 
> On Thu, Jun 16, 2011 at 11:06:47AM -0400, Alan Stern wrote:
> > On Thu, 16 Jun 2011, Tatyana Brokhman wrote:
> > 
> > > This implementation adds a new proprietary device control requests (to be
> > > handled by the dummy_hcd) that initiates a connect/disconnect sequence.
> > > The bRequest value of the new control request is 0x52.
> > > It is used by the user-space Unit testing application.
> > 
> > This is not a bad idea.  On the other hand, it is slightly peculiar -- 
> > it you're testing with real UDC hardware, you would do the 
> > disconnect/reconnect sequence by hand (unplug and replug the USB 
> > cable), not in software.
> 
> actually, this is quite useful. Specially for the controllers which
> _can_ do soft-connect by toggling data pullups. I would rather have
> these sort of thing maybe in composite.c, so that we can build tests
> with all gadget drivers/controllers, not only dummy_hcd.

It sounds like you don't understand the point of this patch.  It allows
the _host_ to control the pullup settings.

Alan Stern

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 2/5] usb:dummy_hcd: connect/disconnect test support
@ 2011-06-16 17:06           ` Alan Stern
  0 siblings, 0 replies; 54+ messages in thread
From: Alan Stern @ 2011-06-16 17:06 UTC (permalink / raw)
  To: Felipe Balbi
  Cc: Tatyana Brokhman, greg, linux-usb, linux-arm-msm, ablay, open list

On Thu, 16 Jun 2011, Felipe Balbi wrote:

> Hi,
> 
> On Thu, Jun 16, 2011 at 11:06:47AM -0400, Alan Stern wrote:
> > On Thu, 16 Jun 2011, Tatyana Brokhman wrote:
> > 
> > > This implementation adds a new proprietary device control requests (to be
> > > handled by the dummy_hcd) that initiates a connect/disconnect sequence.
> > > The bRequest value of the new control request is 0x52.
> > > It is used by the user-space Unit testing application.
> > 
> > This is not a bad idea.  On the other hand, it is slightly peculiar -- 
> > it you're testing with real UDC hardware, you would do the 
> > disconnect/reconnect sequence by hand (unplug and replug the USB 
> > cable), not in software.
> 
> actually, this is quite useful. Specially for the controllers which
> _can_ do soft-connect by toggling data pullups. I would rather have
> these sort of thing maybe in composite.c, so that we can build tests
> with all gadget drivers/controllers, not only dummy_hcd.

It sounds like you don't understand the point of this patch.  It allows
the _host_ to control the pullup settings.

Alan Stern


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 2/5] usb:dummy_hcd: connect/disconnect test support
  2011-06-16 17:06           ` Alan Stern
@ 2011-06-16 17:19             ` Alan Stern
  -1 siblings, 0 replies; 54+ messages in thread
From: Alan Stern @ 2011-06-16 17:19 UTC (permalink / raw)
  To: Felipe Balbi
  Cc: Tatyana Brokhman, greg, linux-usb, linux-arm-msm, ablay, open list

On Thu, 16 Jun 2011, Alan Stern wrote:

> On Thu, 16 Jun 2011, Felipe Balbi wrote:
> 
> > Hi,
> > 
> > On Thu, Jun 16, 2011 at 11:06:47AM -0400, Alan Stern wrote:
> > > On Thu, 16 Jun 2011, Tatyana Brokhman wrote:
> > > 
> > > > This implementation adds a new proprietary device control requests (to be
> > > > handled by the dummy_hcd) that initiates a connect/disconnect sequence.
> > > > The bRequest value of the new control request is 0x52.
> > > > It is used by the user-space Unit testing application.
> > > 
> > > This is not a bad idea.  On the other hand, it is slightly peculiar -- 
> > > it you're testing with real UDC hardware, you would do the 
> > > disconnect/reconnect sequence by hand (unplug and replug the USB 
> > > cable), not in software.
> > 
> > actually, this is quite useful. Specially for the controllers which
> > _can_ do soft-connect by toggling data pullups. I would rather have
> > these sort of thing maybe in composite.c, so that we can build tests
> > with all gadget drivers/controllers, not only dummy_hcd.
> 
> It sounds like you don't understand the point of this patch.  It allows
> the _host_ to control the pullup settings.

Sorry, the misunderstanding was mine -- I didn't grasp what you were 
suggesting.

Yes, something like this could be useful in composite.c.  It could be 
defined as a vendor-specific request with the device as the recipient.  

One problem with making it special for dummy-hcd is that it would 
prevent people from testing gadget drivers that want to use the same 
bRequest value to mean something different.  Putting it in composite.c 
would force all function drivers to know about it.

Alan Stern

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 2/5] usb:dummy_hcd: connect/disconnect test support
@ 2011-06-16 17:19             ` Alan Stern
  0 siblings, 0 replies; 54+ messages in thread
From: Alan Stern @ 2011-06-16 17:19 UTC (permalink / raw)
  To: Felipe Balbi
  Cc: Tatyana Brokhman, greg, linux-usb, linux-arm-msm, ablay, open list

On Thu, 16 Jun 2011, Alan Stern wrote:

> On Thu, 16 Jun 2011, Felipe Balbi wrote:
> 
> > Hi,
> > 
> > On Thu, Jun 16, 2011 at 11:06:47AM -0400, Alan Stern wrote:
> > > On Thu, 16 Jun 2011, Tatyana Brokhman wrote:
> > > 
> > > > This implementation adds a new proprietary device control requests (to be
> > > > handled by the dummy_hcd) that initiates a connect/disconnect sequence.
> > > > The bRequest value of the new control request is 0x52.
> > > > It is used by the user-space Unit testing application.
> > > 
> > > This is not a bad idea.  On the other hand, it is slightly peculiar -- 
> > > it you're testing with real UDC hardware, you would do the 
> > > disconnect/reconnect sequence by hand (unplug and replug the USB 
> > > cable), not in software.
> > 
> > actually, this is quite useful. Specially for the controllers which
> > _can_ do soft-connect by toggling data pullups. I would rather have
> > these sort of thing maybe in composite.c, so that we can build tests
> > with all gadget drivers/controllers, not only dummy_hcd.
> 
> It sounds like you don't understand the point of this patch.  It allows
> the _host_ to control the pullup settings.

Sorry, the misunderstanding was mine -- I didn't grasp what you were 
suggesting.

Yes, something like this could be useful in composite.c.  It could be 
defined as a vendor-specific request with the device as the recipient.  

One problem with making it special for dummy-hcd is that it would 
prevent people from testing gadget drivers that want to use the same 
bRequest value to mean something different.  Putting it in composite.c 
would force all function drivers to know about it.

Alan Stern


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-06-16 16:28   ` Felipe Balbi
@ 2011-06-16 18:21     ` Greg KH
  2011-06-17  8:55         ` ablay
  0 siblings, 1 reply; 54+ messages in thread
From: Greg KH @ 2011-06-16 18:21 UTC (permalink / raw)
  To: Felipe Balbi
  Cc: Tatyana Brokhman, linux-usb, linux-arm-msm, ablay, Amit Blay, open list

On Thu, Jun 16, 2011 at 07:28:40PM +0300, Felipe Balbi wrote:
> On Thu, Jun 16, 2011 at 04:31:07PM +0300, Tatyana Brokhman wrote:
> > Allow user space applications such as LIBUSB, to request
> > streams alloc/dealloc from HCD that implements XHCI.
> > 
> > Signed-off-by: Amit Blay <ablay@qualcomm.com>
> > Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>
> 
> other than what Alan said, this needs major splitting. This patch is too
> big. First we need to discuss the ABI details with the guys at
> libusb-devel, then we implement.

No, we don't break the abi, but rather, create a new one for streams,
and then we can work on adding them to libusb, which should be quite
easy when done.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-06-16 18:21     ` Greg KH
@ 2011-06-17  8:55         ` ablay
  0 siblings, 0 replies; 54+ messages in thread
From: ablay @ 2011-06-17  8:55 UTC (permalink / raw)
  To: Greg KH
  Cc: Felipe Balbi, Tatyana Brokhman, linux-usb, linux-arm-msm, open list

> On Thu, Jun 16, 2011 at 07:28:40PM +0300, Felipe Balbi wrote:
>> On Thu, Jun 16, 2011 at 04:31:07PM +0300, Tatyana Brokhman wrote:
>> > Allow user space applications such as LIBUSB, to request
>> > streams alloc/dealloc from HCD that implements XHCI.
>> >
>> > Signed-off-by: Amit Blay <ablay@qualcomm.com>
>> > Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>
>>
>> other than what Alan said, this needs major splitting. This patch is too
>> big. First we need to discuss the ABI details with the guys at
>> libusb-devel, then we implement.
>
> No, we don't break the abi, but rather, create a new one for streams,
> and then we can work on adding them to libusb, which should be quite
> easy when done.
>
> thanks,
>
> greg k-h
>

My name is Amit Blay, I'm working with Tatyana Brokhman, I originally
created this patch. I want to make sure I understand the solution:

We will create a new IOCTL, i.e., USBDEVFS_SUBMITURB_SS. This IOCTL will
pass new URB structure, usbdevfs_urb_ss, which will hold the "legacy" URB
and in addition the stream_id. libusb will be able to use the new ABI
whenever SuperSpeed streams are required.

Is this correct?

Thanks,
Amit Blay,
---
Sent by an consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to  devio.c
@ 2011-06-17  8:55         ` ablay
  0 siblings, 0 replies; 54+ messages in thread
From: ablay @ 2011-06-17  8:55 UTC (permalink / raw)
  To: Greg KH
  Cc: Felipe Balbi, Tatyana Brokhman, linux-usb, linux-arm-msm, open list

> On Thu, Jun 16, 2011 at 07:28:40PM +0300, Felipe Balbi wrote:
>> On Thu, Jun 16, 2011 at 04:31:07PM +0300, Tatyana Brokhman wrote:
>> > Allow user space applications such as LIBUSB, to request
>> > streams alloc/dealloc from HCD that implements XHCI.
>> >
>> > Signed-off-by: Amit Blay <ablay@qualcomm.com>
>> > Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>
>>
>> other than what Alan said, this needs major splitting. This patch is too
>> big. First we need to discuss the ABI details with the guys at
>> libusb-devel, then we implement.
>
> No, we don't break the abi, but rather, create a new one for streams,
> and then we can work on adding them to libusb, which should be quite
> easy when done.
>
> thanks,
>
> greg k-h
>

My name is Amit Blay, I'm working with Tatyana Brokhman, I originally
created this patch. I want to make sure I understand the solution:

We will create a new IOCTL, i.e., USBDEVFS_SUBMITURB_SS. This IOCTL will
pass new URB structure, usbdevfs_urb_ss, which will hold the "legacy" URB
and in addition the stream_id. libusb will be able to use the new ABI
whenever SuperSpeed streams are required.

Is this correct?

Thanks,
Amit Blay,
---
Sent by an consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.



^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-06-17  8:55         ` ablay
@ 2011-06-17 14:35           ` Alan Stern
  -1 siblings, 0 replies; 54+ messages in thread
From: Alan Stern @ 2011-06-17 14:35 UTC (permalink / raw)
  To: ablay
  Cc: Greg KH, Felipe Balbi, Tatyana Brokhman, linux-usb,
	linux-arm-msm, open list

On Fri, 17 Jun 2011 ablay@codeaurora.org wrote:

> My name is Amit Blay, I'm working with Tatyana Brokhman, I originally
> created this patch. I want to make sure I understand the solution:
> 
> We will create a new IOCTL, i.e., USBDEVFS_SUBMITURB_SS. This IOCTL will
> pass new URB structure, usbdevfs_urb_ss, which will hold the "legacy" URB
> and in addition the stream_id. libusb will be able to use the new ABI
> whenever SuperSpeed streams are required.
> 
> Is this correct?

This probably should be USBDEVFS_SUBMITURB_STREAM, since it is necesary
only for URBs that use bulk streaming rather than for all SuperSpeed
URBs.

Alan Stern

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to  devio.c
@ 2011-06-17 14:35           ` Alan Stern
  0 siblings, 0 replies; 54+ messages in thread
From: Alan Stern @ 2011-06-17 14:35 UTC (permalink / raw)
  To: ablay
  Cc: Greg KH, Felipe Balbi, Tatyana Brokhman, linux-usb,
	linux-arm-msm, open list

On Fri, 17 Jun 2011 ablay@codeaurora.org wrote:

> My name is Amit Blay, I'm working with Tatyana Brokhman, I originally
> created this patch. I want to make sure I understand the solution:
> 
> We will create a new IOCTL, i.e., USBDEVFS_SUBMITURB_SS. This IOCTL will
> pass new URB structure, usbdevfs_urb_ss, which will hold the "legacy" URB
> and in addition the stream_id. libusb will be able to use the new ABI
> whenever SuperSpeed streams are required.
> 
> Is this correct?

This probably should be USBDEVFS_SUBMITURB_STREAM, since it is necesary
only for URBs that use bulk streaming rather than for all SuperSpeed
URBs.

Alan Stern


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-06-16 13:31   ` Tatyana Brokhman
@ 2011-06-30 17:45       ` Sarah Sharp
  -1 siblings, 0 replies; 54+ messages in thread
From: Sarah Sharp @ 2011-06-30 17:45 UTC (permalink / raw)
  To: Tatyana Brokhman
  Cc: greg-U8xfFu+wG4EAvxtiuMwx3w, linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, balbi-l0cyMroinI0,
	ablay-sgV2jX0FEOL9JmXXK+q4OQ, Amit Blay, open list

On Thu, Jun 16, 2011 at 04:31:07PM +0300, Tatyana Brokhman wrote:
> Allow user space applications such as LIBUSB, to request
> streams alloc/dealloc from HCD that implements XHCI.

Hi Tatyana,

Will this patch be used to create a userspace UAS driver, or are you
envisioning other ways userspace might use streams?  I ask because I
can't think of another usage of streams in currently available devices.

This patch is good to have, but I can't imagine that you'll get good
performance if you're trying to create a userspace UAS device.  After
all, usbfs does some fairly stupid things, performance wise, like using
kmalloc to allocate its URB buffers instead of usb_alloc_coherent, which
may cause the userspace buffer to be copied twice if the kmalloc memory
is not DMA'able.

usbfs probably could be changed to pin the user pages and the scatter
gather URB interface to try and avoid even one copy, but that's a
performance enhancement I haven't had time to play around with.  :)

> Signed-off-by: Amit Blay <ablay-zC7DfRvBq/JWk0Htik3J/w@public.gmane.org>
> Signed-off-by: Tatyana Brokhman <tlinder-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> 
> ---
>  drivers/usb/core/devio.c     |  128 +++++++++++++++++++++++++++++++++++++++++-
>  include/linux/usbdevice_fs.h |    5 ++
>  2 files changed, 132 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
> index 37518df..7e73e35 100644
> --- a/drivers/usb/core/devio.c
> +++ b/drivers/usb/core/devio.c
> @@ -943,6 +943,115 @@ static int proc_clearhalt(struct dev_state *ps, void __user *arg)
>  	return usb_clear_halt(ps->dev, pipe);
>  }
>  
> +static int proc_allocstreams(struct dev_state *ps, void __user *arg)

It looks like userspace doesn't have a way to specify the number of
streams USBFS needs to allocate.  Not all userspace applications are
going to want to use all available streams (especially if the device
advertises the max of 65533).

You probably also need a way to communicate back to userspace how many
streams were actually allocated.  The program could choose to free
streams if it doesn't get the amount it expected.  (Also, it needs to
know how many streams are available, so it can set the stream ID.)

> +{
> +	unsigned int ep_map;
> +	int ret;
> +	int intf_num;
> +	struct usb_interface *intf = NULL;
> +	const int max_eps = 32;
> +	int max_streams = 0;
> +	struct usb_host_endpoint *eps[max_eps];
> +	int num_eps = 0;
> +	int i;
> +	unsigned int ep;
> +
> +	if (get_user(ep_map, (unsigned int __user *)arg))
> +		return -EFAULT;
> +
> +	for (i = 0; i < max_eps; i++) {
> +		if (ep_map & (0x1 << i)) {
> +			/* Convert from i to ep address */
> +			if (i < 16) /* IN EP */
> +				ep = i | USB_ENDPOINT_DIR_MASK;
> +			else /* OUT EP */
> +				ep = (i - 16);
> +
> +			intf_num = findintfep(ps->dev, ep);
> +			if (intf_num < 0)
> +				return intf_num;
> +			ret = checkintf(ps, intf_num);
> +			if (ret)
> +				return ret;
> +			intf = usb_ifnum_to_if(ps->dev, intf_num);
> +			if (!intf)
> +				return -ENOENT;
> +
> +			if (ep & USB_ENDPOINT_DIR_MASK)
> +				eps[num_eps] = ps->dev->ep_in[ep &
> +					USB_ENDPOINT_NUMBER_MASK];
> +			else
> +				eps[num_eps] = ps->dev->ep_out[ep &
> +					USB_ENDPOINT_NUMBER_MASK];
> +
> +			if (!max_streams)
> +				max_streams = USB_SS_MAX_STREAMS(
> +					eps[num_eps]->ss_ep_comp.bmAttributes);
> +

So you're just taking the max_streams from the first endpoint that has
streams?  What if other endpoints have varying numbers of max streams?
(A well-designed device probably wouldn't, but the spec doesn't disallow
it.)

All this checking is a bit redundant anyway.  The xHCI driver already
loops over the endpoints that you give it, checking for the minimum
number of reported maximum streams.  It will also make sure that isn't
more than the host controller supports.  So you might as well just ask
for the maximum possible number of streams (65533).

> +			num_eps++;
> +		}
> +	}
> +
> +	if (!intf || !max_streams)
> +		return -ENOENT;
> +
> +	ret = usb_alloc_streams(intf, eps, num_eps, max_streams, GFP_KERNEL);
> +	if (ret > 0)
> +		return 0;
> +	return ret;
> +}
> +


What if you have endpoints on an interface that don't support streams?
It looks like you're passing the xHCI driver all endpoints on a
particular interface.  The call to usb_alloc_streams() will fail if any
of those endpoints don't support streams.

So it seems like you also need a way for userspace to specify which
endpoints get streams, and which endpoints have streams freed.  I will
have to check, but I think the call to usb_free_streams() will fail if
any of the endpoints don't actually have streams enabled.

Sarah Sharp
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
@ 2011-06-30 17:45       ` Sarah Sharp
  0 siblings, 0 replies; 54+ messages in thread
From: Sarah Sharp @ 2011-06-30 17:45 UTC (permalink / raw)
  To: Tatyana Brokhman
  Cc: greg, linux-usb, linux-arm-msm, balbi, ablay, Amit Blay, open list

On Thu, Jun 16, 2011 at 04:31:07PM +0300, Tatyana Brokhman wrote:
> Allow user space applications such as LIBUSB, to request
> streams alloc/dealloc from HCD that implements XHCI.

Hi Tatyana,

Will this patch be used to create a userspace UAS driver, or are you
envisioning other ways userspace might use streams?  I ask because I
can't think of another usage of streams in currently available devices.

This patch is good to have, but I can't imagine that you'll get good
performance if you're trying to create a userspace UAS device.  After
all, usbfs does some fairly stupid things, performance wise, like using
kmalloc to allocate its URB buffers instead of usb_alloc_coherent, which
may cause the userspace buffer to be copied twice if the kmalloc memory
is not DMA'able.

usbfs probably could be changed to pin the user pages and the scatter
gather URB interface to try and avoid even one copy, but that's a
performance enhancement I haven't had time to play around with.  :)

> Signed-off-by: Amit Blay <ablay@qualcomm.com>
> Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>
> 
> ---
>  drivers/usb/core/devio.c     |  128 +++++++++++++++++++++++++++++++++++++++++-
>  include/linux/usbdevice_fs.h |    5 ++
>  2 files changed, 132 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
> index 37518df..7e73e35 100644
> --- a/drivers/usb/core/devio.c
> +++ b/drivers/usb/core/devio.c
> @@ -943,6 +943,115 @@ static int proc_clearhalt(struct dev_state *ps, void __user *arg)
>  	return usb_clear_halt(ps->dev, pipe);
>  }
>  
> +static int proc_allocstreams(struct dev_state *ps, void __user *arg)

It looks like userspace doesn't have a way to specify the number of
streams USBFS needs to allocate.  Not all userspace applications are
going to want to use all available streams (especially if the device
advertises the max of 65533).

You probably also need a way to communicate back to userspace how many
streams were actually allocated.  The program could choose to free
streams if it doesn't get the amount it expected.  (Also, it needs to
know how many streams are available, so it can set the stream ID.)

> +{
> +	unsigned int ep_map;
> +	int ret;
> +	int intf_num;
> +	struct usb_interface *intf = NULL;
> +	const int max_eps = 32;
> +	int max_streams = 0;
> +	struct usb_host_endpoint *eps[max_eps];
> +	int num_eps = 0;
> +	int i;
> +	unsigned int ep;
> +
> +	if (get_user(ep_map, (unsigned int __user *)arg))
> +		return -EFAULT;
> +
> +	for (i = 0; i < max_eps; i++) {
> +		if (ep_map & (0x1 << i)) {
> +			/* Convert from i to ep address */
> +			if (i < 16) /* IN EP */
> +				ep = i | USB_ENDPOINT_DIR_MASK;
> +			else /* OUT EP */
> +				ep = (i - 16);
> +
> +			intf_num = findintfep(ps->dev, ep);
> +			if (intf_num < 0)
> +				return intf_num;
> +			ret = checkintf(ps, intf_num);
> +			if (ret)
> +				return ret;
> +			intf = usb_ifnum_to_if(ps->dev, intf_num);
> +			if (!intf)
> +				return -ENOENT;
> +
> +			if (ep & USB_ENDPOINT_DIR_MASK)
> +				eps[num_eps] = ps->dev->ep_in[ep &
> +					USB_ENDPOINT_NUMBER_MASK];
> +			else
> +				eps[num_eps] = ps->dev->ep_out[ep &
> +					USB_ENDPOINT_NUMBER_MASK];
> +
> +			if (!max_streams)
> +				max_streams = USB_SS_MAX_STREAMS(
> +					eps[num_eps]->ss_ep_comp.bmAttributes);
> +

So you're just taking the max_streams from the first endpoint that has
streams?  What if other endpoints have varying numbers of max streams?
(A well-designed device probably wouldn't, but the spec doesn't disallow
it.)

All this checking is a bit redundant anyway.  The xHCI driver already
loops over the endpoints that you give it, checking for the minimum
number of reported maximum streams.  It will also make sure that isn't
more than the host controller supports.  So you might as well just ask
for the maximum possible number of streams (65533).

> +			num_eps++;
> +		}
> +	}
> +
> +	if (!intf || !max_streams)
> +		return -ENOENT;
> +
> +	ret = usb_alloc_streams(intf, eps, num_eps, max_streams, GFP_KERNEL);
> +	if (ret > 0)
> +		return 0;
> +	return ret;
> +}
> +


What if you have endpoints on an interface that don't support streams?
It looks like you're passing the xHCI driver all endpoints on a
particular interface.  The call to usb_alloc_streams() will fail if any
of those endpoints don't support streams.

So it seems like you also need a way for userspace to specify which
endpoints get streams, and which endpoints have streams freed.  I will
have to check, but I think the call to usb_free_streams() will fail if
any of the endpoints don't actually have streams enabled.

Sarah Sharp

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-06-30 17:45       ` Sarah Sharp
@ 2011-06-30 18:39         ` William Gulland
  -1 siblings, 0 replies; 54+ messages in thread
From: William Gulland @ 2011-06-30 18:39 UTC (permalink / raw)
  To: Sarah Sharp
  Cc: greg, linux-usb, linux-arm-msm, balbi, ablay, Amit Blay,
	open list, Tatyana Brokhman

I haven't had a chance to really look into this yet, but we use usbfs and will want to use streams from userspace (from a VM we've connected a USB3 device to).

William

----- Original Message -----
From: "Sarah Sharp" <sarah.a.sharp@linux.intel.com>
To: "Tatyana Brokhman" <tlinder@codeaurora.org>
Cc: greg@kroah.com, linux-usb@vger.kernel.org, linux-arm-msm@vger.kernel.org, balbi@ti.com, ablay@codeaurora.org, "Amit Blay" <ablay@qualcomm.com>, "open list" <linux-kernel@vger.kernel.org>
Sent: Thursday, June 30, 2011 10:45:38 AM
Subject: Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c

On Thu, Jun 16, 2011 at 04:31:07PM +0300, Tatyana Brokhman wrote:
> Allow user space applications such as LIBUSB, to request
> streams alloc/dealloc from HCD that implements XHCI.

Hi Tatyana,

Will this patch be used to create a userspace UAS driver, or are you
envisioning other ways userspace might use streams?  I ask because I
can't think of another usage of streams in currently available devices.

This patch is good to have, but I can't imagine that you'll get good
performance if you're trying to create a userspace UAS device.  After
all, usbfs does some fairly stupid things, performance wise, like using
kmalloc to allocate its URB buffers instead of usb_alloc_coherent, which
may cause the userspace buffer to be copied twice if the kmalloc memory
is not DMA'able.

usbfs probably could be changed to pin the user pages and the scatter
gather URB interface to try and avoid even one copy, but that's a
performance enhancement I haven't had time to play around with.  :)

> Signed-off-by: Amit Blay <ablay@qualcomm.com>
> Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>
> 
> ---
>  drivers/usb/core/devio.c     |  128 +++++++++++++++++++++++++++++++++++++++++-
>  include/linux/usbdevice_fs.h |    5 ++
>  2 files changed, 132 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
> index 37518df..7e73e35 100644
> --- a/drivers/usb/core/devio.c
> +++ b/drivers/usb/core/devio.c
> @@ -943,6 +943,115 @@ static int proc_clearhalt(struct dev_state *ps, void __user *arg)
>  	return usb_clear_halt(ps->dev, pipe);
>  }
>  
> +static int proc_allocstreams(struct dev_state *ps, void __user *arg)

It looks like userspace doesn't have a way to specify the number of
streams USBFS needs to allocate.  Not all userspace applications are
going to want to use all available streams (especially if the device
advertises the max of 65533).

You probably also need a way to communicate back to userspace how many
streams were actually allocated.  The program could choose to free
streams if it doesn't get the amount it expected.  (Also, it needs to
know how many streams are available, so it can set the stream ID.)

> +{
> +	unsigned int ep_map;
> +	int ret;
> +	int intf_num;
> +	struct usb_interface *intf = NULL;
> +	const int max_eps = 32;
> +	int max_streams = 0;
> +	struct usb_host_endpoint *eps[max_eps];
> +	int num_eps = 0;
> +	int i;
> +	unsigned int ep;
> +
> +	if (get_user(ep_map, (unsigned int __user *)arg))
> +		return -EFAULT;
> +
> +	for (i = 0; i < max_eps; i++) {
> +		if (ep_map & (0x1 << i)) {
> +			/* Convert from i to ep address */
> +			if (i < 16) /* IN EP */
> +				ep = i | USB_ENDPOINT_DIR_MASK;
> +			else /* OUT EP */
> +				ep = (i - 16);
> +
> +			intf_num = findintfep(ps->dev, ep);
> +			if (intf_num < 0)
> +				return intf_num;
> +			ret = checkintf(ps, intf_num);
> +			if (ret)
> +				return ret;
> +			intf = usb_ifnum_to_if(ps->dev, intf_num);
> +			if (!intf)
> +				return -ENOENT;
> +
> +			if (ep & USB_ENDPOINT_DIR_MASK)
> +				eps[num_eps] = ps->dev->ep_in[ep &
> +					USB_ENDPOINT_NUMBER_MASK];
> +			else
> +				eps[num_eps] = ps->dev->ep_out[ep &
> +					USB_ENDPOINT_NUMBER_MASK];
> +
> +			if (!max_streams)
> +				max_streams = USB_SS_MAX_STREAMS(
> +					eps[num_eps]->ss_ep_comp.bmAttributes);
> +

So you're just taking the max_streams from the first endpoint that has
streams?  What if other endpoints have varying numbers of max streams?
(A well-designed device probably wouldn't, but the spec doesn't disallow
it.)

All this checking is a bit redundant anyway.  The xHCI driver already
loops over the endpoints that you give it, checking for the minimum
number of reported maximum streams.  It will also make sure that isn't
more than the host controller supports.  So you might as well just ask
for the maximum possible number of streams (65533).

> +			num_eps++;
> +		}
> +	}
> +
> +	if (!intf || !max_streams)
> +		return -ENOENT;
> +
> +	ret = usb_alloc_streams(intf, eps, num_eps, max_streams, GFP_KERNEL);
> +	if (ret > 0)
> +		return 0;
> +	return ret;
> +}
> +


What if you have endpoints on an interface that don't support streams?
It looks like you're passing the xHCI driver all endpoints on a
particular interface.  The call to usb_alloc_streams() will fail if any
of those endpoints don't support streams.

So it seems like you also need a way for userspace to specify which
endpoints get streams, and which endpoints have streams freed.  I will
have to check, but I think the call to usb_free_streams() will fail if
any of the endpoints don't actually have streams enabled.

Sarah Sharp

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
@ 2011-06-30 18:39         ` William Gulland
  0 siblings, 0 replies; 54+ messages in thread
From: William Gulland @ 2011-06-30 18:39 UTC (permalink / raw)
  To: Sarah Sharp
  Cc: greg, linux-usb, linux-arm-msm, balbi, ablay, Amit Blay,
	open list, Tatyana Brokhman

I haven't had a chance to really look into this yet, but we use usbfs and will want to use streams from userspace (from a VM we've connected a USB3 device to).

William

----- Original Message -----
From: "Sarah Sharp" <sarah.a.sharp@linux.intel.com>
To: "Tatyana Brokhman" <tlinder@codeaurora.org>
Cc: greg@kroah.com, linux-usb@vger.kernel.org, linux-arm-msm@vger.kernel.org, balbi@ti.com, ablay@codeaurora.org, "Amit Blay" <ablay@qualcomm.com>, "open list" <linux-kernel@vger.kernel.org>
Sent: Thursday, June 30, 2011 10:45:38 AM
Subject: Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c

On Thu, Jun 16, 2011 at 04:31:07PM +0300, Tatyana Brokhman wrote:
> Allow user space applications such as LIBUSB, to request
> streams alloc/dealloc from HCD that implements XHCI.

Hi Tatyana,

Will this patch be used to create a userspace UAS driver, or are you
envisioning other ways userspace might use streams?  I ask because I
can't think of another usage of streams in currently available devices.

This patch is good to have, but I can't imagine that you'll get good
performance if you're trying to create a userspace UAS device.  After
all, usbfs does some fairly stupid things, performance wise, like using
kmalloc to allocate its URB buffers instead of usb_alloc_coherent, which
may cause the userspace buffer to be copied twice if the kmalloc memory
is not DMA'able.

usbfs probably could be changed to pin the user pages and the scatter
gather URB interface to try and avoid even one copy, but that's a
performance enhancement I haven't had time to play around with.  :)

> Signed-off-by: Amit Blay <ablay@qualcomm.com>
> Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>
> 
> ---
>  drivers/usb/core/devio.c     |  128 +++++++++++++++++++++++++++++++++++++++++-
>  include/linux/usbdevice_fs.h |    5 ++
>  2 files changed, 132 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
> index 37518df..7e73e35 100644
> --- a/drivers/usb/core/devio.c
> +++ b/drivers/usb/core/devio.c
> @@ -943,6 +943,115 @@ static int proc_clearhalt(struct dev_state *ps, void __user *arg)
>  	return usb_clear_halt(ps->dev, pipe);
>  }
>  
> +static int proc_allocstreams(struct dev_state *ps, void __user *arg)

It looks like userspace doesn't have a way to specify the number of
streams USBFS needs to allocate.  Not all userspace applications are
going to want to use all available streams (especially if the device
advertises the max of 65533).

You probably also need a way to communicate back to userspace how many
streams were actually allocated.  The program could choose to free
streams if it doesn't get the amount it expected.  (Also, it needs to
know how many streams are available, so it can set the stream ID.)

> +{
> +	unsigned int ep_map;
> +	int ret;
> +	int intf_num;
> +	struct usb_interface *intf = NULL;
> +	const int max_eps = 32;
> +	int max_streams = 0;
> +	struct usb_host_endpoint *eps[max_eps];
> +	int num_eps = 0;
> +	int i;
> +	unsigned int ep;
> +
> +	if (get_user(ep_map, (unsigned int __user *)arg))
> +		return -EFAULT;
> +
> +	for (i = 0; i < max_eps; i++) {
> +		if (ep_map & (0x1 << i)) {
> +			/* Convert from i to ep address */
> +			if (i < 16) /* IN EP */
> +				ep = i | USB_ENDPOINT_DIR_MASK;
> +			else /* OUT EP */
> +				ep = (i - 16);
> +
> +			intf_num = findintfep(ps->dev, ep);
> +			if (intf_num < 0)
> +				return intf_num;
> +			ret = checkintf(ps, intf_num);
> +			if (ret)
> +				return ret;
> +			intf = usb_ifnum_to_if(ps->dev, intf_num);
> +			if (!intf)
> +				return -ENOENT;
> +
> +			if (ep & USB_ENDPOINT_DIR_MASK)
> +				eps[num_eps] = ps->dev->ep_in[ep &
> +					USB_ENDPOINT_NUMBER_MASK];
> +			else
> +				eps[num_eps] = ps->dev->ep_out[ep &
> +					USB_ENDPOINT_NUMBER_MASK];
> +
> +			if (!max_streams)
> +				max_streams = USB_SS_MAX_STREAMS(
> +					eps[num_eps]->ss_ep_comp.bmAttributes);
> +

So you're just taking the max_streams from the first endpoint that has
streams?  What if other endpoints have varying numbers of max streams?
(A well-designed device probably wouldn't, but the spec doesn't disallow
it.)

All this checking is a bit redundant anyway.  The xHCI driver already
loops over the endpoints that you give it, checking for the minimum
number of reported maximum streams.  It will also make sure that isn't
more than the host controller supports.  So you might as well just ask
for the maximum possible number of streams (65533).

> +			num_eps++;
> +		}
> +	}
> +
> +	if (!intf || !max_streams)
> +		return -ENOENT;
> +
> +	ret = usb_alloc_streams(intf, eps, num_eps, max_streams, GFP_KERNEL);
> +	if (ret > 0)
> +		return 0;
> +	return ret;
> +}
> +


What if you have endpoints on an interface that don't support streams?
It looks like you're passing the xHCI driver all endpoints on a
particular interface.  The call to usb_alloc_streams() will fail if any
of those endpoints don't support streams.

So it seems like you also need a way for userspace to specify which
endpoints get streams, and which endpoints have streams freed.  I will
have to check, but I think the call to usb_free_streams() will fail if
any of the endpoints don't actually have streams enabled.

Sarah Sharp
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* RE: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-06-30 17:45       ` Sarah Sharp
@ 2011-06-30 18:41         ` Tanya Brokhman
  -1 siblings, 0 replies; 54+ messages in thread
From: Tanya Brokhman @ 2011-06-30 18:41 UTC (permalink / raw)
  To: 'Sarah Sharp'
  Cc: greg, linux-usb, linux-arm-msm, balbi, ablay, 'open list'

Hi Sarah,

> Will this patch be used to create a userspace UAS driver, or are you
> envisioning other ways userspace might use streams?  I ask because I
> can't think of another usage of streams in currently available devices.
> 

No, this patch isn't used for UAS driver. It's used by us only for several
tests that we implemented in the user space unittests framework we released
with this patch. We used this FW to test our superspeed support
implementation and the UAS gadget driver. It's a userspace application that
uses Google test and libusb.
That's the only reason we need this patch at the moment.
But in any case, due to the comments we got on it from Greg/Alan/Felipe this
patch is rewritten at the moment by its original author Amit Blay
(ablay@codeaurora.org). He'll post a new version of it once he's done.


Thanks,
Tanya Brokhman
---
Sent by an consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 54+ messages in thread

* RE: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
@ 2011-06-30 18:41         ` Tanya Brokhman
  0 siblings, 0 replies; 54+ messages in thread
From: Tanya Brokhman @ 2011-06-30 18:41 UTC (permalink / raw)
  To: 'Sarah Sharp'
  Cc: greg, linux-usb, linux-arm-msm, balbi, ablay, 'open list'

Hi Sarah,

> Will this patch be used to create a userspace UAS driver, or are you
> envisioning other ways userspace might use streams?  I ask because I
> can't think of another usage of streams in currently available devices.
> 

No, this patch isn't used for UAS driver. It's used by us only for several
tests that we implemented in the user space unittests framework we released
with this patch. We used this FW to test our superspeed support
implementation and the UAS gadget driver. It's a userspace application that
uses Google test and libusb.
That's the only reason we need this patch at the moment.
But in any case, due to the comments we got on it from Greg/Alan/Felipe this
patch is rewritten at the moment by its original author Amit Blay
(ablay@codeaurora.org). He'll post a new version of it once he's done.


Thanks,
Tanya Brokhman
---
Sent by an consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.





^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-06-30 17:45       ` Sarah Sharp
@ 2011-07-19  9:12         ` Amit Blay
  -1 siblings, 0 replies; 54+ messages in thread
From: Amit Blay @ 2011-07-19  9:12 UTC (permalink / raw)
  To: Sarah Sharp
  Cc: Tatyana Brokhman, greg-U8xfFu+wG4EAvxtiuMwx3w,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, balbi-l0cyMroinI0,
	ablay-sgV2jX0FEOL9JmXXK+q4OQ, Amit Blay, open list

Hi Sarah,

I apologize for the delay responding to the thread. Thanks for your
comments. I would like to continue and fix the previous patch according to
the comments.
Also, I would like to split this patch, and implement the actual usage of
streams for bulk EP transfers (passing the stream ID with the URB) to a
different patch.

>
> It looks like userspace doesn't have a way to specify the number of
> streams USBFS needs to allocate.  Not all userspace applications are

> You probably also need a way to communicate back to userspace how many
> streams were actually allocated.  The program could choose to free

> So you're just taking the max_streams from the first endpoint that has
> streams?  What if other endpoints have varying numbers of max streams?

> What if you have endpoints on an interface that don't support streams?

> So it seems like you also need a way for userspace to specify which
> endpoints get streams, and which endpoints have streams freed.  I will

What I have in mind is user space passing a structure holding:

1. Interface number [IN]
2. Bitmap indicating which EP to allocate streams for [IN]
3. Number of streams to allocate, one number [IN}
4. Number of streams actually allocated, one number  [OUT]

The devio alloc function will double check if all EPs belong to the
interface passed by the user space.
Then it will call the HCI alloc function with the required number of
streams. It will return the number of streams actually allocated by the
HCD. Items 3 & 4 can be merged to one IN/OUT parameter.

No error checking will be done in devio for number of required streams
(i.e, comparing it with the reported max streams). This kind of error
checking is already done by the xHCI driver.

Please let me know if the solution is acceptable.

Thanks,
Amit.

-- 
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-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to  devio.c
@ 2011-07-19  9:12         ` Amit Blay
  0 siblings, 0 replies; 54+ messages in thread
From: Amit Blay @ 2011-07-19  9:12 UTC (permalink / raw)
  To: Sarah Sharp
  Cc: Tatyana Brokhman, greg, linux-usb, linux-arm-msm, balbi, ablay,
	Amit Blay, open list

Hi Sarah,

I apologize for the delay responding to the thread. Thanks for your
comments. I would like to continue and fix the previous patch according to
the comments.
Also, I would like to split this patch, and implement the actual usage of
streams for bulk EP transfers (passing the stream ID with the URB) to a
different patch.

>
> It looks like userspace doesn't have a way to specify the number of
> streams USBFS needs to allocate.  Not all userspace applications are

> You probably also need a way to communicate back to userspace how many
> streams were actually allocated.  The program could choose to free

> So you're just taking the max_streams from the first endpoint that has
> streams?  What if other endpoints have varying numbers of max streams?

> What if you have endpoints on an interface that don't support streams?

> So it seems like you also need a way for userspace to specify which
> endpoints get streams, and which endpoints have streams freed.  I will

What I have in mind is user space passing a structure holding:

1. Interface number [IN]
2. Bitmap indicating which EP to allocate streams for [IN]
3. Number of streams to allocate, one number [IN}
4. Number of streams actually allocated, one number  [OUT]

The devio alloc function will double check if all EPs belong to the
interface passed by the user space.
Then it will call the HCI alloc function with the required number of
streams. It will return the number of streams actually allocated by the
HCD. Items 3 & 4 can be merged to one IN/OUT parameter.

No error checking will be done in devio for number of required streams
(i.e, comparing it with the reported max streams). This kind of error
checking is already done by the xHCI driver.

Please let me know if the solution is acceptable.

Thanks,
Amit.

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-07-19  9:12         ` Amit Blay
  (?)
@ 2011-07-19  9:18         ` Oliver Neukum
  2011-07-19 10:07             ` Amit Blay
  -1 siblings, 1 reply; 54+ messages in thread
From: Oliver Neukum @ 2011-07-19  9:18 UTC (permalink / raw)
  To: Amit Blay
  Cc: Sarah Sharp, Tatyana Brokhman, greg, linux-usb, linux-arm-msm,
	balbi, Amit Blay, open list

Am Dienstag, 19. Juli 2011, 11:12:39 schrieb Amit Blay:

> > So it seems like you also need a way for userspace to specify which
> > endpoints get streams, and which endpoints have streams freed.  I will
> 
> What I have in mind is user space passing a structure holding:
> 
> 1. Interface number [IN]
> 2. Bitmap indicating which EP to allocate streams for [IN]

If this is a bitmap,

> 3. Number of streams to allocate, one number [IN}
> 4. Number of streams actually allocated, one number  [OUT]

how can those be scalars? 

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-07-19  9:18         ` Oliver Neukum
@ 2011-07-19 10:07             ` Amit Blay
  0 siblings, 0 replies; 54+ messages in thread
From: Amit Blay @ 2011-07-19 10:07 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Amit Blay, Sarah Sharp, Tatyana Brokhman, greg, linux-usb,
	linux-arm-msm, balbi, Amit Blay, open list

Hi Oliver,

>> 1. Interface number [IN]
>> 2. Bitmap indicating which EP to allocate streams for [IN]
>
> If this is a bitmap,
>
>> 3. Number of streams to allocate, one number [IN}
>> 4. Number of streams actually allocated, one number  [OUT]
>
> how can those be scalars?
>

The bitmap only indicates which EP the user space requests to allocate
streams for. The actual number is taken from #3.

Thanks,
Amit.

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to  devio.c
@ 2011-07-19 10:07             ` Amit Blay
  0 siblings, 0 replies; 54+ messages in thread
From: Amit Blay @ 2011-07-19 10:07 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Amit Blay, Sarah Sharp, Tatyana Brokhman, greg, linux-usb,
	linux-arm-msm, balbi, Amit Blay, open list

Hi Oliver,

>> 1. Interface number [IN]
>> 2. Bitmap indicating which EP to allocate streams for [IN]
>
> If this is a bitmap,
>
>> 3. Number of streams to allocate, one number [IN}
>> 4. Number of streams actually allocated, one number  [OUT]
>
> how can those be scalars?
>

The bitmap only indicates which EP the user space requests to allocate
streams for. The actual number is taken from #3.

Thanks,
Amit.

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-07-19 10:07             ` Amit Blay
  (?)
@ 2011-07-19 10:26             ` Oliver Neukum
  2011-07-19 10:36                 ` Amit Blay
  -1 siblings, 1 reply; 54+ messages in thread
From: Oliver Neukum @ 2011-07-19 10:26 UTC (permalink / raw)
  To: Amit Blay
  Cc: Sarah Sharp, Tatyana Brokhman, greg, linux-usb, linux-arm-msm,
	balbi, Amit Blay, open list

Am Dienstag, 19. Juli 2011, 12:07:39 schrieben Sie:

Hi,

> >> 1. Interface number [IN]
> >> 2. Bitmap indicating which EP to allocate streams for [IN]
> >
> > If this is a bitmap,
> >
> >> 3. Number of streams to allocate, one number [IN}
> >> 4. Number of streams actually allocated, one number  [OUT]
> >
> > how can those be scalars?
> >
> 
> The bitmap only indicates which EP the user space requests to allocate
> streams for. The actual number is taken from #3.

Exactly. If you specify EP with a bitmap, what do you do if multiple bits
are set in the map?

	Regards
		Oliver
-- 
- - - 
SUSE LINUX Products GmbH, GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer, HRB 16746 (AG Nürnberg) 
Maxfeldstraße 5                         
90409 Nürnberg 
Germany 
- - - 

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-07-19 10:26             ` Oliver Neukum
@ 2011-07-19 10:36                 ` Amit Blay
  0 siblings, 0 replies; 54+ messages in thread
From: Amit Blay @ 2011-07-19 10:36 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Amit Blay, Sarah Sharp, Tatyana Brokhman, greg, linux-usb,
	linux-arm-msm, balbi, Amit Blay, open list

Hi Oliver,

>> >> 1. Interface number [IN]
>> >> 2. Bitmap indicating which EP to allocate streams for [IN]
>> >
>> > If this is a bitmap,
>> >
>> >> 3. Number of streams to allocate, one number [IN}
>> >> 4. Number of streams actually allocated, one number  [OUT]
>> >
>> > how can those be scalars?
>> >
>>
>> The bitmap only indicates which EP the user space requests to allocate
>> streams for. The actual number is taken from #3.
>
> Exactly. If you specify EP with a bitmap, what do you do if multiple bits
> are set in the map?
>

The user space can pass multiple EPs to allocate streams for. This is
aligned with the HCD API which expects an array of EPs and number of
streams to allocate. Please have a look in xhci.c.

I suggest to pass a bitmap from user space to represent the list of EPs.
An alternative is to pass an array, but I didn't find any real advantage
for this.

Thanks,
Amit.

 --
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to  devio.c
@ 2011-07-19 10:36                 ` Amit Blay
  0 siblings, 0 replies; 54+ messages in thread
From: Amit Blay @ 2011-07-19 10:36 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Amit Blay, Sarah Sharp, Tatyana Brokhman, greg, linux-usb,
	linux-arm-msm, balbi, Amit Blay, open list

Hi Oliver,

>> >> 1. Interface number [IN]
>> >> 2. Bitmap indicating which EP to allocate streams for [IN]
>> >
>> > If this is a bitmap,
>> >
>> >> 3. Number of streams to allocate, one number [IN}
>> >> 4. Number of streams actually allocated, one number  [OUT]
>> >
>> > how can those be scalars?
>> >
>>
>> The bitmap only indicates which EP the user space requests to allocate
>> streams for. The actual number is taken from #3.
>
> Exactly. If you specify EP with a bitmap, what do you do if multiple bits
> are set in the map?
>

The user space can pass multiple EPs to allocate streams for. This is
aligned with the HCD API which expects an array of EPs and number of
streams to allocate. Please have a look in xhci.c.

I suggest to pass a bitmap from user space to represent the list of EPs.
An alternative is to pass an array, but I didn't find any real advantage
for this.

Thanks,
Amit.

 --
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to   devio.c
  2011-07-19  9:12         ` Amit Blay
  (?)
  (?)
@ 2011-07-27  6:21         ` Amit Blay
       [not found]           ` <a9d8b0f164cdb51e88125d8432644213.squirrel-mMfbam+mt9083fI46fginR2eb7JE58TQ@public.gmane.org>
  2011-08-18 22:47           ` Sarah Sharp
  -1 siblings, 2 replies; 54+ messages in thread
From: Amit Blay @ 2011-07-27  6:21 UTC (permalink / raw)
  To: Sarah Sharp
  Cc: Tatyana Brokhman, greg, linux-usb, linux-arm-msm, balbi, ablay,
	Amit Blay, open list

Hi Sarah,

A gentle reminder, can you please take a look at the proposed solution
below for stream alloc/dealloc in devio.c? I responded to your comments
about the original patch.

On Tue, July 19, 2011 2:12 am, Amit Blay wrote:
> Hi Sarah,
>
> I apologize for the delay responding to the thread. Thanks for your
> comments. I would like to continue and fix the previous patch according to
> the comments.
> Also, I would like to split this patch, and implement the actual usage of
> streams for bulk EP transfers (passing the stream ID with the URB) to a
> different patch.
>
>>
>> It looks like userspace doesn't have a way to specify the number of
>> streams USBFS needs to allocate.  Not all userspace applications are
>
>> You probably also need a way to communicate back to userspace how many
>> streams were actually allocated.  The program could choose to free
>
>> So you're just taking the max_streams from the first endpoint that has
>> streams?  What if other endpoints have varying numbers of max streams?
>
>> What if you have endpoints on an interface that don't support streams?
>
>> So it seems like you also need a way for userspace to specify which
>> endpoints get streams, and which endpoints have streams freed.  I will
>
> What I have in mind is user space passing a structure holding:
>
> 1. Interface number [IN]
> 2. Bitmap indicating which EP to allocate streams for [IN]
> 3. Number of streams to allocate, one number [IN}
> 4. Number of streams actually allocated, one number  [OUT]
>
> The devio alloc function will double check if all EPs belong to the
> interface passed by the user space.
> Then it will call the HCI alloc function with the required number of
> streams. It will return the number of streams actually allocated by the
> HCD. Items 3 & 4 can be merged to one IN/OUT parameter.
>
> No error checking will be done in devio for number of required streams
> (i.e, comparing it with the reported max streams). This kind of error
> checking is already done by the xHCI driver.
>
> Please let me know if the solution is acceptable.
>
> Thanks,
> Amit.

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-07-27  6:21         ` Amit Blay
@ 2011-08-17  7:06               ` Hans Petter Selasky
  2011-08-18 22:47           ` Sarah Sharp
  1 sibling, 0 replies; 54+ messages in thread
From: Hans Petter Selasky @ 2011-08-17  7:06 UTC (permalink / raw)
  To: Amit Blay
  Cc: Sarah Sharp, Tatyana Brokhman, greg-U8xfFu+wG4EAvxtiuMwx3w,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, balbi-l0cyMroinI0,
	Amit Blay, open list

On Wednesday 27 July 2011 08:21:35 Amit Blay wrote:
> Hi Sarah,
> 
> A gentle reminder, can you please take a look at the proposed solution
> below for stream alloc/dealloc in devio.c? I responded to your comments
> about the original patch.

Hi,

I'm looking into implementing USB 3.0 streams support for FreeBSD and would 
like to have a solution in Linux which is not too far apart, also regarding 
API's for userspace.

I would suggest overloading the "unsigned int pipe", instead of breaking 
existing API's by adding a new stream ID value. Also for LibUSB.

./linux/usb.h:  unsigned int pipe;              /* (in) pipe information */

As per definition there are 15 bits available for "pipe". I think it is not 
important to support more than 255 streams in the first go, hence I see no 
real applications that would benefit from that many streams yet.

#define usb_pipeendpoint(pipe)  (((pipe) >> 15) & 0xf)

Then I suggest a new function/IOCTL in libusb which can be used to switch 
on/off streams on a given endpoint. This is something which would need to be 
done before submitting any URB's on that endpoint. And would be similar to the 
clear-stall case.

If an URB is submitted on a stream when streams are disabled then it should 
just fail and vice versa.

--HPS
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
@ 2011-08-17  7:06               ` Hans Petter Selasky
  0 siblings, 0 replies; 54+ messages in thread
From: Hans Petter Selasky @ 2011-08-17  7:06 UTC (permalink / raw)
  To: Amit Blay
  Cc: Sarah Sharp, Tatyana Brokhman, greg, linux-usb, linux-arm-msm,
	balbi, Amit Blay, open list

On Wednesday 27 July 2011 08:21:35 Amit Blay wrote:
> Hi Sarah,
> 
> A gentle reminder, can you please take a look at the proposed solution
> below for stream alloc/dealloc in devio.c? I responded to your comments
> about the original patch.

Hi,

I'm looking into implementing USB 3.0 streams support for FreeBSD and would 
like to have a solution in Linux which is not too far apart, also regarding 
API's for userspace.

I would suggest overloading the "unsigned int pipe", instead of breaking 
existing API's by adding a new stream ID value. Also for LibUSB.

./linux/usb.h:  unsigned int pipe;              /* (in) pipe information */

As per definition there are 15 bits available for "pipe". I think it is not 
important to support more than 255 streams in the first go, hence I see no 
real applications that would benefit from that many streams yet.

#define usb_pipeendpoint(pipe)  (((pipe) >> 15) & 0xf)

Then I suggest a new function/IOCTL in libusb which can be used to switch 
on/off streams on a given endpoint. This is something which would need to be 
done before submitting any URB's on that endpoint. And would be similar to the 
clear-stall case.

If an URB is submitted on a stream when streams are disabled then it should 
just fail and vice versa.

--HPS

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-07-27  6:21         ` Amit Blay
       [not found]           ` <a9d8b0f164cdb51e88125d8432644213.squirrel-mMfbam+mt9083fI46fginR2eb7JE58TQ@public.gmane.org>
@ 2011-08-18 22:47           ` Sarah Sharp
  2011-08-21 10:18               ` Amit Blay
  2011-08-22  7:56             ` Hans Petter Selasky
  1 sibling, 2 replies; 54+ messages in thread
From: Sarah Sharp @ 2011-08-18 22:47 UTC (permalink / raw)
  To: Amit Blay, Hans Petter Selasky
  Cc: Tatyana Brokhman, greg, linux-usb, linux-arm-msm, balbi,
	Amit Blay, open list

On Tue, Jul 26, 2011 at 11:21:35PM -0700, Amit Blay wrote:
> On Tue, July 19, 2011 2:12 am, Amit Blay wrote:
> > What I have in mind is user space passing a structure holding:
> >
> > 1. Interface number [IN]
> > 2. Bitmap indicating which EP to allocate streams for [IN]
> > 3. Number of streams to allocate, one number [IN}
> > 4. Number of streams actually allocated, one number  [OUT]
> >
> > The devio alloc function will double check if all EPs belong to the
> > interface passed by the user space.
> > Then it will call the HCI alloc function with the required number of
> > streams. It will return the number of streams actually allocated by the
> > HCD. Items 3 & 4 can be merged to one IN/OUT parameter.
> >
> > No error checking will be done in devio for number of required streams
> > (i.e, comparing it with the reported max streams). This kind of error
> > checking is already done by the xHCI driver.
> >
> > Please let me know if the solution is acceptable.

Yes, I think this is the correct solution.  Sorry for taking so long to
get back to you.


On Wed, Aug 17, 2011 at 09:06:03AM +0200, Hans Petter Selasky wrote:
> I'm looking into implementing USB 3.0 streams support for FreeBSD and would 
> like to have a solution in Linux which is not too far apart, also regarding 
> API's for userspace.
> 
> I would suggest overloading the "unsigned int pipe", instead of breaking 
> existing API's by adding a new stream ID value. Also for LibUSB.
> 
> ./linux/usb.h:  unsigned int pipe;              /* (in) pipe information */

I think this gets very close to breaking current API for usbfs.  What
happens if some application is putting garbage in the upper bits of the
pipe?  A libusb application that worked before will break because the
USB core will reject the endpoint as not having streams enabled.  So I
think it's better to have a new IOCTL for submitting URBs to endpoints
with streams enabled, as Alan suggested:

http://marc.info/?l=linux-kernel&m=130832352124932&w=2

> As per definition there are 15 bits available for "pipe". I think it is not 
> important to support more than 255 streams in the first go, hence I see no 
> real applications that would benefit from that many streams yet.

I don't see this as a strong argument why we should arbitrarily limit a
new API.  It's very hard to deprecate kernel to userspace API, so I
think we should do it right the first time.  There are current
applications (like an SSD behind a UAS device) that need as many
concurrent streams in flight as possible, so I don't buy the argument
that there aren't current applications that need that many streams.

I don't want to limit future applications of streams without a very good
reason.  I would like to see the new API allow userspace to submit URBs
for stream IDs up to the maximum limit specified by the USB 3.0 spec
(65,533 streams).

Why do you think reusing the pipe variable would be a better solution?
You're going to need a new IOCTL to enable streams anyway, so why not
also have a new IOCTL for submitting an URB to an endpoint with streams
enabled?

> #define usb_pipeendpoint(pipe)  (((pipe) >> 15) & 0xf)
> 
> Then I suggest a new function/IOCTL in libusb which can be used to switch 
> on/off streams on a given endpoint. This is something which would need to be 
> done before submitting any URB's on that endpoint. And would be similar to the 
> clear-stall case.

Amit was discussing such an IOCTL.  The problem is you just can't turn
streams "on and off".  The xHCI driver has to have an indication of how
many streams your application will need.  That's why Amit's proposal
included a way for the application to pass in the number of streams to
allocate.

> If an URB is submitted on a stream when streams are disabled then it should 
> just fail and vice versa.

That code is already included in the xHCI driver, and usbfs shouldn't do
any checking of the stream ID for the URB, since it's already in the
lower level driver.

Sarah Sharp

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-08-18 22:47           ` Sarah Sharp
@ 2011-08-21 10:18               ` Amit Blay
  2011-08-22  7:56             ` Hans Petter Selasky
  1 sibling, 0 replies; 54+ messages in thread
From: Amit Blay @ 2011-08-21 10:18 UTC (permalink / raw)
  To: Sarah Sharp
  Cc: Amit Blay, Hans Petter Selasky, Tatyana Brokhman, greg,
	linux-usb, linux-arm-msm, balbi, Amit Blay, open list

Thanks Sarah, Hans for your comments,

On Thu, August 18, 2011 3:47 pm, Sarah Sharp wrote:

> Yes, I think this is the correct solution.  Sorry for taking so long to
> get back to you.

OK, so I will go ahead with implementing this solution.

> On Wed, Aug 17, 2011 at 09:06:03AM +0200, Hans Petter Selasky wrote:
>> I would suggest overloading the "unsigned int pipe", instead of breaking
>> existing API's by adding a new stream ID value. Also for LibUSB.

The purposed solution will not break any existing API, by doing the
following:
a. Adding a new API for streams alloc/dealloc
b. Adding a new API for submitting a URB which is stream capable (I will
implement this in a separate patch).

> I don't see this as a strong argument why we should arbitrarily limit a
> new API.  It's very hard to deprecate kernel to userspace API, so I
> think we should do it right the first time.  There are current
> applications (like an SSD behind a UAS device) that need as many
> concurrent streams in flight as possible, so I don't buy the argument
> that there aren't current applications that need that many streams.

I agree with Sarah.
Hans, I appreciate your inputs. Please let me know if you see a good
reason why not implementing the new APIs purposed above for streams
allocation and usage. Otherwise I will go ahead with the implementation.

Thanks,
Amit.

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to  devio.c
@ 2011-08-21 10:18               ` Amit Blay
  0 siblings, 0 replies; 54+ messages in thread
From: Amit Blay @ 2011-08-21 10:18 UTC (permalink / raw)
  To: Sarah Sharp
  Cc: Amit Blay, Hans Petter Selasky, Tatyana Brokhman, greg,
	linux-usb, linux-arm-msm, balbi, Amit Blay, open list

Thanks Sarah, Hans for your comments,

On Thu, August 18, 2011 3:47 pm, Sarah Sharp wrote:

> Yes, I think this is the correct solution.  Sorry for taking so long to
> get back to you.

OK, so I will go ahead with implementing this solution.

> On Wed, Aug 17, 2011 at 09:06:03AM +0200, Hans Petter Selasky wrote:
>> I would suggest overloading the "unsigned int pipe", instead of breaking
>> existing API's by adding a new stream ID value. Also for LibUSB.

The purposed solution will not break any existing API, by doing the
following:
a. Adding a new API for streams alloc/dealloc
b. Adding a new API for submitting a URB which is stream capable (I will
implement this in a separate patch).

> I don't see this as a strong argument why we should arbitrarily limit a
> new API.  It's very hard to deprecate kernel to userspace API, so I
> think we should do it right the first time.  There are current
> applications (like an SSD behind a UAS device) that need as many
> concurrent streams in flight as possible, so I don't buy the argument
> that there aren't current applications that need that many streams.

I agree with Sarah.
Hans, I appreciate your inputs. Please let me know if you see a good
reason why not implementing the new APIs purposed above for streams
allocation and usage. Otherwise I will go ahead with the implementation.

Thanks,
Amit.

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-08-18 22:47           ` Sarah Sharp
  2011-08-21 10:18               ` Amit Blay
@ 2011-08-22  7:56             ` Hans Petter Selasky
  2011-08-22 16:41               ` Sarah Sharp
  1 sibling, 1 reply; 54+ messages in thread
From: Hans Petter Selasky @ 2011-08-22  7:56 UTC (permalink / raw)
  To: Sarah Sharp
  Cc: Amit Blay, Tatyana Brokhman, greg, linux-usb, linux-arm-msm,
	balbi, Amit Blay, open list

Hi,

> 
> On Wed, Aug 17, 2011 at 09:06:03AM +0200, Hans Petter Selasky wrote:
> > I'm looking into implementing USB 3.0 streams support for FreeBSD and
> > would like to have a solution in Linux which is not too far apart, also
> > regarding API's for userspace.
> > 
> > I would suggest overloading the "unsigned int pipe", instead of breaking
> > existing API's by adding a new stream ID value. Also for LibUSB.
> > 
> > ./linux/usb.h:  unsigned int pipe;              /* (in) pipe information
> > */
> 
> I think this gets very close to breaking current API for usbfs.  What
> happens if some application is putting garbage in the upper bits of the
> pipe? 

I think this will never happen, because all USB applications I know about are 
taught to use a set of macros to create the "pipe" value, which by default 
zero these bits.

> A libusb application that worked before will break because the
> USB core will reject the endpoint as not having streams enabled.  So I
> think it's better to have a new IOCTL for submitting URBs to endpoints
> with streams enabled, as Alan suggested:
> 
> http://marc.info/?l=linux-kernel&m=130832352124932&w=2
> 
> > As per definition there are 15 bits available for "pipe". I think it is
> > not important to support more than 255 streams in the first go, hence I
> > see no real applications that would benefit from that many streams yet.
> 
> I don't see this as a strong argument why we should arbitrarily limit a
> new API.  It's very hard to deprecate kernel to userspace API, so I
> think we should do it right the first time.  There are current
> applications (like an SSD behind a UAS device) that need as many
> concurrent streams in flight as possible, so I don't buy the argument
> that there aren't current applications that need that many streams.
> 
> I don't want to limit future applications of streams without a very good
> reason.  I would like to see the new API allow userspace to submit URBs
> for stream IDs up to the maximum limit specified by the USB 3.0 spec
> (65,533 streams).
> 
> Why do you think reusing the pipe variable would be a better solution?
> You're going to need a new IOCTL to enable streams anyway, so why not
> also have a new IOCTL for submitting an URB to an endpoint with streams
> enabled?

What I'm thinking is that you should try to integrate the streams 
functionality as much as possible, with existing API's, so that API's that do 
roughly the same are not duplicated. In FreeBSD 8/9 we have more free bits in 
the pipe variable, and I'll probably use that for the stream ID. It's like 
IPv4 and IPv6, that you extend fields when required and not duplicate them. 
I'm just worried that intel will come up with yet-another way to transfer data 
in a few years, and then we'll have to wreck API's again. So why not foresee 
that now and make 128-bits available for endpoint/stream/XXX addressing?

> 
> > #define usb_pipeendpoint(pipe)  (((pipe) >> 15) & 0xf)
> > 
> > Then I suggest a new function/IOCTL in libusb which can be used to switch
> > on/off streams on a given endpoint. This is something which would need to
> > be done before submitting any URB's on that endpoint. And would be
> > similar to the clear-stall case.
> 
> Amit was discussing such an IOCTL.  The problem is you just can't turn
> streams "on and off".  The xHCI driver has to have an indication of how
> many streams your application will need.  That's why Amit's proposal
> included a way for the application to pass in the number of streams to
> allocate.

Ok.

> 
> > If an URB is submitted on a stream when streams are disabled then it
> > should just fail and vice versa.
> 
> That code is already included in the xHCI driver, and usbfs shouldn't do
> any checking of the stream ID for the URB, since it's already in the
> lower level driver.

Ok.

--HPS

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-08-21 10:18               ` Amit Blay
  (?)
@ 2011-08-22  7:58               ` Hans Petter Selasky
  -1 siblings, 0 replies; 54+ messages in thread
From: Hans Petter Selasky @ 2011-08-22  7:58 UTC (permalink / raw)
  To: Amit Blay
  Cc: Sarah Sharp, Tatyana Brokhman, greg, linux-usb, linux-arm-msm,
	balbi, Amit Blay, open list

On Sunday 21 August 2011 12:18:34 Amit Blay wrote:
> Thanks Sarah, Hans for your comments,
> 
> On Thu, August 18, 2011 3:47 pm, Sarah Sharp wrote:
> > Yes, I think this is the correct solution.  Sorry for taking so long to
> > get back to you.
> 
> OK, so I will go ahead with implementing this solution.
> 
> > On Wed, Aug 17, 2011 at 09:06:03AM +0200, Hans Petter Selasky wrote:
> >> I would suggest overloading the "unsigned int pipe", instead of breaking
> >> existing API's by adding a new stream ID value. Also for LibUSB.
> 
> The purposed solution will not break any existing API, by doing the
> following:
> a. Adding a new API for streams alloc/dealloc
> b. Adding a new API for submitting a URB which is stream capable (I will
> implement this in a separate patch).
> 
> > I don't see this as a strong argument why we should arbitrarily limit a
> > new API.  It's very hard to deprecate kernel to userspace API, so I
> > think we should do it right the first time.  There are current
> > applications (like an SSD behind a UAS device) that need as many
> > concurrent streams in flight as possible, so I don't buy the argument
> > that there aren't current applications that need that many streams.
> 
> I agree with Sarah.
> Hans, I appreciate your inputs. Please let me know if you see a good
> reason why not implementing the new APIs purposed above for streams
> allocation and usage. Otherwise I will go ahead with the implementation.

Hi Amit,

I think your suggestion is OK.

--HPS

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c
  2011-08-22  7:56             ` Hans Petter Selasky
@ 2011-08-22 16:41               ` Sarah Sharp
  0 siblings, 0 replies; 54+ messages in thread
From: Sarah Sharp @ 2011-08-22 16:41 UTC (permalink / raw)
  To: Hans Petter Selasky
  Cc: Amit Blay, Tatyana Brokhman, greg, linux-usb, linux-arm-msm,
	balbi, Amit Blay, open list

On Mon, Aug 22, 2011 at 09:56:51AM +0200, Hans Petter Selasky wrote:
> Hi,
> 
> > 
> > On Wed, Aug 17, 2011 at 09:06:03AM +0200, Hans Petter Selasky wrote:
> > > I'm looking into implementing USB 3.0 streams support for FreeBSD and
> > > would like to have a solution in Linux which is not too far apart, also
> > > regarding API's for userspace.
> > > 
> > > I would suggest overloading the "unsigned int pipe", instead of breaking
> > > existing API's by adding a new stream ID value. Also for LibUSB.
> > > 
> > > ./linux/usb.h:  unsigned int pipe;              /* (in) pipe information
> > > */
> > 
> > I think this gets very close to breaking current API for usbfs.  What
> > happens if some application is putting garbage in the upper bits of the
> > pipe? 
> 
> I think this will never happen, because all USB applications I know about are 
> taught to use a set of macros to create the "pipe" value, which by default 
> zero these bits.

Userspace programs aren't required to use the macros, so there is always
a possibility that some program out there will be passing garbage.  If
your argument had been "the kernel checks for garbage, and returns an
error code if there is garbage, so therefore there can't be any programs
that put garbage in the upper bits", then that would be a different
story.

> > Why do you think reusing the pipe variable would be a better solution?
> > You're going to need a new IOCTL to enable streams anyway, so why not
> > also have a new IOCTL for submitting an URB to an endpoint with streams
> > enabled?
> 
> What I'm thinking is that you should try to integrate the streams 
> functionality as much as possible, with existing API's, so that API's that do 
> roughly the same are not duplicated. In FreeBSD 8/9 we have more free bits in 
> the pipe variable, and I'll probably use that for the stream ID.

We'll try to coalesce the streams and non-streams functions in the
kernel so they share as much code as possible.  I see adding a new call
parameter in a new usbfs ioctl as the right way to share new
functionality in KAPI, rather than overloading currently free bits.
However, if you come from a hardware background, I can see where adding
new functionality in "reserved" bits seems normal.

> It's like 
> IPv4 and IPv6, that you extend fields when required and not duplicate them. 
> I'm just worried that intel will come up with yet-another way to transfer data 
> in a few years, and then we'll have to wreck API's again.

We're not wrecking APIs, we're just creating new ones.  New programs
will have to do something different for streams (especially since
they'll have to deal with out-of-order completions), so it's reasonable
to ask them to call a different function in order to ensure we can use
the full stream ID range.

> So why not foresee 
> that now and make 128-bits available for endpoint/stream/XXX addressing?

We can't predict the future here.  Who knows whether they will come up
with some completely different mechanism that doesn't involve streams?

Besides, it would take a major rev of the USB spec (or at least a very
careful errata) to add more stream ID bits, since the upper bits are
reserved for specific host and device states.  Intel is not the only
company behind USB, and it takes time to get spec changes through the
USB-IF working groups.  Considering that it took them eight years to
update the USB 2.0 spec to USB 3.0, I think it's safe to say the current
stream ID range limitations will be around for several years.

Sarah Sharp

^ permalink raw reply	[flat|nested] 54+ messages in thread

end of thread, other threads:[~2011-08-22 16:41 UTC | newest]

Thread overview: 54+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-16 13:31 [PATCH/RFC 1/5] usb:tools: usb unittests framework Tatyana Brokhman
2011-06-16 13:31 ` Tatyana Brokhman
     [not found] ` <1308231068-24038-2-git-send-email-tlinder-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2011-06-16 13:31   ` [PATCH/RFC 2/5] usb:dummy_hcd: connect/disconnect test support Tatyana Brokhman
2011-06-16 13:31     ` Tatyana Brokhman
2011-06-16 15:06     ` Alan Stern
2011-06-16 15:06       ` Alan Stern
2011-06-16 16:16       ` Felipe Balbi
2011-06-16 17:06         ` Alan Stern
2011-06-16 17:06           ` Alan Stern
2011-06-16 17:19           ` Alan Stern
2011-06-16 17:19             ` Alan Stern
2011-06-16 15:17     ` Alan Stern
2011-06-16 15:17       ` Alan Stern
2011-06-16 16:18     ` Felipe Balbi
2011-06-16 13:31   ` [PATCH/RFC 4/5] usb:dummy_hcd: Disable single-request fifo in dummy hcd Tatyana Brokhman
2011-06-16 13:31     ` Tatyana Brokhman
2011-06-16 15:09     ` Alan Stern
2011-06-16 15:09       ` Alan Stern
2011-06-16 13:31 ` [PATCH/RFC 3/5] usb:g_zero: bulk in/out unittest support Tatyana Brokhman
2011-06-16 13:31   ` Tatyana Brokhman
2011-06-16 16:25   ` Felipe Balbi
2011-06-16 13:31 ` [PATCH/RFC 5/5] usb: Add support for streams alloc/dealloc to devio.c Tatyana Brokhman
2011-06-16 13:31   ` Tatyana Brokhman
     [not found]   ` <1308231068-24038-6-git-send-email-tlinder-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2011-06-16 15:20     ` Alan Stern
2011-06-16 15:20       ` Alan Stern
2011-06-30 17:45     ` Sarah Sharp
2011-06-30 17:45       ` Sarah Sharp
2011-06-30 18:39       ` William Gulland
2011-06-30 18:39         ` William Gulland
2011-06-30 18:41       ` Tanya Brokhman
2011-06-30 18:41         ` Tanya Brokhman
2011-07-19  9:12       ` Amit Blay
2011-07-19  9:12         ` Amit Blay
2011-07-19  9:18         ` Oliver Neukum
2011-07-19 10:07           ` Amit Blay
2011-07-19 10:07             ` Amit Blay
2011-07-19 10:26             ` Oliver Neukum
2011-07-19 10:36               ` Amit Blay
2011-07-19 10:36                 ` Amit Blay
2011-07-27  6:21         ` Amit Blay
     [not found]           ` <a9d8b0f164cdb51e88125d8432644213.squirrel-mMfbam+mt9083fI46fginR2eb7JE58TQ@public.gmane.org>
2011-08-17  7:06             ` Hans Petter Selasky
2011-08-17  7:06               ` Hans Petter Selasky
2011-08-18 22:47           ` Sarah Sharp
2011-08-21 10:18             ` Amit Blay
2011-08-21 10:18               ` Amit Blay
2011-08-22  7:58               ` Hans Petter Selasky
2011-08-22  7:56             ` Hans Petter Selasky
2011-08-22 16:41               ` Sarah Sharp
2011-06-16 16:28   ` Felipe Balbi
2011-06-16 18:21     ` Greg KH
2011-06-17  8:55       ` ablay
2011-06-17  8:55         ` ablay
2011-06-17 14:35         ` Alan Stern
2011-06-17 14:35           ` Alan Stern

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.