Index: trunk/src/VBox/ValidationKit/tests/usb/Makefile.kmk
===================================================================
--- trunk/src/VBox/ValidationKit/tests/usb/Makefile.kmk	(revision 60487)
+++ trunk/src/VBox/ValidationKit/tests/usb/Makefile.kmk	(revision 60488)
@@ -34,5 +34,6 @@
 ValidationKitTestsUsb_EXEC_SOURCES := \
 	$(PATH_SUB_CURRENT)/tdUsb1.py \
-	$(PATH_SUB_CURRENT)/usbgadget.py
+	$(PATH_SUB_CURRENT)/usbgadget.py \
+	$(PATH_SUB_CURRENT)/usbgadget2.py
 
 VBOX_VALIDATIONKIT_PYTHON_SOURCES += $(ValidationKitTestsUsb_EXEC_SOURCES)
Index: trunk/src/VBox/ValidationKit/tests/usb/tdUsb1.py
===================================================================
--- trunk/src/VBox/ValidationKit/tests/usb/tdUsb1.py	(revision 60487)
+++ trunk/src/VBox/ValidationKit/tests/usb/tdUsb1.py	(revision 60488)
@@ -49,5 +49,5 @@
 
 # USB gadget control import
-import usbgadget;
+import usbgadget2;
 
 class tdUsbBenchmark(vbox.TestDriver):                                      # pylint: disable=R0902
@@ -65,15 +65,15 @@
     kdGadgetParams = {
         # The following is for local testing and not for the test lab.
+        #'adaris': {
+        #    'Low':   ('beaglebone',),
+        #    'Full':  ('beaglebone',),
+        #    'High':  ('beaglebone',),
+        #    'Super': ('odroidxu3',)
+        #},
         'adaris': {
-            'Low':   ('beaglebone', usbgadget.g_ksGadgetTypeBeaglebone),
-            'Full':  ('beaglebone', usbgadget.g_ksGadgetTypeBeaglebone),
-            'High':  ('beaglebone', usbgadget.g_ksGadgetTypeBeaglebone),
-            'Super': ('odroidxu3',  usbgadget.g_ksGadgetTypeODroidXu3)
-        },
-        'archusb': {
-            'Low':   ('beaglebone', usbgadget.g_ksGadgetTypeBeaglebone),
-            'Full':  ('beaglebone', usbgadget.g_ksGadgetTypeBeaglebone),
-            'High':  ('beaglebone', usbgadget.g_ksGadgetTypeBeaglebone),
-            'Super': ('odroidxu3',  usbgadget.g_ksGadgetTypeODroidXu3)
+            'Low':   ('127.0.0.1', 0),
+            'Full':  ('127.0.0.1', 0),
+            'High':  ('127.0.0.1', 0),
+            'Super': ('127.0.0.1', 0)
         },
     };
@@ -105,5 +105,4 @@
         self.cUsbReattachCycles    = self.cUsbReattachCyclesDef;
         self.sHostname             = socket.gethostname().lower();
-        self.fUseTxs               = True;
 
     #
@@ -132,7 +131,4 @@
         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;
 
@@ -200,6 +196,4 @@
                 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);
@@ -294,23 +288,21 @@
         """
         # Get configured USB test devices from hostname we are running on
-        if self.fUseTxs is True:
-            sGadgetHost, sGadgetType = self.getGadgetParams(self.sHostname, sSpeed);
-        else:
-            sGadgetHost = 'dummy';
-            sGadgetType = usbgadget.g_ksGadgetTypeDummyHcd;
-
-        # Create device filter
-        fRc = oSession.addUsbDeviceFilter('Compliance device', '0525', 'a4a0');
+        sGadgetHost, _ = self.getGadgetParams(self.sHostname, sSpeed);
+
+        oUsbGadget = usbgadget2.UsbGadget();
+        reporter.log('Connecting to UTS: ' + sGadgetHost);
+        fRc = oUsbGadget.connectTo(30 * 1000, sGadgetHost);
         if fRc is True:
-            oUsbGadget = usbgadget.UsbGadget();
-            reporter.log('Connecting to gadget: ' + sGadgetType);
-            fRc = oUsbGadget.connectTo(30 * 1000, sGadgetType, self.fUseTxs, sGadgetHost);
+            reporter.log('Connect succeeded');
+            self.oVBox.host.addUSBDeviceSource('USBIP', sGadgetHost, sGadgetHost, [], []);
+
+            # Create device filter
+            fRc = oSession.addUsbDeviceFilter('Compliance device', '0525', 'a4a0');
             if fRc is True:
-                reporter.log('Connect succeeded');
-                fRc = oUsbGadget.impersonate(usbgadget.g_ksGadgetImpersonationTest);
+                fRc = oUsbGadget.impersonate(usbgadget2.g_ksGadgetImpersonationTest);
                 if fRc is True:
 
                     # Wait a moment to let the USB device appear
-                    self.sleep(3);
+                    self.sleep(10);
 
                     tupCmdLine = ('UsbTest', );
@@ -329,7 +321,9 @@
                 oUsbGadget.disconnectFrom();
             else:
-                reporter.testFailure('Failed to connect to USB gadget');
+                reporter.testFailure('Failed to create USB device filter');
+
+            self.oVBox.host.removeUSBDeviceSource(sGadgetHost);
         else:
-            reporter.testFailure('Failed to create USB device filter');
+            reporter.testFailure('Failed to connect to USB gadget');
 
         return fRc;
@@ -340,19 +334,17 @@
         """
         # Get configured USB test devices from hostname we are running on
-        if self.fUseTxs is True:
-            sGadgetHost, sGadgetType = self.getGadgetParams(self.sHostname, sSpeed);
-        else:
-            sGadgetHost = 'dummy';
-            sGadgetType = usbgadget.g_ksGadgetTypeDummyHcd;
-
-        # Create device filter
-        fRc = oSession.addUsbDeviceFilter('Compliance device', '0525', 'a4a0');
+        sGadgetHost, _ = self.getGadgetParams(self.sHostname, sSpeed);
+
+        oUsbGadget = usbgadget2.UsbGadget();
+        reporter.log('Connecting to UTS: ' + sGadgetHost);
+        fRc = oUsbGadget.connectTo(30 * 1000, sGadgetHost);
         if fRc is True:
-            oUsbGadget = usbgadget.UsbGadget();
-            reporter.log('Connecting to gadget: ' + sGadgetType);
-            fRc = oUsbGadget.connectTo(30 * 1000, sGadgetType, self.fUseTxs, sGadgetHost);
+            reporter.log('Connect succeeded');
+            self.oVBox.host.addUSBDeviceSource('USBIP', sGadgetHost, sGadgetHost, [], []);
+
+            # Create device filter
+            fRc = oSession.addUsbDeviceFilter('Compliance device', '0525', 'a4a0');
             if fRc is True:
-                reporter.log('Connect succeeded');
-                fRc = oUsbGadget.impersonate(usbgadget.g_ksGadgetImpersonationTest);
+                fRc = oUsbGadget.impersonate(usbgadget2.g_ksGadgetImpersonationTest);
                 if fRc is True:
 
Index: trunk/src/VBox/ValidationKit/tests/usb/tst-utsgadget.py
===================================================================
--- trunk/src/VBox/ValidationKit/tests/usb/tst-utsgadget.py	(revision 60488)
+++ trunk/src/VBox/ValidationKit/tests/usb/tst-utsgadget.py	(revision 60488)
@@ -0,0 +1,119 @@
+# -*- coding: utf-8 -*-
+# $Id$
+
+"""
+Simple testcase for usbgadget2.py.
+"""
+
+__copyright__ = \
+"""
+Copyright (C) 2016 Oracle Corporation
+
+This file is part of VirtualBox Open Source Edition (OSE), as
+available from http://www.virtualbox.org. This file is free software;
+you can redistribute it and/or modify it under the terms of the GNU
+General Public License (GPL) as published by the Free Software
+Foundation, in version 2 as it comes in the "COPYING" file of the
+VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+The contents of this file may alternatively be used under the terms
+of the Common Development and Distribution License Version 1.0
+(CDDL) only, as it comes in the "COPYING.CDDL" file of the
+VirtualBox OSE distribution, in which case the provisions of the
+CDDL are applicable instead of those of the GPL.
+
+You may elect to license modified versions of this file under the
+terms and conditions of either the GPL or the CDDL or both.
+"""
+__version__ = "$Revision$"
+
+# Standard python imports.
+import os
+import sys
+import types
+
+# Validation Kit imports.
+sys.path.insert(0, '.');
+sys.path.insert(0, '..');
+import usbgadget2 as usbgadget;
+import testdriver.reporter as reporter
+from common import utils;
+
+g_cTests = 0;
+g_cFailures = 0
+
+def boolRes(rc, fExpect = True):
+    """Checks a boolean result."""
+    global g_cTests, g_cFailures;
+    g_cTests = g_cTests + 1;
+    if isinstance(rc, types.BooleanType):
+        if rc == fExpect:
+            return 'PASSED';
+    g_cFailures = g_cFailures + 1;
+    return 'FAILED';
+
+def stringRes(rc, sExpect):
+    """Checks a string result."""
+    global g_cTests, g_cFailures;
+    g_cTests = g_cTests + 1;
+    if isinstance(rc, basestring):
+        if rc == sExpect:
+            return 'PASSED';
+    g_cFailures = g_cFailures + 1;
+    return 'FAILED';
+
+def main(asArgs): # pylint: disable=C0111,R0914,R0915
+    cMsTimeout      = 30*1000;
+    sAddress        = 'localhost';
+    uPort           = None;
+    fStdTests       = True;
+
+    i = 1;
+    while i < len(asArgs):
+        if asArgs[i] == '--hostname':
+            sAddress = asArgs[i + 1];
+            i = i + 2;
+        elif asArgs[i] == '--port':
+            uPort = int(asArgs[i + 1]);
+            i = i + 2;
+        elif asArgs[i] == '--timeout':
+            cMsTimeout = long(asArgs[i + 1]);
+            i = i + 2;
+        elif asArgs[i] == '--help':
+            print 'tst-utsgadget.py [--hostname <addr|name>] [--port <num>] [--timeout <cMS>]'
+            return 0;
+        else:
+            print 'Unknown argument: %s' % (asArgs[i]);
+            return 2;
+
+    oGadget = usbgadget.UsbGadget(); 
+    if uPort is None:
+        rc = oGadget.connectTo(cMsTimeout, sAddress);
+    else:
+        rc = oGadget.connectTo(cMsTimeout, sAddress, uPort = uPort);
+    if rc is False:
+        print 'connectTo failed';
+        return 1;
+
+    if fStdTests:
+
+
+        # Done
+        rc = oGadget.disconnectFrom();
+        print '%s: disconnect() -> %s' % (boolRes(rc), rc);
+
+    if g_cFailures != 0:
+        print 'tst-utsgadget.py: %u out of %u test failed' % (g_cFailures, g_cTests);
+        return 1;
+    print 'tst-utsgadget.py: all %u tests passed!' % (g_cTests);
+    return 0;
+
+
+if __name__ == '__main__':
+    reporter.incVerbosity();
+    reporter.incVerbosity();
+    reporter.incVerbosity();
+    reporter.incVerbosity();
+    sys.exit(main(sys.argv));
+
Index: trunk/src/VBox/ValidationKit/tests/usb/usbgadget.py
===================================================================
--- trunk/src/VBox/ValidationKit/tests/usb/usbgadget.py	(revision 60487)
+++ trunk/src/VBox/ValidationKit/tests/usb/usbgadget.py	(revision 60488)
@@ -30,4 +30,5 @@
 __version__ = "$Revision$"
 
+import time;
 
 # Validation Kit imports.
@@ -150,5 +151,5 @@
         sPath = '/sys/class/udc/' + sUdcFile + '/soft_connect';
 
-        return self._execLocallyOrThroughTxs('/usr/bin/sh', ('-c', 'echo' + sAction + ' > ' + sPath));
+        return self._execLocallyOrThroughTxs('/usr/bin/sh', ('-c', 'echo ' + sAction + ' > ' + sPath));
 
     def _prepareGadget(self):
@@ -192,20 +193,24 @@
         self.sImpersonation = sImpersonation;
 
-        if sImpersonation == g_ksGadgetImpersonationInvalid:
-            return False;
-        elif sImpersonation == g_ksGadgetImpersonationTest:
-            return self._loadModule('g_zero');
+        fRc = False;
+        if sImpersonation == g_ksGadgetImpersonationTest:
+            fRc = self._loadModule('g_zero');
         elif sImpersonation == g_ksGadgetImpersonationMsd:
             # @todo: Not complete
-            return self._loadModule('g_mass_storage');
+            fRc = self._loadModule('g_mass_storage');
         elif sImpersonation == g_ksGadgetImpersonationWebcam:
             # @todo: Not complete
-            return self._loadModule('g_webcam');
+            fRc = self._loadModule('g_webcam');
         elif sImpersonation == g_ksGadgetImpersonationEther:
-            return self._loadModule('g_ether');
+            fRc = self._loadModule('g_ether');
         else:
             reporter.log('Invalid impersonation');
 
-        return False;
+        if fRc and self.sGadgetType is g_ksGadgetTypeDummyHcd and self.oTxsSession is not None:
+            time.sleep(2); # Fudge
+            # For the dummy HCD over USB/IP case we have to bind the device to the USB/IP server
+            self._execLocallyOrThroughTxs('/usr/bin/sh', ('-c', '/usr/bin/usbip bind -b 3-1'));
+
+        return fRc;
 
     def connectTo(self, cMsTimeout, sGadgetType, fUseTxs, sHostname, uPort = None):
Index: trunk/src/VBox/ValidationKit/tests/usb/usbgadget2.py
===================================================================
--- trunk/src/VBox/ValidationKit/tests/usb/usbgadget2.py	(revision 60487)
+++ trunk/src/VBox/ValidationKit/tests/usb/usbgadget2.py	(revision 60488)
@@ -71,4 +71,15 @@
 #
 
+def getU64(abData, off):
+    """Get a U64 field."""
+    return abData[off] \
+         + abData[off + 1] * 256 \
+         + abData[off + 2] * 65536 \
+         + abData[off + 3] * 16777216 \
+         + abData[off + 4] * 4294967296 \
+         + abData[off + 5] * 1099511627776 \
+         + abData[off + 6] * 281474976710656 \
+         + abData[off + 7] * 72057594037927936;
+
 def getU32(abData, off):
     """Get a U32 field."""
@@ -77,4 +88,13 @@
          + abData[off + 2] * 65536 \
          + abData[off + 3] * 16777216;
+
+def getU16(abData, off):
+    """Get a U16 field."""
+    return abData[off] \
+         + abData[off + 1] * 256;
+
+def getU8(abData, off):
+    """Get a U8 field."""
+    return abData[off];
 
 def getSZ(abData, off, sDefault = None):
@@ -150,5 +170,13 @@
 def u8ToByteArray(u8):
     """Encodes the u8 value as a little endian byte (B) array."""
-    return array.array('B', (u8 % 256);
+    return array.array('B', (u8 % 256));
+
+def zeroByteArray(cb):
+    """Returns an array with the given size containing 0."""
+    abArray = array.array('B', (0, ));
+    cb = cb - 1;
+    for i in range(cb):
+        abArray.append(0);
+    return abArray;
 
 class TransportBase(object):
@@ -693,5 +721,7 @@
     def taskGreet(self, cMsIdleFudge):
         """Greets the UTS"""
-        rc = self.sendMsg("HOWDY", ());
+        sHostname = socket.gethostname().lower();
+        cbFill = 68 - len(sHostname) - 1;
+        rc = self.sendMsg("HOWDY", (long((1 << 16) | 0), long(0x1), long(len(sHostname)), sHostname, zeroByteArray(cbFill)));
         if rc is True:
             rc = self.recvAckLogged("HOWDY", self.fTryConnect);
@@ -718,5 +748,5 @@
     def taskGadgetCreate(self, iGadgetType, iGadgetAccess):
         """Creates a new gadget on UTS"""
-        fRc = self.senfMsg("GDGTCRT", (iGadgetType, iGadgetAccess, 0));
+        fRc = self.sendMsg("GDGTCRT", (iGadgetType, iGadgetAccess, 0));
         if fRc is True:
             fRc = self.recvAckLogged("GDGTCRT");
@@ -725,5 +755,5 @@
     def taskGadgetDestroy(self, iGadgetId):
         """Destroys the given gadget handle on UTS"""
-        fRc = self.senfMsg("GDGTDTOR", (iGadgetId, ));
+        fRc = self.sendMsg("GDGTDTOR", (iGadgetId, ));
         if fRc is True:
             fRc = self.recvAckLogged("GDGTDTOR");
@@ -732,5 +762,5 @@
     def taskGadgetConnect(self, iGadgetId):
         """Connects the given gadget handle on UTS"""
-        fRc = self.senfMsg("GDGTCNCT", (iGadgetId, ));
+        fRc = self.sendMsg("GDGTCNCT", (iGadgetId, ));
         if fRc is True:
             fRc = self.recvAckLogged("GDGTCNCT");
@@ -739,5 +769,5 @@
     def taskGadgetDisconnect(self, iGadgetId):
         """Disconnects the given gadget handle from UTS"""
-        fRc = self.senfMsg("GDGTDCNT", (iGadgetId, ));
+        fRc = self.sendMsg("GDGTDCNT", (iGadgetId, ));
         if fRc is True:
             fRc = self.recvAckLogged("GDGTDCNT");
@@ -805,5 +835,63 @@
     #
 
-    def 
+    def asyncGadgetCreate(self, iGadgetType, iGadgetAccess, cMsTimeout = 30000, fIgnoreErrors = False):
+        """
+        Initiates a gadget create task.
+
+        Returns True on success, False on failure (logged).
+
+        The task returns True on success and False on failure.
+        """
+        return self.startTask(cMsTimeout, fIgnoreErrors, "GadgetCreate", self.taskGadgetCreate, \
+                              (long(iGadgetType), long(iGadgetAccess)));
+
+    def syncGadgetCreate(self, iGadgetType, iGadgetAccess, cMsTimeout = 30000, fIgnoreErrors = False):
+        """Synchronous version."""
+        return self.asyncToSync(self.asyncGadgetCreate, iGadgetType, iGadgetAccess, cMsTimeout, fIgnoreErrors);
+
+    def asyncGadgetDestroy(self, iGadgetId, cMsTimeout = 30000, fIgnoreErrors = False):
+        """
+        Initiates a gadget destroy task.
+
+        Returns True on success, False on failure (logged).
+
+        The task returns True on success and False on failure.
+        """
+        return self.startTask(cMsTimeout, fIgnoreErrors, "GadgetDestroy", self.taskGadgetDestroy, \
+                              (long(iGadgetId), ));
+
+    def syncGadgetDestroy(self, iGadgetId, cMsTimeout = 30000, fIgnoreErrors = False):
+        """Synchronous version."""
+        return self.asyncToSync(self.asyncGadgetDestroy, iGadgetId, cMsTimeout, fIgnoreErrors);
+
+    def asyncGadgetConnect(self, iGadgetId, cMsTimeout = 30000, fIgnoreErrors = False):
+        """
+        Initiates a gadget connect task.
+
+        Returns True on success, False on failure (logged).
+
+        The task returns True on success and False on failure.
+        """
+        return self.startTask(cMsTimeout, fIgnoreErrors, "GadgetConnect", self.taskGadgetConnect, \
+                              (long(iGadgetId), ));
+
+    def syncGadgetConnect(self, iGadgetId, cMsTimeout = 30000, fIgnoreErrors = False):
+        """Synchronous version."""
+        return self.asyncToSync(self.asyncGadgetConnect, iGadgetId, cMsTimeout, fIgnoreErrors);
+
+    def asyncGadgetDisconnect(self, iGadgetId, cMsTimeout = 30000, fIgnoreErrors = False):
+        """
+        Initiates a gadget disconnect task.
+
+        Returns True on success, False on failure (logged).
+
+        The task returns True on success and False on failure.
+        """
+        return self.startTask(cMsTimeout, fIgnoreErrors, "GadgetDisconnect", self.taskGadgetDisconnect, \
+                              (long(iGadgetId), ));
+
+    def syncGadgetDisconnect(self, iGadgetId, cMsTimeout = 30000, fIgnoreErrors = False):
+        """Synchronous version."""
+        return self.asyncToSync(self.asyncGadgetDisconnect, iGadgetId, cMsTimeout, fIgnoreErrors);
 
 
@@ -1203,6 +1291,6 @@
         self.oUtsSession    = None;
         self.sImpersonation = g_ksGadgetImpersonationInvalid;
-        self.sGadgetType    = g_ksGadgetTypeInvalid;
         self.idGadget       = None;
+        self.iUsbIpPort     = None;
 
     def _clearImpersonation(self):
@@ -1247,5 +1335,12 @@
         return fRc;
 
-    def connectTo(self, cMsTimeout, sHostname, uPort = None):
+    def getUsbIpPort(self):
+        """
+        Returns the port the USB/IP server is listening on if requested,
+        None if USB/IP is not supported.
+        """
+        return self.iUsbIpPort;
+
+    def connectTo(self, cMsTimeout, sHostname, uPort = None, fUsbIpSupport = True, cMsIdleFudge = 0):
         """
         Connects to the specified target device.
@@ -1270,7 +1365,4 @@
             else:
                 fRc = False;
-
-            if fRc:
-                fRc = self._prepareGadget();
         except:
             reporter.errorXcpt(None, 15);
Index: trunk/src/VBox/ValidationKit/utils/usb/UsbTestService.cpp
===================================================================
--- trunk/src/VBox/ValidationKit/utils/usb/UsbTestService.cpp	(revision 60487)
+++ trunk/src/VBox/ValidationKit/utils/usb/UsbTestService.cpp	(revision 60488)
@@ -462,5 +462,5 @@
 
     return utsReplyFailure(pClient, pPktHdr, "FAILED  ", rcOperation, "%s failed with rc=%Rrc (opcode '%.8s')",
-                           rcOperation, szOperation, rcOperation, pPktHdr->achOpcode);
+                           szOperation, rcOperation, pPktHdr->achOpcode);
 }
 
@@ -600,7 +600,7 @@
 
     /* Extract string. */
-    pClient->pszHostname = RTStrDup(pClient->pszHostname);
+    pClient->pszHostname = RTStrDup(&pReq->achHostname[0]);
     if (!pClient->pszHostname)
-        return utsReplyRC(pClient, pPktHdr, VERR_NO_MEMORY, "Failed to alllocate memory for the hostname string");
+        return utsReplyRC(pClient, pPktHdr, VERR_NO_MEMORY, "Failed to allocate memory for the hostname string");
 
     if (pReq->fUsbConn & UTSPKT_HOWDY_CONN_F_PHYSICAL)
@@ -897,5 +897,6 @@
 
                     uint8_t bRead;
-                    rc = RTPipeRead(g_hPipeR, &bRead, 1, NULL);
+                    size_t cbRead = 0;
+                    rc = RTPipeRead(g_hPipeR, &bRead, 1, &cbRead);
                     AssertRC(rc);
 
@@ -950,4 +951,5 @@
                     /* Client sends a request, pick the right client and process it. */
                     PUTSCLIENT pClient = papClients[uId - 1];
+                    AssertPtr(pClient);
                     if (fEvts & RTPOLL_EVT_READ)
                         rc = utsClientReqProcess(pClient);
@@ -957,4 +959,7 @@
                     {
                         /* Close connection and remove client from array. */
+                        rc = g_pTransport->pfnPollSetRemove(hPollSet, pClient->pTransportClient, uId);
+                        AssertRC(rc);
+
                         g_pTransport->pfnNotifyBye(pClient->pTransportClient);
                         papClients[uId - 1] = NULL;
@@ -995,5 +1000,5 @@
          * the request handling thread.
          */
-        PUTSCLIENT pClient = (PUTSCLIENT)RTMemAllocZ(sizeof(PUTSCLIENT));
+        PUTSCLIENT pClient = (PUTSCLIENT)RTMemAllocZ(sizeof(UTSCLIENT));
         if (RT_LIKELY(pClient))
         {
@@ -1003,4 +1008,14 @@
             pClient->hGadgetHost      = NIL_UTSGADGETHOST;
             pClient->hGadget          = NIL_UTSGADGET;
+
+            /* Add client to the new list and inform the worker thread. */
+            RTCritSectEnter(&g_CritSectClients);
+            RTListAppend(&g_LstClientsNew, &pClient->NdLst);
+            RTCritSectLeave(&g_CritSectClients);
+
+            size_t cbWritten = 0;
+            rc = RTPipeWrite(g_hPipeW, "", 1, &cbWritten);
+            if (RT_FAILURE(rc))
+                RTMsgError("Failed to inform worker thread of a new client");
         }
         else
Index: trunk/src/VBox/ValidationKit/utils/usb/UsbTestServiceGadgetHostUsbIp.cpp
===================================================================
--- trunk/src/VBox/ValidationKit/utils/usb/UsbTestServiceGadgetHostUsbIp.cpp	(revision 60487)
+++ trunk/src/VBox/ValidationKit/utils/usb/UsbTestServiceGadgetHostUsbIp.cpp	(revision 60488)
@@ -101,13 +101,13 @@
     {
         /* Make sure the kernel drivers are loaded. */
-        rc = utsGadgetHostUsbIpLoadModule("usbip-core.ko");
+        rc = utsGadgetHostUsbIpLoadModule("usbip-core");
         if (RT_SUCCESS(rc))
         {
-            rc = utsGadgetHostUsbIpLoadModule("usbip-host.ko");
+            rc = utsGadgetHostUsbIpLoadModule("usbip-host");
             if (RT_SUCCESS(rc))
             {
                 char aszPort[10];
                 char aszPidFile[64];
-                const char *apszArgv[5];
+                const char *apszArgv[6];
 
                 RTStrPrintf(aszPort, RT_ELEMENTS(aszPort), "%u", uPort);
@@ -117,6 +117,7 @@
                 apszArgv[1] = "--tcp-port";
                 apszArgv[2] = aszPort;
-                apszArgv[3] = "--pid-file";
+                apszArgv[3] = "--pid";
                 apszArgv[4] = aszPidFile;
+                apszArgv[5] = NULL;
                 rc = RTProcCreate("usbipd", apszArgv, RTENV_DEFAULT, RTPROC_FLAGS_SEARCH_PATH, &pIf->hProcUsbIp);
                 if (RT_SUCCESS(rc))
Index: trunk/src/VBox/ValidationKit/utils/usb/UsbTestServiceInternal.h
===================================================================
--- trunk/src/VBox/ValidationKit/utils/usb/UsbTestServiceInternal.h	(revision 60487)
+++ trunk/src/VBox/ValidationKit/utils/usb/UsbTestServiceInternal.h	(revision 60488)
@@ -122,4 +122,14 @@
 
     /**
+     * Removes the given client frmo the given pollset.
+     *
+     * @returns IPRT status code.
+     * @param   hPollSet            The poll set to remove from.
+     * @paramm  pClient             The transport client structure. 
+     * @param   idStart             The handle ID to remove.
+     */
+    DECLR3CALLBACKMEMBER(int, pfnPollSetRemove, (RTPOLLSET hPollSet, PUTSTRANSPORTCLIENT pClient, uint32_t idStart));
+
+    /**
      * Receives an incoming packet.
      *
Index: trunk/src/VBox/ValidationKit/utils/usb/UsbTestServiceProtocol.h
===================================================================
--- trunk/src/VBox/ValidationKit/utils/usb/UsbTestServiceProtocol.h	(revision 60487)
+++ trunk/src/VBox/ValidationKit/utils/usb/UsbTestServiceProtocol.h	(revision 60488)
@@ -100,5 +100,5 @@
     uint32_t        cchHostname;
     /** The client host name as terminated ASCII string. */
-    uint8_t         achHostname[68];
+    char            achHostname[68];
 } UTSPKTREQHOWDY;
 AssertCompileSizeAlignment(UTSPKTREQHOWDY, UTSPKT_ALIGNMENT);
Index: trunk/src/VBox/ValidationKit/utils/usb/UsbTestServiceTcp.cpp
===================================================================
--- trunk/src/VBox/ValidationKit/utils/usb/UsbTestServiceTcp.cpp	(revision 60487)
+++ trunk/src/VBox/ValidationKit/utils/usb/UsbTestServiceTcp.cpp	(revision 60488)
@@ -93,13 +93,20 @@
 
 /**
- * Disconnects the current client and frees its data structure.
+ * Disconnects the current client and frees all stashed data.
  */
 static void utsTcpDisconnectClient(PUTSTRANSPORTCLIENT pClient)
 {
-    int rc = RTTcpServerDisconnectClient2(pClient->hTcpClient);
-    AssertRCSuccess(rc);
+    if (pClient->hTcpClient == NIL_RTSOCKET)
+    {
+        int rc = RTTcpServerDisconnectClient2(pClient->hTcpClient);
+        pClient->hTcpClient = NIL_RTSOCKET;
+        AssertRCSuccess(rc);
+    }
+
     if (pClient->pbTcpStashed)
+    {
         RTMemFree(pClient->pbTcpStashed);
-    RTMemFree(pClient);
+        pClient->pbTcpStashed = NULL;
+    }
 }
 
@@ -158,4 +165,5 @@
     Log(("utsTcpNotifyBye: utsTcpDisconnectClient %RTsock\n", pClient->hTcpClient));
     utsTcpDisconnectClient(pClient);
+    RTMemFree(pClient);
 }
 
@@ -347,4 +355,12 @@
 
 /**
+ * @interface_method_impl{UTSTRANSPORT,pfnPollSetRemove}
+ */
+static DECLCALLBACK(int) utsTcpPollSetRemove(RTPOLLSET hPollSet, PUTSTRANSPORTCLIENT pClient, uint32_t idStart)
+{
+    return RTPollSetRemove(hPollSet, idStart);
+}
+
+/**
  * @interface_method_impl{UTSTRANSPORT,pfnPollIn}
  */
@@ -471,4 +487,5 @@
     /* .pfnPollIn         = */ utsTcpPollIn,
     /* .pfnPollSetAdd     = */ utsTcpPollSetAdd,
+    /* .pfnPollSetRemove  = */ utsTcpPollSetRemove,
     /* .pfnRecvPkt        = */ utsTcpRecvPkt,
     /* .pfnSendPkt        = */ utsTcpSendPkt,
