Index: /trunk/src/VBox/ValidationKit/tests/usb/tdUsb1.py
===================================================================
--- /trunk/src/VBox/ValidationKit/tests/usb/tdUsb1.py	(revision 59883)
+++ /trunk/src/VBox/ValidationKit/tests/usb/tdUsb1.py	(revision 59884)
@@ -9,5 +9,5 @@
 __copyright__ = \
 """
-Copyright (C) 2014-2015 Oracle Corporation
+Copyright (C) 2014-2016 Oracle Corporation
 
 This file is part of VirtualBox Open Source Edition (OSE), as
@@ -105,4 +105,5 @@
         self.cUsbReattachCycles    = self.cUsbReattachCyclesDef;
         self.sHostname             = socket.gethostname().lower();
+        self.fUseTxs               = True;
 
     #
@@ -112,5 +113,5 @@
         rc = vbox.TestDriver.showUsage(self);
         reporter.log('');
-        reporter.log('tdStorageBenchmark1 Options:');
+        reporter.log('tdUsb1 Options:');
         reporter.log('  --virt-modes    <m1[:m2[:]]');
         reporter.log('      Default: %s' % (':'.join(self.asVirtModesDef)));
@@ -131,4 +132,7 @@
         reporter.log('  --usb-reattach-cycles <cycles>');
         reporter.log('      Default: %s' % (self.cUsbReattachCyclesDef));
+        reporter.log('  --local');
+        reporter.log('      Don\'t use TXS for communication with the gadget but do everything');
+        reporter.log('      on this host');
         return rc;
 
@@ -196,4 +200,6 @@
                 raise base.InvalidOption('The "--usb-reattach-cycles" value "%s" is zero or negative.' \
                     % (self.cUsbReattachCycles,));
+        elif asArgs[iArg] == '--local':
+            self.fUseTxs = False;
         else:
             return vbox.TestDriver.parseOption(self, asArgs, iArg);
@@ -288,5 +294,9 @@
         """
         # Get configured USB test devices from hostname we are running on
-        sGadgetHost, sGadgetType = self.getGadgetParams(self.sHostname, sSpeed);
+        if self.fUseTxs is True:
+            sGadgetHost, sGadgetType = self.getGadgetParams(self.sHostname, sSpeed);
+        else:
+            sGadgetHost = 'dummy';
+            sGadgetType = usbgadget.g_ksGadgetTypeDummyHcd;
 
         # Create device filter
@@ -295,5 +305,5 @@
             oUsbGadget = usbgadget.UsbGadget();
             reporter.log('Connecting to gadget: ' + sGadgetType);
-            fRc = oUsbGadget.connectTo(30 * 1000, sGadgetType, sGadgetHost);
+            fRc = oUsbGadget.connectTo(30 * 1000, sGadgetType, self.fUseTxs, sGadgetHost);
             if fRc is True:
                 reporter.log('Connect succeeded');
@@ -330,5 +340,9 @@
         """
         # Get configured USB test devices from hostname we are running on
-        sGadgetHost, sGadgetType = self.getGadgetParams(self.sHostname, sSpeed);
+        if self.fUseTxs is True:
+            sGadgetHost, sGadgetType = self.getGadgetParams(self.sHostname, sSpeed);
+        else:
+            sGadgetHost = 'dummy';
+            sGadgetType = usbgadget.g_ksGadgetTypeDummyHcd;
 
         # Create device filter
@@ -337,5 +351,5 @@
             oUsbGadget = usbgadget.UsbGadget();
             reporter.log('Connecting to gadget: ' + sGadgetType);
-            fRc = oUsbGadget.connectTo(30 * 1000, sGadgetType, sGadgetHost);
+            fRc = oUsbGadget.connectTo(30 * 1000, sGadgetType, self.fUseTxs, sGadgetHost);
             if fRc is True:
                 reporter.log('Connect succeeded');
Index: /trunk/src/VBox/ValidationKit/tests/usb/usbgadget.py
===================================================================
--- /trunk/src/VBox/ValidationKit/tests/usb/usbgadget.py	(revision 59883)
+++ /trunk/src/VBox/ValidationKit/tests/usb/usbgadget.py	(revision 59884)
@@ -9,5 +9,5 @@
 __copyright__ = \
 """
-Copyright (C) 2014-2015 Oracle Corporation
+Copyright (C) 2014-2016 Oracle Corporation
 
 This file is part of VirtualBox Open Source Edition (OSE), as
@@ -34,4 +34,5 @@
 import testdriver.txsclient as txsclient;
 import testdriver.reporter as reporter;
+from common import utils;
 
 ## @name USB gadget type string constants.
@@ -40,4 +41,14 @@
 g_ksGadgetTypeBeaglebone  = 'BeagleBone';
 g_ksGadgetTypeODroidXu3   = 'ODroidXu3';
+g_ksGadgetTypeDummyHcd    = 'DummyHcd';
+## @}
+
+## @name USB gadget configurations.
+## @{
+g_kdGadgetCfgs = {
+    g_ksGadgetTypeBeaglebone: ('musb-hdrc.0.auto'),
+    g_ksGadgetTypeODroidXu3:  ('12400000.dwc3'),
+    g_ksGadgetTypeDummyHcd:   ('dummy_udc.0')
+};
 ## @}
 
@@ -59,7 +70,37 @@
 
     def __init__(self):
-        self.oTxsSession = None;
+        self.oTxsSession    = None;
         self.sImpersonation = g_ksGadgetImpersonationInvalid;
         self.sGadgetType    = g_ksGadgetTypeInvalid;
+
+    def _sudoExecuteSync(self, asArgs):
+        """
+        Executes a sudo child process synchronously.
+        Returns a tuple [True, 0] if the process executed successfully
+        and returned 0, otherwise [False, rc] is returned.
+        """
+        reporter.log('Executing [sudo]: %s' % (asArgs, ));
+        reporter.flushall();
+        iRc = 0;
+        try:
+            iRc = utils.sudoProcessCall(asArgs, shell = False, close_fds = False);
+        except:
+            reporter.errorXcpt();
+            return (False, 0);
+        reporter.log('Exit code [sudo]: %s (%s)' % (iRc, asArgs));
+        return (iRc is 0, iRc);
+
+    def _execLocallyOrThroughTxs(self, sExec, asArgs):
+        """
+        Executes the given program locally or through TXS based on the
+        current config.
+        """
+        fRc = False;
+
+        if self.oTxsSession is not None:
+            fRc = self.oTxsSession.syncExecEx(sExec, (sExec,) + asArgs);
+        else:
+            fRc, _ = self._sudoExecuteSync([sExec, ] + list(asArgs));
+        return fRc;
 
     def _loadModule(self, sModule):
@@ -69,9 +110,5 @@
         Returns False otherwise.
         """
-        fRc = False;
-        if self.oTxsSession is not None:
-            fRc = self.oTxsSession.syncExecEx('/usr/bin/modprobe', ('/usr/bin/modprobe', sModule));
-            fRc = fRc and self.connectUsb();
-        return fRc;
+        return self._execLocallyOrThroughTxs('/usr/bin/modprobe', (sModule, ));
 
     def _unloadModule(self, sModule):
@@ -81,10 +118,5 @@
         Returns False otherwise.
         """
-        fRc = False;
-        if self.oTxsSession is not None:
-            self.disconnectUsb();
-            fRc = self.oTxsSession.syncExecEx('/usr/bin/rmmod', ('/usr/bin/rmmod', sModule));
-
-        return fRc;
+        return self._execLocallyOrThroughTxs('/usr/bin/rmmod', (sModule, ));
 
     def _clearImpersonation(self):
@@ -111,4 +143,31 @@
         return False;
 
+    def _doSoftConnect(self, sAction):
+        """
+        Does a softconnect/-disconnect based on the given action.
+        """
+        sUdcFile = g_kdGadgetCfgs.get(self.sGadgetType);
+        sPath = '/sys/class/udc/' + sUdcFile + '/soft_connect';
+
+        return self._execLocallyOrThroughTxs('/usr/bin/sh', ('-c', 'echo' + sAction + ' > ' + sPath));
+
+    def _prepareGadget(self):
+        """
+        Prepares the gadget for use in testing.
+        """
+        fRc = True;
+        if self.sGadgetType is g_ksGadgetTypeDummyHcd:
+            fRc = self._loadModule('dummy_hcd');
+        return fRc;
+
+    def _cleanupGadget(self):
+        """
+        Cleans up the gadget to the default state.
+        """
+        fRc = True;
+        if self.sGadgetType is g_ksGadgetTypeDummyHcd:
+            fRc = self._unloadModule('dummy_hcd');
+        return fRc;
+
     def disconnectUsb(self):
         """
@@ -116,11 +175,5 @@
         connection used for control)
         """
-        if self.sGadgetType == g_ksGadgetTypeODroidXu3:
-            fRc = self.oTxsSession.syncExecEx('/usr/bin/sh', \
-                    ('/usr/bin/sh', '-c', 'echo disconnect > /sys/class/udc/12400000.dwc3/soft_connect'));
-        elif self.sGadgetType == g_ksGadgetTypeBeaglebone:
-            fRc = self.oTxsSession.syncExecEx('/usr/bin/sh', \
-                    ('/usr/bin/sh', '-c', 'echo disconnect > /sys/class/udc/musb-hdrc.0.auto/soft_connect'));
-        return fRc;
+        return self._doSoftConnect('disconnect');
 
     def connectUsb(self):
@@ -128,11 +181,5 @@
         Connect the USB gadget to the host.
         """
-        if self.sGadgetType == g_ksGadgetTypeODroidXu3:
-            fRc = self.oTxsSession.syncExecEx('/usr/bin/sh', \
-                    ('/usr/bin/sh', '-c', 'echo connect > /sys/class/udc/12400000.dwc3/soft_connect'));
-        elif self.sGadgetType == g_ksGadgetTypeBeaglebone:
-            fRc = self.oTxsSession.syncExecEx('/usr/bin/sh', \
-                    ('/usr/bin/sh', '-c', 'echo connect > /sys/class/udc/musb-hdrc.0.auto/soft_connect'));
-        return fRc;
+        return self._doSoftConnect('connect');
 
     def impersonate(self, sImpersonation):
@@ -162,5 +209,5 @@
         return False;
 
-    def connectTo(self, cMsTimeout, sGadgetType, sHostname, uPort = None):
+    def connectTo(self, cMsTimeout, sGadgetType, fUseTxs, sHostname, uPort = None):
         """
         Connects to the specified target device.
@@ -168,20 +215,28 @@
         Returns False otherwise.
         """
-        if uPort is None:
-            self.oTxsSession = txsclient.openTcpSession(cMsTimeout, sHostname);
-        else:
-            self.oTxsSession = txsclient.openTcpSession(cMsTimeout, sHostname, uPort = uPort);
-        if self.oTxsSession is None:
-            return False;
-
-        fDone = self.oTxsSession.waitForTask(30*1000);
-        print 'connect: waitForTask -> %s, result %s' % (fDone, self.oTxsSession.getResult());
-        if fDone is True and self.oTxsSession.isSuccess():
-            fRc = True;
-        else:
-            fRc = False;
-
-        if fRc is True:
-            self.sGadgetType = sGadgetType;
+        fRc = True;
+
+        if fUseTxs:
+            if uPort is None:
+                self.oTxsSession = txsclient.openTcpSession(cMsTimeout, sHostname);
+            else:
+                self.oTxsSession = txsclient.openTcpSession(cMsTimeout, sHostname, uPort = uPort);
+            if self.oTxsSession is None:
+                return False;
+
+            fDone = self.oTxsSession.waitForTask(30*1000);
+            print 'connect: waitForTask -> %s, result %s' % (fDone, self.oTxsSession.getResult());
+            if fDone is True and self.oTxsSession.isSuccess():
+                fRc = True;
+            else:
+                fRc = False;
+
+            if fRc is True:
+                self.sGadgetType = sGadgetType;
+            else:
+                self.sGadgetType = g_ksGadgetTypeInvalid;
+
+        if fRc:
+            fRc = self._prepareGadget();
 
         return fRc;
@@ -193,7 +248,9 @@
         fRc = True;
 
-        if self.oTxsSession is not None:
+        if self.sGadgetType is not g_ksGadgetTypeInvalid:
             self._clearImpersonation();
-            fRc = self.oTxsSession.syncDisconnect();
-
-        return fRc;
+            self._cleanupGadget();
+            if self.oTxsSession is not None:
+                fRc = self.oTxsSession.syncDisconnect();
+
+        return fRc;
