Index: trunk/src/VBox/RDP/client/Makefile.kmk
===================================================================
--- trunk/src/VBox/RDP/client/Makefile.kmk	(revision 31538)
+++ trunk/src/VBox/RDP/client/Makefile.kmk	(revision 31557)
@@ -21,4 +21,5 @@
 # Globals
 VBOX_PATH_RDESKTOP_SRC := $(PATH_SUB_CURRENT)
+VBOX_PATH_DEVICES_USB  := $(PATH_ROOT)/src/VBox/Devices/USB
 VBOX_RDESKTOP_SRC_SUBDIR = rdesktop-1.6.0-vrdp
 
@@ -92,4 +93,9 @@
 	vrdp/rdpusb.c \
 	vrdp/USBProxyDevice-linux.c
+rdesktop-vrdp_INCS += \
+    $(VBOX_PATH_RDESKTOP_SRC) \
+    $(VBOX_PATH_RDESKTOP_SRC)/vrdp \
+    $(VBOX_PATH_DEVICES_USB) \
+    $(PATH_ROOT)/include/VBox
 # @todo implement usb proxy for Solaris
 rdesktop-vrdp_SOURCES.solaris = \
@@ -120,51 +126,59 @@
 ## @todo change this to an INSTALLS target.
 OTHERS += $(PATH_BIN)/rdesktop-vrdp.tar.gz
-OTHER_CLEAN += $(OTHERS) $(PATH_TARGET)/$(VBOX_RDESKTOP_SRC_SUBDIR)
+OTHER_CLEAN += $(OTHERS)
 
 
 include $(KBUILD_PATH)/subfooter.kmk
 
-rdesktop-vrdp_TARSOURCES = \
-	COPYING \
-	README \
-	configure \
-	configure.ac \
-	config.sub \
-	config.guess \
-	bootstrap \
-	install-sh \
-	Makefile.in \
-	proto.head \
-	proto.tail \
-	rdesktop.spec \
-	*.c \
-	*.h \
-	keymaps/?? \
-	keymaps/??-?? \
-	keymaps/common \
-	keymaps/modifiers \
-	keymaps/convert-map \
-	doc/HACKING \
-	doc/AUTHORS \
-	doc/TODO \
-	doc/ChangeLog \
-	doc/keymapping.txt \
-	doc/keymap-names.txt \
-	doc/ipv6.txt \
-	doc/licensing.txt \
-	doc/patches.txt \
-	doc/redirection.txt \
-	doc/rdesktop.1 \
-	vrdp/*.c \
-	vrdp/*.h
+INSTALLS += rdesktop-bin
+rdesktop-bin_INST    = obj/$(VBOX_RDESKTOP_SRC_SUBDIR)
+rdesktop-bin_MODE    = a+rx,u+w
+rdesktop-bin_SOURCES = \
+    $(foreach i,configure \
+                config.sub \
+                config.guess \
+                bootstrap \
+                install-sh, \
+            client/$i=>$i)
 
-$(PATH_TARGET)/$(VBOX_RDESKTOP_SRC_SUBDIR):
-	$(MKDIR) -p $(@D)
-	$(LN_SYMLINK) $(abspath $(VBOX_PATH_RDESKTOP_SRC)) $@
+INSTALLS += rdesktop-nonbin
+rdesktop-nonbin_INST    = obj/$(VBOX_RDESKTOP_SRC_SUBDIR)
+rdesktop-nonbin_MODE    = a+r,u+w
+rdesktop-nonbin_SOURCES = \
+    $(foreach i,COPYING \
+                README \
+                configure.ac \
+                Makefile.in \
+                proto.head \
+                proto.tail \
+                rdesktop.spec \
+                keymaps/common \
+                keymaps/modifiers \
+                keymaps/convert-map \
+                doc/HACKING \
+                doc/AUTHORS \
+                doc/TODO \
+                doc/ChangeLog \
+                doc/keymapping.txt \
+                doc/keymap-names.txt \
+                doc/ipv6.txt \
+                doc/licensing.txt \
+                doc/patches.txt \
+                doc/redirection.txt \
+                doc/rdesktop.1 \
+                vrdp/rdpusb.c \
+                vrdp/runtime.h \
+                vrdp/vrdpusb.h, \
+            client/$i=>$i) \
+    $(PATH_ROOT)/include/VBox/vusb.h=>vrdp/vusb.h \
+    $(VBOX_PATH_DEVICES_USB)/linux/USBProxyDevice-linux.cpp=>vrdp/USBProxyDevice-linux.c \
+    $(VBOX_PATH_DEVICES_USB)/USBProxyDevice.h=>vrdp/USBProxyDevice.h \
+    $(foreach i,*.c *.h keymaps/?? keymaps/??-??, \
+        $(foreach j,$(wildcard $(VBOX_PATH_RDESKTOP_SRC)/$i), \
+            client/$(dir $i)$(notdir $j)=>$(dir $i)$(notdir $j)))
 
 $(PATH_BIN)/rdesktop-vrdp.tar.gz: \
-		$(addprefix $(PATH_ROOT)/src/VBox/RDP/client/,$(rdesktop-vrdp_TARSOURCES)) \
-		| $(PATH_TARGET)/$(VBOX_RDESKTOP_SRC_SUBDIR)
+		rdesktop-bin \
+		rdesktop-nonbin
 	$(call MSG_TOOL,tar/gzip,,$@)
-	$(QUIET)cd $(PATH_TARGET) && tar -chf - $(addprefix $(VBOX_RDESKTOP_SRC_SUBDIR)/,$(rdesktop-vrdp_TARSOURCES)) | gzip - > $@
-
+	$(QUIET)cd $(PATH_TARGET) && tar -cf - $(VBOX_RDESKTOP_SRC_SUBDIR) | gzip - > $@
Index: trunk/src/VBox/RDP/client/vrdp/USBProxyDevice-linux.c
===================================================================
--- trunk/src/VBox/RDP/client/vrdp/USBProxyDevice-linux.c	(revision 31538)
+++ trunk/src/VBox/RDP/client/vrdp/USBProxyDevice-linux.c	(revision 31557)
@@ -16,1965 +16,3 @@
  */
 
-/* START */
-
-/*******************************************************************************
-*   Defined Constants And Macros                                               *
-*******************************************************************************/
-/** Define NO_PORT_RESET to skip the slow and broken linux port reset.
- * Resetting will break PalmOne. */
-#define NO_PORT_RESET
-/** Define NO_LOGICAL_RECONNECT to skip the broken logical reconnect handling. */
-#define NO_LOGICAL_RECONNECT
-
-
-/*******************************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#define LOG_GROUP LOG_GROUP_DRV_USBPROXY
-#ifndef RDESKTOP
-# include <iprt/stdint.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/vfs.h>
-#include <sys/ioctl.h>
-#include <sys/poll.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#ifdef VBOX_WITH_LINUX_COMPILER_H
-# include <linux/compiler.h>
-#endif
-#include <linux/usbdevice_fs.h>
-/*
- * Backlevel 2.4 headers doesn't have these two defines.
- * They were added some time between 2.4.21 and 2.4.26, probably in 2.4.23.
- */
-#ifndef USBDEVFS_DISCONNECT
-# define USBDEVFS_DISCONNECT        _IO('U', 22)
-# define USBDEVFS_CONNECT           _IO('U', 23)
-#endif
-
-#ifndef USBDEVFS_URB_SHORT_NOT_OK
-# define USBDEVFS_URB_SHORT_NOT_OK  0 /* rhel3 doesn't have this. darn! */
-#endif
-
-
-/* FedoraCore 4 does not have the bit defined by default. */
-#ifndef POLLWRNORM
-# define POLLWRNORM 0x0100
-#endif
-
-#ifndef RDESKTOP
-# include <VBox/pdm.h>
-# include <VBox/err.h>
-# include <VBox/log.h>
-# include <iprt/alloc.h>
-# include <iprt/assert.h>
-# include <iprt/asm.h>
-# include <iprt/ctype.h>
-# include <iprt/file.h>
-# include <iprt/linux/sysfs.h>
-# include <iprt/stream.h>
-# include <iprt/string.h>
-# include <iprt/thread.h>
-# include <iprt/time.h>
-# include "../USBProxyDevice.h"
-#else
-
-# include "../rdesktop.h"
-# include "runtime.h"
-# include "USBProxyDevice.h"
-# ifdef VBOX_USB_WITH_SYSFS
-#  include "sysfs.h"
-# endif
-#endif
-
-
-/*******************************************************************************
-*   Structures and Typedefs                                                    *
-*******************************************************************************/
-/**
- * Wrapper around the linux urb request structure.
- * This is required to track in-flight and landed URBs.
- */
-typedef struct USBPROXYURBLNX
-{
-    /** The kernel URB data */
-    struct usbdevfs_urb     KUrb;
-    /** Space filler for the isochronous packets. */
-    struct usbdevfs_iso_packet_desc aIsocPktsDonUseTheseUseTheOnesInKUrb[8];
-    /** The millisecond timestamp when this URB was submitted. */
-    uint64_t                u64SubmitTS;
-    /** Pointer to the next linux URB. */
-    struct USBPROXYURBLNX  *pNext;
-    /** Pointer to the previous linux URB. */
-    struct USBPROXYURBLNX  *pPrev;
-    /** If we've split the VUSBURB up into multiple linux URBs, this is points to the head. */
-    struct USBPROXYURBLNX  *pSplitHead;
-    /** The next linux URB if split up. */
-    struct USBPROXYURBLNX  *pSplitNext;
-    /** Whether it has timed out and should be shot down on the next failing reap call. */
-    bool                    fTimedOut;
-    /** Indicates that this URB has been canceled by timeout and should return an CRC error. */
-    bool                    fCanceledByTimedOut;
-    /** Don't report these back. */
-    bool                    fCanceledBySubmit;
-    /** This split element is reaped. */
-    bool                    fSplitElementReaped;
-    /** Size to transfer in remaining fragments of a split URB */
-    uint32_t                cbSplitRemaining;
-} USBPROXYURBLNX, *PUSBPROXYURBLNX;
-
-/**
- * Data for the linux usb proxy backend.
- */
-typedef struct USBPROXYDEVLNX
-{
-    /** The open file. */
-    RTFILE              File;
-    /** Critical section protecting the two lists. */
-    RTCRITSECT          CritSect;
-    /** The list of free linux URBs. Singly linked. */
-    PUSBPROXYURBLNX     pFreeHead;
-    /** The list of active linux URBs. Doubly linked.
-     * We must maintain this so we can properly reap URBs of a detached device.
-     * Only the split head will appear in this list. */
-    PUSBPROXYURBLNX     pInFlightHead;
-    /** The list of landed linux URBs. Doubly linked.
-     * Only the split head will appear in this list. */
-    PUSBPROXYURBLNX     pTaxingHead;
-    /** The tail of the landed linux URBs. */
-    PUSBPROXYURBLNX     pTaxingTail;
-    /** Are we using sysfs to find the active configuration? */
-    bool                fUsingSysfs;
-    /** The device node/sysfs path of the device.
-     * Used to figure out the configuration after a reset. */
-    char                szPath[1];
-} USBPROXYDEVLNX, *PUSBPROXYDEVLNX;
-
-
-/*******************************************************************************
-*   Internal Functions                                                         *
-*******************************************************************************/
-static int usbProxyLinuxDoIoCtl(PUSBPROXYDEV pProxyDev, unsigned long iCmd, void *pvArg, bool fHandleNoDev, uint32_t cTries);
-static void usbProxLinuxUrbUnplugged(PUSBPROXYDEV pProxyDev);
-static void usbProxyLinuxSetConnected(PUSBPROXYDEV pProyxDev, int iIf, bool fConnect, bool fQuiet);
-static PUSBPROXYURBLNX usbProxyLinuxUrbAlloc(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pSplitHead);
-static void usbProxyLinuxUrbFree(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pUrbLnx);
-static void usbProxyLinuxUrbFreeSplitList(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pUrbLnx);
-static int usbProxyLinuxFindActiveConfig(PUSBPROXYDEV pProxyDev, const char *pszPath, int *piFirstCfg);
-
-
-
-/**
- * Wrapper for the ioctl call.
- *
- * This wrapper will repeate the call if we get an EINTR or EAGAIN. It can also
- * handle ENODEV (detached device) errors.
- *
- * @returns whatever ioctl returns.
- * @param   pProxyDev       The proxy device.
- * @param   iCmd            The ioctl command / function.
- * @param   pvArg           The ioctl argument / data.
- * @param   fHandleNoDev    Whether to handle ENODEV.
- * @param   cTries          The number of retries. Use UINT32_MAX for (kind of) indefinite retries.
- * @internal
- */
-static int usbProxyLinuxDoIoCtl(PUSBPROXYDEV pProxyDev, unsigned long iCmd, void *pvArg, bool fHandleNoDev, uint32_t cTries)
-{
-    int rc;
-    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
-    do
-    {
-        do
-        {
-            rc = ioctl(pDevLnx->File, iCmd, pvArg);
-            if (rc >= 0)
-                return rc;
-        } while (errno == EINTR);
-
-        if (errno == ENODEV && fHandleNoDev)
-        {
-            usbProxLinuxUrbUnplugged(pProxyDev);
-            Log(("usb-linux: ENODEV -> unplugged. pProxyDev=%s\n", usbProxyGetName(pProxyDev)));
-            errno = ENODEV;
-            break;
-        }
-        if (errno != EAGAIN)
-            break;
-    } while (cTries-- > 0);
-
-    return rc;
-}
-
-
-/**
- * The device has been unplugged.
- * Cancel all in-flight URBs and put them up for reaping.
- */
-static void usbProxLinuxUrbUnplugged(PUSBPROXYDEV pProxyDev)
-{
-    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
-
-    /*
-     * Shoot down all flying URBs.
-     */
-    RTCritSectEnter(&pDevLnx->CritSect);
-    pProxyDev->fDetached = true;
-
-    PUSBPROXYURBLNX pUrbTaxing = NULL;
-    PUSBPROXYURBLNX pUrbLnx = pDevLnx->pInFlightHead;
-    pDevLnx->pInFlightHead = NULL;
-    while (pUrbLnx)
-    {
-        PUSBPROXYURBLNX pCur = pUrbLnx;
-        pUrbLnx = pUrbLnx->pNext;
-
-        ioctl(pDevLnx->File, USBDEVFS_DISCARDURB, &pCur->KUrb); /* not sure if this is required.. */
-        if (!pCur->KUrb.status)
-            pCur->KUrb.status = -ENODEV;
-
-        /* insert into the taxing list. */
-        pCur->pPrev = NULL;
-        if (    !pCur->pSplitHead
-            ||  pCur == pCur->pSplitHead)
-        {
-            pCur->pNext = pUrbTaxing;
-            if (pUrbTaxing)
-                pUrbTaxing->pPrev = pCur;
-            pUrbTaxing = pCur;
-        }
-        else
-            pCur->pNext = NULL;
-    }
-
-    /* Append the URBs we shot down to the taxing queue. */
-    if (pUrbTaxing)
-    {
-        pUrbTaxing->pPrev = pDevLnx->pTaxingTail;
-        if (pUrbTaxing->pPrev)
-            pUrbTaxing->pPrev->pNext = pUrbTaxing;
-        else
-            pDevLnx->pTaxingTail = pDevLnx->pTaxingHead = pUrbTaxing;
-    }
-
-    RTCritSectLeave(&pDevLnx->CritSect);
-}
-
-
-/**
- * Set the connect state seen by kernel drivers
- * @internal
- */
-static void usbProxyLinuxSetConnected(PUSBPROXYDEV pProxyDev, int iIf, bool fConnect, bool fQuiet)
-{
-    if (    iIf >= 32
-        ||  !(pProxyDev->fMaskedIfs & RT_BIT(iIf)))
-    {
-        struct usbdevfs_ioctl IoCtl;
-        if (!fQuiet)
-            LogFlow(("usbProxyLinuxSetConnected: pProxyDev=%s iIf=%#x fConnect=%RTbool\n",
-                     usbProxyGetName(pProxyDev), iIf, fConnect));
-
-        IoCtl.ifno = iIf;
-        IoCtl.ioctl_code = fConnect ? USBDEVFS_CONNECT : USBDEVFS_DISCONNECT;
-        IoCtl.data = NULL;
-        if (    usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_IOCTL, &IoCtl, true, UINT32_MAX)
-            &&  !fQuiet)
-            Log(("usbProxyLinuxSetConnected: failure, errno=%d. pProxyDev=%s\n",
-                 errno, usbProxyGetName(pProxyDev)));
-    }
-}
-
-
-/**
- * Allocates a linux URB request structure.
- * @returns Pointer to an active URB request.
- * @returns NULL on failure.
- * @param   pProxyDev       The proxy device instance.
- * @param   pSplitHead      The split list head if allocating for a split list.
- */
-static PUSBPROXYURBLNX usbProxyLinuxUrbAlloc(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pSplitHead)
-{
-    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
-    PUSBPROXYURBLNX pUrbLnx;
-
-    RTCritSectEnter(&pDevLnx->CritSect);
-
-    /*
-     * Try remove a linux URB from the free list, if none there allocate a new one.
-     */
-    pUrbLnx = pDevLnx->pFreeHead;
-    if (pUrbLnx)
-        pDevLnx->pFreeHead = pUrbLnx->pNext;
-    else
-    {
-        RTCritSectLeave(&pDevLnx->CritSect);
-        pUrbLnx = (PUSBPROXYURBLNX)RTMemAlloc(sizeof(*pUrbLnx));
-        if (!pUrbLnx)
-            return NULL;
-        RTCritSectEnter(&pDevLnx->CritSect);
-    }
-    pUrbLnx->pSplitHead = pSplitHead;
-    pUrbLnx->pSplitNext = NULL;
-    pUrbLnx->fTimedOut = false;
-    pUrbLnx->fCanceledByTimedOut = false;
-    pUrbLnx->fCanceledBySubmit = false;
-    pUrbLnx->fSplitElementReaped = false;
-
-    /*
-     * Link it into the active list
-     */
-    if (!pSplitHead)
-    {
-        pUrbLnx->pPrev = NULL;
-        pUrbLnx->pNext = pDevLnx->pInFlightHead;
-        if (pUrbLnx->pNext)
-            pUrbLnx->pNext->pPrev = pUrbLnx;
-        pDevLnx->pInFlightHead = pUrbLnx;
-    }
-    else
-        pUrbLnx->pPrev = pUrbLnx->pNext = (PUSBPROXYURBLNX)0xdead;
-
-    RTCritSectLeave(&pDevLnx->CritSect);
-    return pUrbLnx;
-}
-
-
-/**
- * Frees a linux URB request structure.
- *
- * @param   pProxyDev       The proxy device instance.
- * @param   pUrbLnx         The linux URB to free.
- */
-static void usbProxyLinuxUrbFree(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pUrbLnx)
-{
-    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
-
-    RTCritSectEnter(&pDevLnx->CritSect);
-
-    /*
-     * Remove from the active list.
-     */
-    if (    !pUrbLnx->pSplitHead
-        ||  pUrbLnx->pSplitHead == pUrbLnx)
-    {
-        if (pUrbLnx->pNext)
-            pUrbLnx->pNext->pPrev = pUrbLnx->pPrev;
-        if (pUrbLnx->pPrev)
-            pUrbLnx->pPrev->pNext = pUrbLnx->pNext;
-        else
-            pDevLnx->pInFlightHead  = pUrbLnx->pNext;
-    }
-    pUrbLnx->pSplitHead = pUrbLnx->pSplitNext = NULL;
-
-    /*
-     * Link it into the free list.
-     */
-    pUrbLnx->pPrev = NULL;
-    pUrbLnx->pNext = pDevLnx->pFreeHead;
-    pDevLnx->pFreeHead = pUrbLnx;
-
-    RTCritSectLeave(&pDevLnx->CritSect);
-}
-
-
-/**
- * Frees split list of a linux URB request structure.
- *
- * @param   pProxyDev       The proxy device instance.
- * @param   pUrbLnx         A linux URB to in the split list to be freed.
- */
-static void usbProxyLinuxUrbFreeSplitList(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pUrbLnx)
-{
-    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
-
-    RTCritSectEnter(&pDevLnx->CritSect);
-
-    pUrbLnx = pUrbLnx->pSplitHead;
-    Assert(pUrbLnx);
-    while (pUrbLnx)
-    {
-        PUSBPROXYURBLNX pFree = pUrbLnx;
-        pUrbLnx = pUrbLnx->pSplitNext;
-        Assert(pFree->pSplitHead);
-        usbProxyLinuxUrbFree(pProxyDev, pFree);
-    }
-
-    RTCritSectLeave(&pDevLnx->CritSect);
-}
-
-
-/**
- * This finds the device in the /proc/bus/usb/bus/addr file and finds
- * the config with an asterix.
- *
- * @returns The Cfg#.
- * @returns -1 if no active config.
- * @param   pszDevNode      The path to the device. We infere the location of
- *                          the devices file, which bus and device number we're
- *                          looking for.
- * @param   iFirstCfg       The first configuration. (optional)
- * @internal
- */
-static int usbProxyLinuxFindActiveConfigUsbfs(PUSBPROXYDEV pProxyDev, const char *pszDevNode, int *piFirstCfg)
-{
-    /*
-     * Set return defaults.
-     */
-    int iActiveCfg = -1;
-    if (piFirstCfg)
-        *piFirstCfg = 1;
-
-    /*
-     * Parse the usbfs device node path and turn it into a path to the "devices" file,
-     * picking up the device number and bus along the way.
-     */
-    size_t cchDevNode = strlen(pszDevNode);
-    char *pszDevices = (char *)RTMemDupEx(pszDevNode, cchDevNode, sizeof("devices"));
-    AssertReturn(pszDevices, iActiveCfg);
-
-    /* the device number */
-    char *psz = pszDevices + cchDevNode;
-    while (*psz != '/')
-        psz--;
-    Assert(pszDevices < psz);
-    uint32_t uDev;
-    int rc = RTStrToUInt32Ex(psz + 1, NULL, 10, &uDev);
-    if (RT_SUCCESS(rc))
-    {
-        /* the bus number */
-        *psz-- = '\0';
-        while (*psz != '/')
-            psz--;
-        Assert(pszDevices < psz);
-        uint32_t uBus;
-        rc = RTStrToUInt32Ex(psz + 1, NULL, 10, &uBus);
-        if (RT_SUCCESS(rc))
-        {
-            strcpy(psz + 1, "devices");
-
-            /*
-             * Open and scan the devices file.
-             * We're ASSUMING that each device starts off with a 'T:' line.
-             */
-            PRTSTREAM pFile;
-            rc = RTStrmOpen(pszDevices, "r", &pFile);
-            if (RT_SUCCESS(rc))
-            {
-                char szLine[1024];
-                while (RT_SUCCESS(RTStrmGetLine(pFile, szLine, sizeof(szLine))))
-                {
-                    /* we're only interested in 'T:' lines. */
-                    psz = RTStrStripL(szLine);
-                    if (psz[0] != 'T' || psz[1] != ':')
-                        continue;
-
-                    /* Skip ahead to 'Bus' and compare */
-                    psz = RTStrStripL(psz + 2); Assert(!strncmp(psz, "Bus=", 4));
-                    psz = RTStrStripL(psz + 4);
-                    char *pszNext;
-                    uint32_t u;
-                    rc = RTStrToUInt32Ex(psz, &pszNext, 10, &u); AssertRC(rc);
-                    if (RT_FAILURE(rc))
-                        continue;
-                    if (u != uBus)
-                        continue;
-
-                    /* Skip ahead to 'Dev#' and compare */
-                    psz = strstr(psz, "Dev#="); Assert(psz);
-                    if (!psz)
-                        continue;
-                    psz = RTStrStripL(psz + 5);
-                    rc = RTStrToUInt32Ex(psz, &pszNext, 10, &u); AssertRC(rc);
-                    if (RT_FAILURE(rc))
-                        continue;
-                    if (u != uDev)
-                        continue;
-
-                    /*
-                     * Ok, we've found the device.
-                     * Scan until we find a selected configuration, the next device, or EOF.
-                     */
-                    while (RT_SUCCESS(RTStrmGetLine(pFile, szLine, sizeof(szLine))))
-                    {
-                        psz = RTStrStripL(szLine);
-                        if (psz[0] == 'T')
-                            break;
-                        if (psz[0] != 'C' || psz[1] != ':')
-                            continue;
-                        const bool fActive = psz[2] == '*';
-                        if (!fActive && !piFirstCfg)
-                            continue;
-
-                        /* Get the 'Cfg#' value. */
-                        psz = strstr(psz, "Cfg#="); Assert(psz);
-                        if (psz)
-                        {
-                            psz = RTStrStripL(psz + 5);
-                            rc = RTStrToUInt32Ex(psz, &pszNext, 10, &u); AssertRC(rc);
-                            if (RT_SUCCESS(rc))
-                            {
-                                if (piFirstCfg)
-                                {
-                                    *piFirstCfg = u;
-                                    piFirstCfg = NULL;
-                                }
-                                if (fActive)
-                                    iActiveCfg = u;
-                            }
-                        }
-                        if (fActive)
-                            break;
-                    }
-                    break;
-                }
-                RTStrmClose(pFile);
-            }
-        }
-    }
-    RTMemFree(pszDevices);
-
-    return iActiveCfg;
-}
-
-
-/**
- * This finds the active configuration from sysfs.
- *
- * @returns The Cfg#.
- * @returns -1 if no active config.
- * @param   pszPath         The sysfs path for the device.
- * @param   piFirstCfg      The first configuration. (optional)
- * @internal
- */
-static int usbProxyLinuxFindActiveConfigSysfs(PUSBPROXYDEV pProxyDev, const char *pszPath, int *piFirstCfg)
-{
-#ifdef VBOX_USB_WITH_SYSFS
-    if (piFirstCfg != NULL)
-        *piFirstCfg = pProxyDev->paCfgDescs != NULL
-                    ? pProxyDev->paCfgDescs[0].Core.bConfigurationValue
-                    : 1;
-    return RTLinuxSysFsReadIntFile(10, "%s/bConfigurationValue", pszPath); /* returns -1 on failure */
-#else  /* !VBOX_USB_WITH_SYSFS */
-    return -1;
-#endif /* !VBOX_USB_WITH_SYSFS */
-}
-
-
-/**
- * This finds the active configuration.
- *
- * @returns The Cfg#.
- * @returns -1 if no active config.
- * @param   pszPath         The sysfs path for the device, or the usbfs device
- *                          node path.
- * @param   iFirstCfg       The first configuration. (optional)
- * @internal
- */
-static int usbProxyLinuxFindActiveConfig(PUSBPROXYDEV pProxyDev, const char *pszPath, int *piFirstCfg)
-{
-    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
-    if (pDevLnx->fUsingSysfs)
-        return usbProxyLinuxFindActiveConfigSysfs(pProxyDev, pszPath, piFirstCfg);
-    return usbProxyLinuxFindActiveConfigUsbfs(pProxyDev, pszPath, piFirstCfg);
-}
-
-
-/**
- * Extracts the Linux file descriptor associated with the kernel USB device.
- * This is used by rdesktop-vrdp for polling for events.
- * @returns  the FD, or asserts and returns -1 on error
- * @param    pProxyDev    The device instance
- */
-RTDECL(int) USBProxyDeviceLinuxGetFD(PUSBPROXYDEV pProxyDev)
-{
-    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
-    AssertReturn(pDevLnx->File != NIL_RTFILE, -1);
-    return pDevLnx->File;
-}
-
-
-/**
- * Opens the device file.
- *
- * @returns VBox status code.
- * @param   pProxyDev       The device instance.
- * @param   pszAddress      If we are using usbfs, this is the path to the
- *                          device.  If we are using sysfs, this is a string of
- *                          the form "sysfs:<sysfs path>//device:<device node>".
- *                          In the second case, the two paths are guaranteed
- *                          not to contain the substring "//".
- * @param   pvBackend       Backend specific pointer, unused for the linux backend.
- */
-static int usbProxyLinuxOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, void *pvBackend)
-{
-    LogFlow(("usbProxyLinuxOpen: pProxyDev=%p pszAddress=%s\n", pProxyDev, pszAddress));
-    const char *pszDevNode;
-    const char *pszPath;
-    size_t      cchPath;
-    bool        fUsingSysfs;
-
-    /*
-     * Are we using sysfs or usbfs?
-     */
-#ifdef VBOX_USB_WITH_SYSFS
-    fUsingSysfs = strncmp(pszAddress, "sysfs:", sizeof("sysfs:") - 1) == 0;
-    if (fUsingSysfs)
-    {
-        pszDevNode = strstr(pszAddress, "//device:");
-        if (!pszDevNode)
-        {
-            LogRel(("usbProxyLinuxOpen: Invalid device address: '%s'\n", pszAddress));
-            pProxyDev->Backend.pv = NULL;
-            return VERR_INVALID_PARAMETER;
-        }
-
-        pszPath = pszAddress + sizeof("sysfs:") - 1;
-        cchPath = pszDevNode - pszPath;
-        pszDevNode += sizeof("//device:") - 1;
-    }
-    else
-#endif  /* VBOX_USB_WITH_SYSFS */
-    {
-#ifndef VBOX_USB_WITH_SYSFS
-        fUsingSysfs = false;
-#endif
-        pszPath = pszDevNode = pszAddress;
-        cchPath = strlen(pszPath);
-    }
-
-    /*
-     * Try open the device node.
-     */
-    RTFILE File;
-    int rc = RTFileOpen(&File, pszDevNode, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
-    if (RT_SUCCESS(rc))
-    {
-        /*
-         * Allocate and initialize the linux backend data.
-         */
-        PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)RTMemAllocZVar(sizeof(*pDevLnx) + cchPath);
-        if (pDevLnx)
-        {
-            pDevLnx->fUsingSysfs = fUsingSysfs;
-            memcpy(&pDevLnx->szPath[0], pszPath, cchPath);
-            pDevLnx->szPath[cchPath] = '\0';
-            pDevLnx->File = File;
-            rc = RTCritSectInit(&pDevLnx->CritSect);
-            if (RT_SUCCESS(rc))
-            {
-                pProxyDev->Backend.pv = pDevLnx;
-
-                LogFlow(("usbProxyLinuxOpen(%p, %s): returns successfully File=%d iActiveCfg=%d\n",
-                         pProxyDev, pszAddress, pDevLnx->File, pProxyDev->iActiveCfg));
-
-                return VINF_SUCCESS;
-            }
-
-            RTMemFree(pDevLnx);
-        }
-        else
-            rc = VERR_NO_MEMORY;
-        RTFileClose(File);
-    }
-    else if (rc == VERR_ACCESS_DENIED)
-        rc = VERR_VUSB_USBFS_PERMISSION;
-
-    Log(("usbProxyLinuxOpen(%p, %s) failed, rc=%Rrc!\n", pProxyDev, pszAddress, rc));
-    pProxyDev->Backend.pv = NULL;
-
-    NOREF(pvBackend);
-    return rc;
-}
-
-
-/**
- * Claims all the interfaces and figures out the
- * current configuration.
- *
- * @returns VINF_SUCCESS.
- * @param   pProxyDev       The proxy device.
- */
-static int usbProxyLinuxInit(PUSBPROXYDEV pProxyDev)
-{
-    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
-
-    /*
-     * Brute force rulez.
-     * usbProxyLinuxSetConnected check for masked interfaces.
-     */
-    unsigned iIf;
-    for (iIf = 0; iIf < 256; iIf++)
-        usbProxyLinuxSetConnected(pProxyDev, iIf, false, true);
-
-    /*
-     * Determin the active configuration.
-     *
-     * If there isn't any active configuration, we will get EHOSTUNREACH (113) errors
-     * when trying to read the device descriptors in usbProxyDevCreate. So, we'll make
-     * the first one active (usually 1) then.
-     */
-    pProxyDev->cIgnoreSetConfigs = 1;
-    int iFirstCfg;
-    pProxyDev->iActiveCfg = usbProxyLinuxFindActiveConfig(pProxyDev, pDevLnx->szPath, &iFirstCfg);
-    if (pProxyDev->iActiveCfg == -1)
-    {
-        usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_SETCONFIGURATION, &iFirstCfg, false, UINT32_MAX);
-        pProxyDev->iActiveCfg = usbProxyLinuxFindActiveConfig(pProxyDev, pDevLnx->szPath, NULL);
-        Log(("usbProxyLinuxInit: No active config! Tried to set %d: iActiveCfg=%d\n", iFirstCfg, pProxyDev->iActiveCfg));
-    }
-    else
-        Log(("usbProxyLinuxInit(%p): iActiveCfg=%d\n", pProxyDev, pProxyDev->iActiveCfg));
-    return VINF_SUCCESS;
-}
-
-
-/**
- * Closes the proxy device.
- */
-static void usbProxyLinuxClose(PUSBPROXYDEV pProxyDev)
-{
-    LogFlow(("usbProxyLinuxClose: pProxyDev=%s\n", usbProxyGetName(pProxyDev)));
-    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
-    Assert(pDevLnx);
-    if (!pDevLnx)
-        return;
-
-    /*
-     * Try put the device in a state which linux can cope with before we release it.
-     * Resetting it would be a nice start, although we must remember
-     * that it might have been disconnected...
-     *
-     * Don't reset if we're masking interfaces or if construction failed.
-     */
-    if (pProxyDev->fInited)
-    {
-        /* ASSUMES: thread == EMT */
-        if (    pProxyDev->fMaskedIfs
-            ||  !usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_RESET, NULL, false, 10))
-        {
-            /* Connect drivers. */
-            unsigned iIf;
-            for (iIf = 0; iIf < 256; iIf++)
-                usbProxyLinuxSetConnected(pProxyDev, iIf, true, true);
-            LogRel(("USB: Successfully reset device pProxyDev=%s\n", usbProxyGetName(pProxyDev)));
-        }
-        else if (errno != ENODEV)
-            LogRel(("USB: Reset failed, errno=%d, pProxyDev=%s.\n", errno, usbProxyGetName(pProxyDev)));
-        else
-            Log(("USB: Reset failed, errno=%d (ENODEV), pProxyDev=%s.\n", errno, usbProxyGetName(pProxyDev)));
-    }
-
-    /*
-     * Now we can free all the resources and close the device.
-     */
-    RTCritSectDelete(&pDevLnx->CritSect);
-
-    PUSBPROXYURBLNX pUrbLnx;
-    while ((pUrbLnx = pDevLnx->pInFlightHead) != NULL)
-    {
-        pDevLnx->pInFlightHead = pUrbLnx->pNext;
-        if (    usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_DISCARDURB, &pUrbLnx->KUrb, false, UINT32_MAX)
-            &&  errno != ENODEV
-            &&  errno != ENOENT)
-            AssertMsgFailed(("errno=%d\n", errno));
-        if (pUrbLnx->pSplitHead)
-        {
-            PUSBPROXYURBLNX pCur = pUrbLnx->pSplitNext;
-            while (pCur)
-            {
-                PUSBPROXYURBLNX pFree = pCur;
-                pCur = pFree->pSplitNext;
-                if (    !pFree->fSplitElementReaped
-                    &&  usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_DISCARDURB, &pFree->KUrb, false, UINT32_MAX)
-                    &&  errno != ENODEV
-                    &&  errno != ENOENT)
-                    AssertMsgFailed(("errno=%d\n", errno));
-                RTMemFree(pFree);
-            }
-        }
-        else
-            Assert(!pUrbLnx->pSplitNext);
-        RTMemFree(pUrbLnx);
-    }
-
-    while ((pUrbLnx = pDevLnx->pFreeHead) != NULL)
-    {
-        pDevLnx->pFreeHead = pUrbLnx->pNext;
-        RTMemFree(pUrbLnx);
-    }
-
-    RTFileClose(pDevLnx->File);
-    pDevLnx->File = NIL_RTFILE;
-
-    RTMemFree(pDevLnx);
-    pProxyDev->Backend.pv = NULL;
-    LogFlow(("usbProxyLinuxClose: returns\n"));
-}
-
-
-#if defined(NO_PORT_RESET) && !defined(NO_LOGICAL_RECONNECT)
-/**
- * Look for the logically reconnected device.
- * After 5 seconds we'll give up.
- *
- * @returns VBox status code.
- * @thread  Reset thread or EMT.
- */
-static int usb_reset_logical_reconnect(PUSBPROXYDEV pDev)
-{
-    FILE *          pFile;
-    uint64_t        u64StartTS = RTTimeMilliTS();
-
-    Log2(("usb_reset_logical_reconnect: pDev=%p:{.bBus=%#x, .bDevNum=%#x, .idVendor=%#x, .idProduct=%#x, .bcdDevice=%#x, .u64SerialHash=%#llx .bDevNumParent=%#x .bPort=%#x .bLevel=%#x}\n",
-          pDev, pDev->Info.bBus, pDev->Info.bDevNum, pDev->Info.idVendor, pDev->Info.idProduct, pDev->Info.bcdDevice,
-          pDev->Info.u64SerialHash, pDev->Info.bDevNumParent, pDev->Info.bPort, pDev->Info.bLevel));
-
-    /* First, let hubd get a chance to logically reconnect the device. */
-    if (!RTThreadYield())
-        RTThreadSleep(1);
-
-    /*
-     * Search for the new device address.
-     */
-    pFile = get_devices_file();
-    if (!pFile)
-        return VERR_FILE_NOT_FOUND;
-
-    /*
-     * Loop until found or 5seconds have elapsed.
-     */
-    for (;;) {
-        struct pollfd   pfd;
-        uint8_t     tmp;
-        int         rc;
-        char        buf[512];
-        uint64_t    u64Elapsed;
-        int         got = 0;
-        struct usb_dev_entry id = {0};
-
-        /*
-         * Since this is kernel ABI we don't need to be too fussy about
-         * the parsing.
-         */
-        while (fgets(buf, sizeof(buf), pFile)) {
-            char *psz = strchr(buf, '\n');
-            if ( psz == NULL ) {
-                AssertMsgFailed(("usb_reset_logical_reconnect: Line to long!!\n"));
-                break;
-            }
-            *psz = '\0';
-
-            switch ( buf[0] ) {
-            case 'T': /* topology */
-                /* Check if we've got enough for a device. */
-                if (got >= 2) {
-                    Log2(("usb_reset_logical_reconnect: {.bBus=%#x, .bDevNum=%#x, .idVendor=%#x, .idProduct=%#x, .bcdDevice=%#x, .u64SerialHash=%#llx, .bDevNumParent=%#x, .bPort=%#x, .bLevel=%#x}\n",
-                          id.bBus, id.bDevNum, id.idVendor, id.idProduct, id.bcdDevice, id.u64SerialHash, id.bDevNumParent, id.bPort, id.bLevel));
-                    if (    id.bDevNumParent == pDev->Info.bDevNumParent
-                        &&  id.idVendor == pDev->Info.idVendor
-                        &&  id.idProduct == pDev->Info.idProduct
-                        &&  id.bcdDevice == pDev->Info.bcdDevice
-                        &&  id.u64SerialHash == pDev->Info.u64SerialHash
-                        &&  id.bBus == pDev->Info.bBus
-                        &&  id.bPort == pDev->Info.bPort
-                        &&  id.bLevel == pDev->Info.bLevel) {
-                        goto l_found;
-                    }
-                }
-
-                /* restart */
-                got = 0;
-                memset(&id, 0, sizeof(id));
-
-                /*T:  Bus=04 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5 MxCh= 0*/
-                Log2(("usb_reset_logical_reconnect: %s\n", buf));
-                buf[10] = '\0';
-                if ( !get_u8(buf + 8, &id.bBus) )
-                    break;
-                buf[49] = '\0';
-                psz = buf + 46;
-                while ( *psz == ' ' )
-                    psz++;
-                if ( !get_u8(psz, &id.bDevNum) )
-                    break;
-
-                buf[17] = '\0';
-                if ( !get_u8(buf + 15, &id.bLevel) )
-                    break;
-                buf[25] = '\0';
-                if ( !get_u8(buf + 23, &id.bDevNumParent) )
-                    break;
-                buf[33] = '\0';
-                if ( !get_u8(buf + 31, &id.bPort) )
-                    break;
-                got++;
-                break;
-
-            case 'P': /* product */
-                Log2(("usb_reset_logical_reconnect: %s\n", buf));
-                buf[15] = '\0';
-                if ( !get_x16(buf + 11, &id.idVendor) )
-                    break;
-                buf[27] = '\0';
-                if ( !get_x16(buf + 23, &id.idProduct) )
-                    break;
-                buf[34] = '\0';
-                if ( buf[32] == ' ' )
-                    buf[32] = '0';
-                id.bcdDevice = 0;
-                if ( !get_x8(buf + 32, &tmp) )
-                    break;
-                id.bcdDevice = tmp << 8;
-                if ( !get_x8(buf + 35, &tmp) )
-                    break;
-                id.bcdDevice |= tmp;
-                got++;
-                break;
-
-            case 'S': /* String descriptor */
-                /* Skip past "S:" and then the whitespace */
-                for(psz = buf + 2; *psz != '\0'; psz++)
-                    if ( !RT_C_IS_SPACE(*psz) )
-                        break;
-
-                /* If it is a serial number string, skip past
-                 * "SerialNumber="
-                 */
-                if ( strncmp(psz, "SerialNumber=", sizeof("SerialNumber=") - 1) )
-                    break;
-
-                Log2(("usb_reset_logical_reconnect: %s\n", buf));
-                psz += sizeof("SerialNumber=") - 1;
-
-                usb_serial_hash(psz, &id.u64SerialHash);
-                break;
-            }
-        }
-
-        /*
-         * Check last.
-         */
-        if (    got >= 2
-            &&  id.bDevNumParent == pDev->Info.bDevNumParent
-            &&  id.idVendor == pDev->Info.idVendor
-            &&  id.idProduct == pDev->Info.idProduct
-            &&  id.bcdDevice == pDev->Info.bcdDevice
-            &&  id.u64SerialHash == pDev->Info.u64SerialHash
-            &&  id.bBus == pDev->Info.bBus
-            &&  id.bPort == pDev->Info.bPort
-            &&  id.bLevel == pDev->Info.bLevel) {
-        l_found:
-            /* close the existing file descriptor. */
-            RTFileClose(pDevLnx->File);
-            pDevLnx->File = NIL_RTFILE;
-
-            /* open stuff at the new address. */
-            pDev->Info = id;
-            if (usbProxyLinuxOpen(pDev, &id))
-                return VINF_SUCCESS;
-            break;
-        }
-
-        /*
-         * Wait for a while and then check the file again.
-         */
-        u64Elapsed = RTTimeMilliTS() - u64StartTS;
-        if (u64Elapsed >= 5000/*ms*/)
-            break; /* done */
-
-        pfd.fd = fileno(pFile);
-        pfd.events = POLLIN;
-        rc = poll(&pfd, 1, 5000 - u64Elapsed);
-        if (rc < 0) {
-            AssertMsg(errno == EINTR, ("errno=%d\n", errno));
-            RTThreadSleep(32); /* paranoia: don't eat cpu on failure */
-        }
-
-        rewind(pFile);
-    } /* for loop */
-
-    return VERR_GENERAL_FAILURE;
-}
-#endif /* !NO_PORT_RESET && !NO_LOGICAL_RECONNECT */
-
-
-/**
- * Reset a device.
- *
- * @returns VBox status code.
- * @param   pDev    The device to reset.
- */
-static int usbProxyLinuxReset(PUSBPROXYDEV pProxyDev, bool fResetOnLinux)
-{
-#ifdef NO_PORT_RESET
-    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
-
-    /*
-     * Specific device resets are NOPs.
-     * Root hub resets that affects all devices are executed.
-     *
-     * The reasoning is that when a root hub reset is done, the guest shouldn't
-     * will have to re enumerate the devices after doing this kind of reset.
-     * So, it doesn't really matter if a device is 'logically disconnected'.
-     */
-    if (    !fResetOnLinux
-        ||  pProxyDev->fMaskedIfs)
-        LogFlow(("usbProxyLinuxReset: pProxyDev=%s - NO_PORT_RESET\n", usbProxyGetName(pProxyDev)));
-    else
-    {
-        LogFlow(("usbProxyLinuxReset: pProxyDev=%s - Real Reset!\n", usbProxyGetName(pProxyDev)));
-        if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_RESET, NULL, false, 10))
-        {
-            int rc = errno;
-            Log(("usb-linux: Reset failed, rc=%Rrc errno=%d.\n", RTErrConvertFromErrno(rc), rc));
-            pProxyDev->iActiveCfg = -1;
-            return RTErrConvertFromErrno(rc);
-        }
-
-        /* find the active config - damn annoying. */
-        pProxyDev->iActiveCfg = usbProxyLinuxFindActiveConfig(pProxyDev, pDevLnx->szPath, NULL);
-        LogFlow(("usbProxyLinuxReset: returns successfully iActiveCfg=%d\n", pProxyDev->iActiveCfg));
-    }
-    pProxyDev->cIgnoreSetConfigs = 2;
-
-#else /* !NO_PORT_RESET */
-
-    /*
-     * This is the alternative, we will allways reset when asked to do so.
-     *
-     * The problem we're facing here is that on reset failure linux will do
-     * a 'logical reconnect' on the device. This will invalidate the current
-     * handle and we'll have to reopen the device. This is problematic to say
-     * the least, especially since it happens pretty often.
-     */
-    LogFlow(("usbProxyLinuxReset: pProxyDev=%s\n", usbProxyGetName(pProxyDev)));
-# ifndef NO_LOGICAL_RECONNECT
-    ASMAtomicIncU32(&g_cResetActive);
-# endif
-
-    if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_RESET, NULL, false, 10))
-    {
-        int rc = errno;
-# ifndef NO_LOGICAL_RECONNECT
-        if (rc == ENODEV)
-        {
-            /*
-             * This usually happens because of a 'logical disconnection'.
-             * So, we're in for a real treat from our excellent OS now...
-             */
-            rc2 = usb_reset_logical_reconnect(pProxyDev);
-            if (RT_FAILURE(rc2))
-                usbProxLinuxUrbUnplugged(pProxyDev);
-            if (RT_SUCCESS(rc2))
-            {
-                ASMAtomicDecU32(&g_cResetActive);
-                LogFlow(("usbProxyLinuxReset: returns success (after recovering disconnected device!)\n"));
-                return VINF_SUCCESS;
-            }
-        }
-        ASMAtomicDecU32(&g_cResetActive);
-# endif /* NO_LOGICAL_RECONNECT */
-
-        Log(("usb-linux: Reset failed, rc=%Rrc errno=%d.\n", RTErrConvertFromErrno(rc), rc));
-        pProxyDev->iActiveCfg = -1;
-        return RTErrConvertFromErrno(rc);
-    }
-
-# ifndef NO_LOGICAL_RECONNECT
-    ASMAtomicDecU32(&g_cResetActive);
-# endif
-
-    pProxyDev->cIgnoreSetConfigs = 2;
-    LogFlow(("usbProxyLinuxReset: returns success\n"));
-#endif /* !NO_PORT_RESET */
-    return VINF_SUCCESS;
-}
-
-
-/**
- * SET_CONFIGURATION.
- *
- * The caller makes sure that it's not called first time after open or reset
- * with the active interface.
- *
- * @returns success indicator.
- * @param   pProxyDev       The device instance data.
- * @param   iCfg            The configuration to set.
- */
-static int usbProxyLinuxSetConfig(PUSBPROXYDEV pProxyDev, int iCfg)
-{
-    LogFlow(("usbProxyLinuxSetConfig: pProxyDev=%s cfg=%#x\n",
-             usbProxyGetName(pProxyDev), iCfg));
-
-    if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_SETCONFIGURATION, &iCfg, true, UINT32_MAX))
-    {
-        Log(("usb-linux: Set configuration. errno=%d\n", errno));
-        return false;
-    }
-    return true;
-}
-
-
-/**
- * Claims an interface.
- * @returns success indicator.
- */
-static int usbProxyLinuxClaimInterface(PUSBPROXYDEV pProxyDev, int iIf)
-{
-    LogFlow(("usbProxyLinuxClaimInterface: pProxyDev=%s ifnum=%#x\n", usbProxyGetName(pProxyDev), iIf));
-    usbProxyLinuxSetConnected(pProxyDev, iIf, false, false);
-
-    if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_CLAIMINTERFACE, &iIf, true, UINT32_MAX))
-    {
-        Log(("usb-linux: Claim interface. errno=%d pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev)));
-        return false;
-    }
-    return true;
-}
-
-
-/**
- * Releases an interface.
- * @returns success indicator.
- */
-static int usbProxyLinuxReleaseInterface(PUSBPROXYDEV pProxyDev, int iIf)
-{
-    LogFlow(("usbProxyLinuxReleaseInterface: pProxyDev=%s ifnum=%#x\n", usbProxyGetName(pProxyDev), iIf));
-
-    if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_RELEASEINTERFACE, &iIf, true, UINT32_MAX))
-    {
-        Log(("usb-linux: Release interface, errno=%d. pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev)));
-        return false;
-    }
-    return true;
-}
-
-
-/**
- * SET_INTERFACE.
- *
- * @returns success indicator.
- */
-static int usbProxyLinuxSetInterface(PUSBPROXYDEV pProxyDev, int iIf, int iAlt)
-{
-    struct usbdevfs_setinterface SetIf;
-    LogFlow(("usbProxyLinuxSetInterface: pProxyDev=%p iIf=%#x iAlt=%#x\n", pProxyDev, iIf, iAlt));
-
-    SetIf.interface  = iIf;
-    SetIf.altsetting = iAlt;
-    if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_SETINTERFACE, &SetIf, true, UINT32_MAX))
-    {
-        Log(("usb-linux: Set interface, errno=%d. pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev)));
-        return false;
-    }
-    return true;
-}
-
-
-/**
- * Clears the halted endpoint 'EndPt'.
- */
-static bool usbProxyLinuxClearHaltedEp(PUSBPROXYDEV pProxyDev, unsigned int EndPt)
-{
-    LogFlow(("usbProxyLinuxClearHaltedEp: pProxyDev=%s EndPt=%u\n", usbProxyGetName(pProxyDev), EndPt));
-
-    if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_CLEAR_HALT, &EndPt, true, UINT32_MAX))
-    {
-        /*
-         * Unfortunately this doesn't work on control pipes.
-         * Windows doing this on the default endpoint and possibly other pipes too,
-         * so we'll feign success for ENOENT errors.
-         */
-        if (errno == ENOENT)
-        {
-            Log(("usb-linux: clear_halted_ep failed errno=%d. pProxyDev=%s ep=%d - IGNORED\n",
-                 errno, usbProxyGetName(pProxyDev), EndPt));
-            return true;
-        }
-        Log(("usb-linux: clear_halted_ep failed errno=%d. pProxyDev=%s ep=%d\n",
-             errno, usbProxyGetName(pProxyDev), EndPt));
-        return false;
-    }
-    return true;
-}
-
-
-/**
- * Setup packet byte-swapping routines.
- */
-static void usbProxyLinuxUrbSwapSetup(PVUSBSETUP pSetup)
-{
-    pSetup->wValue = RT_H2LE_U16(pSetup->wValue);
-    pSetup->wIndex = RT_H2LE_U16(pSetup->wIndex);
-    pSetup->wLength = RT_H2LE_U16(pSetup->wLength);
-}
-
-
-/**
- * Clean up after a failed URB submit.
- */
-static void usbProxyLinuxCleanupFailedSubmit(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pUrbLnx, PUSBPROXYURBLNX pCur, PVUSBURB pUrb, bool *pfUnplugged)
-{
-    if (pUrb->enmType == VUSBXFERTYPE_MSG)
-        usbProxyLinuxUrbSwapSetup((PVUSBSETUP)pUrb->abData);
-
-    /* discard and reap later (walking with pUrbLnx). */
-    if (pUrbLnx != pCur)
-    {
-        for (;;)
-        {
-            pUrbLnx->fCanceledBySubmit = true;
-            pUrbLnx->KUrb.usercontext = NULL;
-            if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_DISCARDURB, &pUrbLnx->KUrb, false, UINT32_MAX))
-            {
-                if (errno == ENODEV)
-                    *pfUnplugged = true;
-                else if (errno == ENOENT)
-                    pUrbLnx->fSplitElementReaped = true;
-                else
-                    LogRel(("USB: Failed to discard %p! errno=%d (pUrb=%p)\n", pUrbLnx->KUrb.usercontext, errno, pUrb)); /* serious! */
-            }
-            if (pUrbLnx->pSplitNext == pCur)
-            {
-                pUrbLnx->pSplitNext = NULL;
-                break;
-            }
-            pUrbLnx = pUrbLnx->pSplitNext; Assert(pUrbLnx);
-        }
-    }
-
-    /* free the unsubmitted ones. */
-    while (pCur)
-    {
-        PUSBPROXYURBLNX pFree = pCur;
-        pCur = pCur->pSplitNext;
-        usbProxyLinuxUrbFree(pProxyDev, pFree);
-    }
-
-    /* send unplug event if we failed with ENODEV originally. */
-    if (*pfUnplugged)
-        usbProxLinuxUrbUnplugged(pProxyDev);
-}
-
-/**
- * Submit one URB through the usbfs IOCTL interface, with
- * retries
- *
- * @returns true / false.
- */
-static bool usbProxyLinuxSubmitURB(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pCur, PVUSBURB pUrb, bool *pfUnplugged)
-{
-    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
-    unsigned        cTries = 0;
-
-    while (ioctl(pDevLnx->File, USBDEVFS_SUBMITURB, &pCur->KUrb))
-    {
-        if (errno == EINTR)
-            continue;
-        if (errno == ENODEV)
-        {
-            Log(("usbProxyLinuxSubmitURB: ENODEV -> unplugged. pProxyDev=%s\n", usbProxyGetName(pProxyDev)));
-            *pfUnplugged = true;
-            return false;
-        }
-
-        Log(("usb-linux: Submit URB %p -> %d!!! type=%d ep=%#x buffer_length=%#x cTries=%d\n",
-             pUrb, errno, pCur->KUrb.type, pCur->KUrb.endpoint, pCur->KUrb.buffer_length, cTries));
-        if (errno != EBUSY && ++cTries < 3) /* this doesn't work for the floppy :/ */
-        {
-            pCur->u64SubmitTS = RTTimeMilliTS();
-            continue;
-        }
-        return false;
-    }
-    return true;
-}
-
-/** The split size. 16K in known Linux kernel versions. */
-#define SPLIT_SIZE 0x4000
-
-/**
- * Create a URB fragment of up to SPLIT_SIZE size and hook it
- * into the list of fragments.
- *
- * @returns pointer to newly allocated URB fragment or NULL.
- */
-static PUSBPROXYURBLNX usbProxyLinuxSplitURBFragment(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pHead, PUSBPROXYURBLNX pCur)
-{
-    PUSBPROXYURBLNX     pNew;
-    uint32_t            cbLeft = pCur->cbSplitRemaining;
-    uint8_t             *pb = (uint8_t *)pCur->KUrb.buffer;
-
-    Assert(cbLeft != 0);
-    pNew = pCur->pSplitNext = usbProxyLinuxUrbAlloc(pProxyDev, pHead);
-    if (!pNew)
-    {
-        usbProxyLinuxUrbFreeSplitList(pProxyDev, pHead);
-        return NULL;
-    }
-    Assert(pHead->pNext != pNew); Assert(pHead->pPrev != pNew); Assert(pNew->pNext == pNew->pPrev);
-    Assert(pNew->pSplitHead == pHead);
-    Assert(pNew->pSplitNext == NULL);
-
-    pNew->KUrb = pHead->KUrb;
-    pNew->KUrb.buffer = pb + pCur->KUrb.buffer_length;
-    pNew->KUrb.buffer_length = RT_MIN(cbLeft, SPLIT_SIZE);
-    pNew->KUrb.actual_length = 0;
-
-    cbLeft -= pNew->KUrb.buffer_length;
-    Assert(cbLeft < INT32_MAX);
-    pNew->cbSplitRemaining = cbLeft;
-    return pNew;
-}
-
-/**
- * Try splitting up a VUSB URB into smaller URBs which the
- * linux kernel (usbfs) can deal with.
- *
- * NB: For ShortOK reads things get a little tricky - we don't
- * know how much data is going to arrive and not all the
- * fragment URBs might be filled. We can only safely set up one
- * URB at a time -> worse performance but correct behaviour.
- *
- * @returns true / false.
- * @param   pProxyDev   The proxy device.
- * @param   pUrbLnx     The linux URB which was rejected because of being too big.
- * @param   pUrb        The VUSB URB.
- */
-static int usbProxyLinuxUrbQueueSplit(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pUrbLnx, PVUSBURB pUrb)
-{
-    /*
-     * Split it up into SPLIT_SIZE sized blocks.
-     */
-    const unsigned cKUrbs = (pUrb->cbData + SPLIT_SIZE - 1) / SPLIT_SIZE;
-    LogFlow(("usbProxyLinuxUrbQueueSplit: pUrb=%p cKUrbs=%d cbData=%d\n", pUrb, cKUrbs, pUrb->cbData));
-
-    uint32_t cbLeft = pUrb->cbData;
-    uint8_t *pb = &pUrb->abData[0];
-
-    /* the first one (already allocated) */
-    switch (pUrb->enmType)
-    {
-        default: /* shut up gcc */
-        case VUSBXFERTYPE_BULK: pUrbLnx->KUrb.type = USBDEVFS_URB_TYPE_BULK; break;
-        case VUSBXFERTYPE_INTR: pUrbLnx->KUrb.type = USBDEVFS_URB_TYPE_INTERRUPT; break;
-        case VUSBXFERTYPE_MSG:  pUrbLnx->KUrb.type = USBDEVFS_URB_TYPE_CONTROL; break;
-        case VUSBXFERTYPE_ISOC:
-            AssertMsgFailed(("We can't split isochronous URBs!\n"));
-            usbProxyLinuxUrbFree(pProxyDev, pUrbLnx);
-            return false;
-    }
-    pUrbLnx->KUrb.endpoint          = pUrb->EndPt;
-    if (pUrb->enmDir == VUSBDIRECTION_IN)
-        pUrbLnx->KUrb.endpoint |= 0x80;
-    pUrbLnx->KUrb.status            = 0;
-    pUrbLnx->KUrb.flags             = pUrb->fShortNotOk ? USBDEVFS_URB_SHORT_NOT_OK : 0; /* ISO_ASAP too? */
-    pUrbLnx->KUrb.buffer            = pb;
-    pUrbLnx->KUrb.buffer_length     = RT_MIN(cbLeft, SPLIT_SIZE);
-    pUrbLnx->KUrb.actual_length     = 0;
-    pUrbLnx->KUrb.start_frame       = 0;
-    pUrbLnx->KUrb.number_of_packets = 0;
-    pUrbLnx->KUrb.error_count       = 0;
-    pUrbLnx->KUrb.signr             = 0;
-    pUrbLnx->KUrb.usercontext       = pUrb;
-    pUrbLnx->pSplitHead = pUrbLnx;
-    pUrbLnx->pSplitNext = NULL;
-
-    PUSBPROXYURBLNX pCur = pUrbLnx;
-
-    cbLeft -= pUrbLnx->KUrb.buffer_length;
-    pUrbLnx->cbSplitRemaining = cbLeft;
-
-    bool fSucceeded = false;
-    bool fUnplugged = false;
-    if (pUrb->enmDir == VUSBDIRECTION_IN && !pUrb->fShortNotOk)
-    {
-        /* Subsequent fragments will be queued only after the previous fragment is reaped
-         * and only if necessary.
-         */
-        fSucceeded = true;
-        Log(("usb-linux: Large ShortOK read, only queuing first fragment.\n"));
-        Assert(pUrbLnx->cbSplitRemaining > 0 && pUrbLnx->cbSplitRemaining < 256 * _1K);
-        fSucceeded = usbProxyLinuxSubmitURB(pProxyDev, pUrbLnx, pUrb, &fUnplugged);
-    }
-    else
-    {
-        /* the rest. */
-        unsigned i;
-        for (i = 1; i < cKUrbs; i++)
-        {
-            pCur = usbProxyLinuxSplitURBFragment(pProxyDev, pUrbLnx, pCur);
-            if (!pCur)
-            {
-                return false;
-            }
-        }
-        Assert(pCur->cbSplitRemaining == 0);
-
-        /* Submit the blocks. */
-        pCur = pUrbLnx;
-        for (i = 0; i < cKUrbs; i++, pCur = pCur->pSplitNext)
-        {
-            fSucceeded = usbProxyLinuxSubmitURB(pProxyDev, pCur, pUrb, &fUnplugged);
-            if (!fSucceeded)
-                break;
-        }
-    }
-
-    if (fSucceeded)
-    {
-        pUrb->Dev.pvPrivate = pUrbLnx;
-        LogFlow(("usbProxyLinuxUrbQueueSplit: ok\n"));
-        return true;
-    }
-
-    usbProxyLinuxCleanupFailedSubmit(pProxyDev, pUrbLnx, pCur, pUrb, &fUnplugged);
-    return false;
-}
-
-
-/**
- * @copydoc USBPROXYBACK::pfnUrbQueue
- */
-static int usbProxyLinuxUrbQueue(PVUSBURB pUrb)
-{
-    unsigned        cTries;
-#ifndef RDESKTOP
-    PUSBPROXYDEV    pProxyDev = PDMINS_2_DATA(pUrb->pUsbIns, PUSBPROXYDEV);
-#else
-    PUSBPROXYDEV    pProxyDev = usbProxyFromVusbDev(pUrb->pDev);
-#endif
-    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
-    LogFlow(("usbProxyLinuxUrbQueue: pProxyDev=%s pUrb=%p EndPt=%d cbData=%d\n",
-             usbProxyGetName(pProxyDev), pUrb, pUrb->EndPt, pUrb->cbData));
-
-    /*
-     * Allocate a linux urb.
-     */
-    PUSBPROXYURBLNX pUrbLnx = usbProxyLinuxUrbAlloc(pProxyDev, NULL);
-    if (!pUrbLnx)
-        return false;
-
-    pUrbLnx->KUrb.endpoint          = pUrb->EndPt | (pUrb->enmDir == VUSBDIRECTION_IN ? 0x80 : 0);
-    pUrbLnx->KUrb.status            = 0;
-    pUrbLnx->KUrb.flags             = pUrb->fShortNotOk ? USBDEVFS_URB_SHORT_NOT_OK : 0;
-    pUrbLnx->KUrb.buffer            = pUrb->abData;
-    pUrbLnx->KUrb.buffer_length     = pUrb->cbData;
-    pUrbLnx->KUrb.actual_length     = 0;
-    pUrbLnx->KUrb.start_frame       = 0;
-    pUrbLnx->KUrb.number_of_packets = 0;
-    pUrbLnx->KUrb.error_count       = 0;
-    pUrbLnx->KUrb.signr             = 0;
-    pUrbLnx->KUrb.usercontext       = pUrb;
-
-    switch (pUrb->enmType)
-    {
-        case VUSBXFERTYPE_MSG:
-            pUrbLnx->KUrb.type = USBDEVFS_URB_TYPE_CONTROL;
-            if (pUrb->cbData < sizeof(VUSBSETUP))
-            {
-                usbProxyLinuxUrbFree(pProxyDev, pUrbLnx);
-                return false;
-            }
-            usbProxyLinuxUrbSwapSetup((PVUSBSETUP)pUrb->abData);
-            LogFlow(("usbProxyLinuxUrbQueue: message\n"));
-            break;
-        case VUSBXFERTYPE_BULK:
-            pUrbLnx->KUrb.type = USBDEVFS_URB_TYPE_BULK;
-            break;
-        case VUSBXFERTYPE_ISOC:
-            pUrbLnx->KUrb.type = USBDEVFS_URB_TYPE_ISO;
-            pUrbLnx->KUrb.flags |= USBDEVFS_URB_ISO_ASAP;
-            pUrbLnx->KUrb.number_of_packets = pUrb->cIsocPkts;
-            unsigned i;
-            for (i = 0; i < pUrb->cIsocPkts; i++)
-            {
-                pUrbLnx->KUrb.iso_frame_desc[i].length = pUrb->aIsocPkts[i].cb;
-                pUrbLnx->KUrb.iso_frame_desc[i].actual_length = 0;
-                pUrbLnx->KUrb.iso_frame_desc[i].status = 0x7fff;
-            }
-            break;
-        case VUSBXFERTYPE_INTR:
-            pUrbLnx->KUrb.type = USBDEVFS_URB_TYPE_INTERRUPT;
-            break;
-        default:
-            goto l_err;
-    }
-
-    /*
-     * Submit it.
-     */
-    cTries = 0;
-    while (ioctl(pDevLnx->File, USBDEVFS_SUBMITURB, &pUrbLnx->KUrb))
-    {
-        if (errno == EINTR)
-            continue;
-        if (errno == ENODEV)
-        {
-            Log(("usbProxyLinuxUrbQueue: ENODEV -> unplugged. pProxyDev=%s\n", usbProxyGetName(pProxyDev)));
-            if (pUrb->enmType == VUSBXFERTYPE_MSG)
-                usbProxyLinuxUrbSwapSetup((PVUSBSETUP)pUrb->abData);
-            usbProxyLinuxUrbFree(pProxyDev, pUrbLnx);
-
-            usbProxLinuxUrbUnplugged(pProxyDev);
-            return false;
-        }
-
-        /*
-         * usbfs has or used to have a low buffer limit (16KB) in order to prevent
-         * processes wasting kmalloc'ed memory. It will return EINVAL if break that
-         * limit, and we'll have to split the VUSB URB up into multiple linux URBs.
-         *
-         * Since this is a limit which is subject to change, we cannot check for it
-         * before submitting the URB. We just have to try and fail.
-         */
-        if (    errno == EINVAL
-            &&  pUrb->cbData >= 8*_1K)
-            return usbProxyLinuxUrbQueueSplit(pProxyDev, pUrbLnx, pUrb);
-
-        Log(("usb-linux: Queue URB %p -> %d!!! type=%d ep=%#x buffer_length=%#x cTries=%d\n",
-             pUrb, errno, pUrbLnx->KUrb.type, pUrbLnx->KUrb.endpoint, pUrbLnx->KUrb.buffer_length, cTries));
-        if (errno != EBUSY && ++cTries < 3) /* this doesn't work for the floppy :/ */
-            continue;
-l_err:
-        if (pUrb->enmType == VUSBXFERTYPE_MSG)
-            usbProxyLinuxUrbSwapSetup((PVUSBSETUP)pUrb->abData);
-        usbProxyLinuxUrbFree(pProxyDev, pUrbLnx);
-        return false;
-    }
-    pUrbLnx->u64SubmitTS = RTTimeMilliTS();
-
-    LogFlow(("usbProxyLinuxUrbQueue: ok\n"));
-    pUrb->Dev.pvPrivate = pUrbLnx;
-    return true;
-}
-
-
-/**
- * Check if any or the in-flight URBs are taking too long and should be cancelled.
- *
- * Cancelling is done in three turns, first a URB is marked for timeout if it's
- * exceeding a certain time limit. Then the next time it's encountered it is actually
- * cancelled. The idea now is that it's supposed to be reaped and returned in the next
- * round of calls.
- *
- * @param   pProxyDev   The proxy device.
- * @param   pDevLnx     The linux backend data.
- *
- * @todo    Make the HCI do proper timeout handling! Current timeout is 3 min and 20 seconds
- *          as not to break bloomberg which queues IN packages with 3 min timeouts.
- */
-static void vusbProxyLinuxUrbDoTimeouts(PUSBPROXYDEV pProxyDev, PUSBPROXYDEVLNX pDevLnx)
-{
-    RTCritSectEnter(&pDevLnx->CritSect);
-    uint64_t u64MilliTS = RTTimeMilliTS();
-    PUSBPROXYURBLNX pCur;
-    for (pCur = pDevLnx->pInFlightHead;
-         pCur;
-         pCur = pCur->pNext)
-    {
-        if (pCur->fTimedOut)
-        {
-            if (pCur->pSplitHead)
-            {
-                /* split */
-                Assert(pCur == pCur->pSplitHead);
-                unsigned cFailures = 0;
-                PUSBPROXYURBLNX pCur2;
-                for (pCur2 = pCur; pCur2; pCur2 = pCur2->pSplitNext)
-                {
-                    if (pCur2->fSplitElementReaped)
-                        continue;
-
-                    if (    !usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_DISCARDURB, &pCur2->KUrb, true, UINT32_MAX)
-                        ||  errno == ENOENT)
-                        pCur2->fCanceledByTimedOut = true;
-                    else if (errno != ENODEV)
-                        Log(("vusbProxyLinuxUrbDoTimeouts: pUrb=%p failed errno=%d (!!split!!)\n", pCur2->KUrb.usercontext, errno));
-                    else
-                        goto l_leave; /* ENODEV means break and everything cancelled elsewhere. */
-                }
-                LogRel(("USB: Cancelled URB (%p) after %llums!! (cFailures=%d)\n",
-                        pCur->KUrb.usercontext, (long long unsigned) u64MilliTS - pCur->u64SubmitTS, cFailures));
-            }
-            else
-            {
-                /* unsplit */
-                if (    !usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_DISCARDURB, &pCur->KUrb, true, UINT32_MAX)
-                    ||  errno == -ENOENT)
-                {
-                    pCur->fCanceledByTimedOut = true;
-                    LogRel(("USB: Cancelled URB (%p) after %llums!!\n", pCur->KUrb.usercontext, (long long unsigned) u64MilliTS - pCur->u64SubmitTS));
-                }
-                else if (errno != ENODEV)
-                    LogFlow(("vusbProxyLinuxUrbDoTimeouts: pUrb=%p failed errno=%d\n", pCur->KUrb.usercontext, errno));
-                else
-                    goto l_leave; /* ENODEV means break and everything cancelled elsewhere. */
-            }
-        }
-#if 0
-        /* Disabled for the time beeing as some USB devices have URBs pending for an unknown amount of time.
-         * One example is the OmniKey CardMan 3821. */
-        else if (u64MilliTS - pCur->u64SubmitTS >= 200*1000 /* 200 sec (180 sec has been observed with XP) */)
-            pCur->fTimedOut = true;
-#endif
-    }
-
-l_leave:
-    RTCritSectLeave(&pDevLnx->CritSect);
-}
-
-
-/**
- * Translate the linux status to a VUSB status.
- *
- * @remarks see cc_to_error in ohci.h, uhci_map_status in uhci-q.c,
- *          sitd_complete+itd_complete in ehci-sched.c, and qtd_copy_status in
- *          ehci-q.c.
- */
-static VUSBSTATUS vusbProxyLinuxStatusToVUsbStatus(int iStatus)
-{
-    switch (iStatus)
-    {
-        /** @todo VUSBSTATUS_NOT_ACCESSED */
-        case -EXDEV: /* iso transfer, partial result. */
-        case 0:
-            return VUSBSTATUS_OK;
-
-        case -EILSEQ:
-            return VUSBSTATUS_CRC;
-
-        case -EREMOTEIO: /* ehci and ohci uses this for underflow error. */
-            return VUSBSTATUS_DATA_UNDERRUN;
-        case -EOVERFLOW:
-            return VUSBSTATUS_DATA_OVERRUN;
-
-        case -ETIME:
-        case -ENODEV:
-            return VUSBSTATUS_DNR;
-
-        //case -ECOMM:
-        //    return VUSBSTATUS_BUFFER_OVERRUN;
-        //case -ENOSR:
-        //    return VUSBSTATUS_BUFFER_UNDERRUN;
-
-        //case -EPROTO:
-        //    return VUSBSTATUS_BIT_STUFFING;
-
-        case -EPIPE:
-            Log(("vusbProxyLinuxStatusToVUsbStatus: STALL/EPIPE!!\n"));
-            return VUSBSTATUS_STALL;
-
-        case -ESHUTDOWN:
-            Log(("vusbProxyLinuxStatusToVUsbStatus: SHUTDOWN!!\n"));
-            return VUSBSTATUS_STALL;
-
-        default:
-            Log(("vusbProxyLinuxStatusToVUsbStatus: status %d!!\n", iStatus));
-            return VUSBSTATUS_STALL;
-    }
-}
-
-
-/**
- * Get and translates the linux status to a VUSB status.
- */
-static VUSBSTATUS vusbProxyLinuxUrbGetStatus(PUSBPROXYURBLNX pUrbLnx)
-{
-    if (    pUrbLnx->fCanceledByTimedOut
-        &&  pUrbLnx->KUrb.status == 0)
-        return VUSBSTATUS_CRC;
-    return vusbProxyLinuxStatusToVUsbStatus(pUrbLnx->KUrb.status);
-}
-
-
-/**
- * Reap URBs in-flight on a device.
- *
- * @returns Pointer to a completed URB.
- * @returns NULL if no URB was completed.
- * @param   pProxyDev   The device.
- * @param   cMillies    Number of milliseconds to wait. Use 0 to not wait at all.
- */
-static PVUSBURB usbProxyLinuxUrbReap(PUSBPROXYDEV pProxyDev, RTMSINTERVAL cMillies)
-{
-    PUSBPROXYURBLNX pUrbLnx = NULL;
-    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
-
-    /*
-     * Any URBs pending delivery?
-     */
-    if (pDevLnx->pTaxingHead)
-    {
-        RTCritSectEnter(&pDevLnx->CritSect);
-        pUrbLnx = pDevLnx->pTaxingHead;
-        if (pUrbLnx)
-        {
-            /* unlink from the pending delivery list */
-            if (pUrbLnx->pNext)
-            {
-                pUrbLnx->pNext->pPrev = NULL;
-                pDevLnx->pTaxingHead = pUrbLnx->pNext;
-            }
-            else
-                pDevLnx->pTaxingHead = pDevLnx->pTaxingTail = NULL;
-
-            /* temporarily into the active list, so free works right. */
-            pUrbLnx->pPrev = NULL;
-            pUrbLnx->pNext = pDevLnx->pInFlightHead;
-            if (pUrbLnx->pNext)
-                pUrbLnx->pNext->pPrev = pUrbLnx;
-            pDevLnx->pInFlightHead = pUrbLnx;
-        }
-        RTCritSectLeave(&pDevLnx->CritSect);
-    }
-    if (!pUrbLnx)
-    {
-        /*
-         * Don't block if nothing is in the air.
-         */
-        if (!pDevLnx->pInFlightHead)
-            return NULL;
-
-        /*
-         * Block for requested period.
-         *
-         * It seems to me that the path of poll() is shorter and
-         * involves less semaphores than ioctl() on usbfs. So, we'll
-         * do a poll regardless of whether cMillies == 0 or not.
-         */
-        if (cMillies)
-        {
-
-            for (;;)
-            {
-                struct pollfd pfd;
-                int rc;
-
-                pfd.fd = pDevLnx->File;
-                pfd.events = POLLOUT | POLLWRNORM /* completed async */
-                           | POLLERR | POLLHUP    /* disconnected */;
-                pfd.revents = 0;
-                rc = poll(&pfd, 1, cMillies);
-                Log(("usbProxyLinuxUrbReap: poll rc = %d\n", rc));
-                if (rc >= 1)
-                    break;
-                if (rc >= 0 /*|| errno == ETIMEOUT*/)
-                {
-                    vusbProxyLinuxUrbDoTimeouts(pProxyDev, pDevLnx);
-                    return NULL;
-                }
-                if (errno != EAGAIN)
-                {
-                    Log(("usb-linux: Reap URB - poll -> %d errno=%d pProxyDev=%s\n", rc, errno, usbProxyGetName(pProxyDev)));
-                    return NULL;
-                }
-                Log(("usbProxyLinuxUrbReap: poll again - weird!!!\n"));
-            }
-        }
-
-        /*
-         * Reap URBs, non-blocking.
-         */
-        for (;;)
-        {
-            struct usbdevfs_urb *pKUrb;
-            while (ioctl(pDevLnx->File, USBDEVFS_REAPURBNDELAY, &pKUrb))
-                if (errno != EINTR)
-                {
-                    if (errno == ENODEV)
-                        usbProxLinuxUrbUnplugged(pProxyDev);
-                    else if (errno == EAGAIN)
-                        vusbProxyLinuxUrbDoTimeouts(pProxyDev, pDevLnx);
-                    else
-                        Log(("usb-linux: Reap URB. errno=%d pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev)));
-                    return NULL;
-                }
-            pUrbLnx = (PUSBPROXYURBLNX)pKUrb;
-
-            /* split list: Is the entire split list done yet? */
-            if (pUrbLnx->pSplitHead)
-            {
-                pUrbLnx->fSplitElementReaped = true;
-
-                /* for variable size URBs, we may need to queue more if the just-reaped URB was completely filled */
-                if (pUrbLnx->cbSplitRemaining && (pKUrb->actual_length == pKUrb->buffer_length) && !pUrbLnx->pSplitNext)
-                {
-                    bool fUnplugged = false;
-                    bool fSucceeded;
-
-                    Assert(pUrbLnx->pSplitHead);
-                    Assert((pKUrb->endpoint & 0x80) && (!pKUrb->flags & USBDEVFS_URB_SHORT_NOT_OK));
-                    PUSBPROXYURBLNX pNew = usbProxyLinuxSplitURBFragment(pProxyDev, pUrbLnx->pSplitHead, pUrbLnx);
-                    if (!pNew)
-                    {
-                        Log(("usb-linux: Allocating URB fragment failed. errno=%d pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev)));
-                        return NULL;
-                    }
-                    PVUSBURB pUrb = (PVUSBURB)pUrbLnx->KUrb.usercontext;
-                    fSucceeded = usbProxyLinuxSubmitURB(pProxyDev, pNew, pUrb, &fUnplugged);
-                    if (fUnplugged)
-                        usbProxLinuxUrbUnplugged(pProxyDev);
-                    if (!fSucceeded)
-                        return NULL;
-                    continue;   /* try reaping another URB */
-                }
-                PUSBPROXYURBLNX pCur;
-                for (pCur = pUrbLnx->pSplitHead; pCur; pCur = pCur->pSplitNext)
-                    if (!pCur->fSplitElementReaped)
-                    {
-                        pUrbLnx = NULL;
-                        break;
-                    }
-                if (!pUrbLnx)
-                    continue;
-                pUrbLnx = pUrbLnx->pSplitHead;
-            }
-            break;
-        }
-    }
-
-    /*
-     * Ok, we got one!
-     */
-    PVUSBURB pUrb = (PVUSBURB)pUrbLnx->KUrb.usercontext;
-    if (    pUrb
-        &&  !pUrbLnx->fCanceledBySubmit)
-    {
-        if (pUrbLnx->pSplitHead)
-        {
-            /* split - find the end byte and the first error status. */
-            Assert(pUrbLnx == pUrbLnx->pSplitHead);
-            uint8_t *pbEnd = &pUrb->abData[0];
-            pUrb->enmStatus = VUSBSTATUS_OK;
-            PUSBPROXYURBLNX pCur;
-            for (pCur = pUrbLnx; pCur; pCur = pCur->pSplitNext)
-            {
-                if (pCur->KUrb.actual_length)
-                    pbEnd = (uint8_t *)pCur->KUrb.buffer + pCur->KUrb.actual_length;
-                if (pUrb->enmStatus == VUSBSTATUS_OK)
-                    pUrb->enmStatus = vusbProxyLinuxUrbGetStatus(pCur);
-            }
-            pUrb->cbData = pbEnd - &pUrb->abData[0];
-            usbProxyLinuxUrbFreeSplitList(pProxyDev, pUrbLnx);
-        }
-        else
-        {
-            /* unsplit. */
-            pUrb->enmStatus = vusbProxyLinuxUrbGetStatus(pUrbLnx);
-            pUrb->cbData = pUrbLnx->KUrb.actual_length;
-            if (pUrb->enmType == VUSBXFERTYPE_ISOC)
-            {
-                unsigned i, off;
-                for (i = 0, off = 0; i < pUrb->cIsocPkts; i++)
-                {
-                    pUrb->aIsocPkts[i].enmStatus = vusbProxyLinuxStatusToVUsbStatus(pUrbLnx->KUrb.iso_frame_desc[i].status);
-                    Assert(pUrb->aIsocPkts[i].off == off);
-                    pUrb->aIsocPkts[i].cb = pUrbLnx->KUrb.iso_frame_desc[i].actual_length;
-                    off += pUrbLnx->KUrb.iso_frame_desc[i].length;
-                }
-            }
-            usbProxyLinuxUrbFree(pProxyDev, pUrbLnx);
-        }
-        pUrb->Dev.pvPrivate = NULL;
-
-        /* some adjustments for message transfers. */
-        if (pUrb->enmType == VUSBXFERTYPE_MSG)
-        {
-            pUrb->cbData += sizeof(VUSBSETUP);
-            usbProxyLinuxUrbSwapSetup((PVUSBSETUP)pUrb->abData);
-        }
-    }
-    else
-    {
-        usbProxyLinuxUrbFree(pProxyDev, pUrbLnx);
-        pUrb = NULL;
-    }
-
-    LogFlow(("usbProxyLinuxUrbReap: pProxyDev=%s returns %p\n", usbProxyGetName(pProxyDev), pUrb));
-    return pUrb;
-}
-
-
-/**
- * Cancels the URB.
- * The URB requires reaping, so we don't change its state.
- */
-static void usbProxyLinuxUrbCancel(PVUSBURB pUrb)
-{
-#ifndef RDESKTOP
-    PUSBPROXYDEV pProxyDev = PDMINS_2_DATA(pUrb->pUsbIns, PUSBPROXYDEV);
-#else
-    PUSBPROXYDEV pProxyDev = usbProxyFromVusbDev(pUrb->pDev);
-#endif
-    PUSBPROXYURBLNX pUrbLnx = (PUSBPROXYURBLNX)pUrb->Dev.pvPrivate;
-    if (pUrbLnx->pSplitHead)
-    {
-        /* split */
-        Assert(pUrbLnx == pUrbLnx->pSplitHead);
-        PUSBPROXYURBLNX pCur;
-        for (pCur = pUrbLnx; pCur; pCur = pCur->pSplitNext)
-        {
-            if (pCur->fSplitElementReaped)
-                continue;
-            if (    !usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_DISCARDURB, &pCur->KUrb, true, UINT32_MAX)
-                ||  errno == ENOENT)
-                continue;
-            if (errno == ENODEV)
-                break;
-            Log(("usb-linux: Discard URB %p failed, errno=%d. pProxyDev=%s!!! (split)\n",
-                 pUrb, errno, usbProxyGetName(pProxyDev)));
-        }
-    }
-    else
-    {
-        /* unsplit */
-        if (    usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_DISCARDURB, &pUrbLnx->KUrb, true, UINT32_MAX)
-            &&  errno != ENODEV /* deal with elsewhere. */
-            &&  errno != ENOENT)
-            Log(("usb-linux: Discard URB %p failed, errno=%d. pProxyDev=%s!!!\n",
-                 pUrb, errno, usbProxyGetName(pProxyDev)));
-    }
-}
-
-
-/**
- * The Linux USB Proxy Backend.
- */
-const USBPROXYBACK g_USBProxyDeviceHost =
-{
-    "host",
-    usbProxyLinuxOpen,
-    usbProxyLinuxInit,
-    usbProxyLinuxClose,
-    usbProxyLinuxReset,
-    usbProxyLinuxSetConfig,
-    usbProxyLinuxClaimInterface,
-    usbProxyLinuxReleaseInterface,
-    usbProxyLinuxSetInterface,
-    usbProxyLinuxClearHaltedEp,
-    usbProxyLinuxUrbQueue,
-    usbProxyLinuxUrbCancel,
-    usbProxyLinuxUrbReap,
-    0
-};
-
-
-/*
- * Local Variables:
- *  mode: c
- *  c-file-style: "bsd"
- *  c-basic-offset: 4
- *  tab-width: 4
- *  indent-tabs-mode: s
- * End:
- */
-
+#include "../../../Devices/USB/linux/USBProxyDevice-linux.cpp"
Index: trunk/src/VBox/RDP/client/vrdp/USBProxyDevice.h
===================================================================
--- trunk/src/VBox/RDP/client/vrdp/USBProxyDevice.h	(revision 31538)
+++ 	(revision )
@@ -1,246 +1,0 @@
-/* $Id$ */
-/** @file
- * USBPROXY - USB proxy header
- */
-
-/*
- * Copyright (C) 2006-2007 Oracle Corporation
- *
- * Oracle Corporation confidential
- * All rights reserved
- */
-
-#ifndef ___USBProxyDevice_h
-#define ___USBProxyDevice_h
-
-#ifndef RDESKTOP
-# include <VBox/cdefs.h>
-# include <VBox/vusb.h>
-#else
-# include "runtime.h"
-# include "vusb.h"
-#endif
-
-RT_C_DECLS_BEGIN
-
-
-/**
- * Arguments passed to the USB proxy device constructor.
- */
-typedef struct USBPROXYDEVARGS
-{
-    /** Whether this is a remote (VRDP) or local (Host) device. */
-    bool        fRemote;
-    /** Host specific USB device address. */
-    const char *pszAddress;
-    /** Pointer to backend specific data. */
-    void       *pvBackend;
-} USBPROXYDEVARGS;
-/** Pointer to proxy device creation structure. */
-typedef USBPROXYDEVARGS *PUSBPROXYDEVARGS;
-
-
-/** Pointer to a USB proxy device. */
-typedef struct USBPROXYDEV *PUSBPROXYDEV;
-
-/**
- * USB Proxy Device Backend
- */
-typedef struct USBPROXYBACK
-{
-    /** Name of the backend. */
-    const char *pszName;
-
-    /**
-     * Opens the USB device specfied by pszAddress.
-     *
-     * This method will initialize backend private data. If the backend has
-     * already selected a configuration for the device, this must be indicated
-     * in USBPROXYDEV::iActiveCfg.
-     *
-     * @returns VBox status code.
-     * @param   pProxyDev   The USB Proxy Device instance.
-     * @param   pszAddress  Host specific USB device address.
-     * @param   pvBackend   Pointer to backend specific data.
-     */
-    int  (* pfnOpen)(PUSBPROXYDEV pProxyDev, const char *pszAddress, void *pvBackend);
-
-    /**
-     * Optional callback for initalizing the device after the configuration
-     * has been established.
-     *
-     * @returns VBox status code.
-     * @param   pProxyDev   The USB Proxy Device instance.
-     */
-    int  (* pfnInit)(PUSBPROXYDEV pProxyDev);
-
-    /**         Closes handle to the host USB device.
-     *
-     * @param   pDev        The USB Proxy Device instance.
-     */
-    void (* pfnClose)(PUSBPROXYDEV pProxyDev);
-
-    /**
-     * Reset a device.
-     *
-     * The backend must update iActualCfg and fIgnoreEqualSetConfig.
-     *
-     * @returns VBox status code.
-     * @param   pDev            The device to reset.
-     * @param   fResetOnLinux   It's safe to do reset on linux, we can deal with devices
-     *                          being logically reconnected.
-     */
-    int  (* pfnReset)(PUSBPROXYDEV pProxyDev, bool fResetOnLinux);
-
-    /** @todo make it return a VBox status code! */
-    int  (* pfnSetConfig)(PUSBPROXYDEV pProxyDev, int iCfg);
-
-    /** @todo make it return a VBox status code! */
-    int  (* pfnClaimInterface)(PUSBPROXYDEV pProxyDev, int iIf);
-
-    /** @todo make it return a VBox status code! */
-    int  (* pfnReleaseInterface)(PUSBPROXYDEV pProxyDev, int iIf);
-
-    /** @todo make it return a VBox status code! */
-    int  (* pfnSetInterface)(PUSBPROXYDEV pProxyDev, int iIf, int setting);
-
-    /** @todo make it return a VBox status code! */
-    bool (* pfnClearHaltedEndpoint)(PUSBPROXYDEV  pDev, unsigned int iEp);
-
-    /** @todo make it return a VBox status code! Add pDev. */
-    int  (* pfnUrbQueue)(PVUSBURB pUrb);
-
-    /**
-     * Cancel an in-flight URB.
-     *
-     * @param   pUrb        The URB to cancel.
-     * @todo make it return a VBox status code! Add pDev.
-     */
-    void (* pfnUrbCancel)(PVUSBURB pUrb);
-
-    /**
-     * Reap URBs in-flight on a device.
-     *
-     * @returns Pointer to a completed URB.
-     * @returns NULL if no URB was completed.
-     * @param   pDev        The device.
-     * @param   cMillies    Number of milliseconds to wait. Use 0 to not
-     *                      wait at all.
-     */
-    PVUSBURB (* pfnUrbReap)(PUSBPROXYDEV pProxyDev, RTMSINTERVAL cMillies);
-
-    /** Dummy entry for making sure we've got all members initialized. */
-    uint32_t uDummy;
-} USBPROXYBACK;
-/** Pointer to a USB Proxy Device Backend. */
-typedef USBPROXYBACK *PUSBPROXYBACK;
-/** Pointer to a const USB Proxy Device Backend. */
-typedef const USBPROXYBACK *PCUSBPROXYBACK;
-
-/** The Host backend. */
-extern const USBPROXYBACK g_USBProxyDeviceHost;
-#ifdef VBOX_WITH_VRDP
-/** The VRDP backend. */
-extern const USBPROXYBACK g_USBProxyDeviceVRDP;
-#endif /* VBOX_WITH_VRDP */
-
-#ifdef RDESKTOP
-typedef struct VUSBDEV
-{
-    char* pszName;
-} VUSBDEV, *PVUSBDEV;
-#endif
-
-/**
- * USB Proxy device.
- */
-typedef struct USBPROXYDEV
-{
-#ifdef RDESKTOP
-    /** The VUSB device structure - must be the first structure member. */
-    VUSBDEV             Dev;
-    /** The next device in rdesktop-vrdp's linked list */
-    PUSBPROXYDEV        pNext;
-    /** The previous device in rdesktop-vrdp's linked list */
-    PUSBPROXYDEV        pPrev;
-    /** The vrdp device ID */
-    uint32_t devid;
-    /** Linked list of in-flight URBs */
-    PVUSBURB            pUrbs;
-#endif
-    /** The device descriptor. */
-    VUSBDESCDEVICE      DevDesc;
-    /** The configuration descriptor array. */
-    PVUSBDESCCONFIGEX   paCfgDescs;
-#ifndef RDESKTOP
-    /** The descriptor cache.
-     * Contains &DevDesc and paConfigDescs. */
-    PDMUSBDESCCACHE     DescCache;
-    /** Pointer to the PDM USB device instance. */
-    PPDMUSBINS          pUsbIns;
-#endif
-
-    /** Pointer to the backend. */
-    PCUSBPROXYBACK      pOps;
-    /** The currently active configration.
-     * It's -1 if no configuration is active. This is set to -1 before open and reset,
-     * the backend will change it if open or reset implies SET_CONFIGURATION. */
-    int                 iActiveCfg;
-    /** Ignore one or two SET_CONFIGURATION operation.
-     * See usbProxyDevSetCfg for details. */
-    int                 cIgnoreSetConfigs;
-    /** Mask of the interfaces that the guest shall doesn't see.
-     * This is experimental!
-     */
-    uint32_t            fMaskedIfs;
-    /** Whether we've opened the device or not.
-     * For dealing with failed construction (the destruct method is always called). */
-    bool                fOpened;
-    /** Whether we've called pfnInit or not.
-     * For dealing with failed construction (the destruct method is always called). */
-    bool                fInited;
-    /** Whether the device has been detached.
-     * This is hack for making PDMUSBREG::pfnUsbQueue return the right status code. */
-    bool                fDetached;
-    /** Backend specific data */
-    union USBPROXYBACKENDDATA
-    {
-        /** Pointer to some backend data.
-         * The Linux and Darwin backends are making use of this. */
-        void *pv;
-        RTFILE File;
-        int fd;
-#ifdef VBOX_WITH_VRDP
-        struct vrdp_priv
-        {
-            void *pCallback;
-            void *pDevice;
-        } vrdp;
-#endif /* VBOX_WITH_VRDP */
-    } Backend;
-} USBPROXYDEV;
-
-static inline char *usbProxyGetName(PUSBPROXYDEV pProxyDev)
-{
-#ifndef RDESKTOP
-    return pProxyDev->pUsbIns->pszName;
-#else
-    return pProxyDev->Dev.pszName;
-#endif
-}
-
-#ifdef RDESKTOP
-static inline PUSBPROXYDEV usbProxyFromVusbDev(PVUSBDEV pDev)
-{
-    return (PUSBPROXYDEV)pDev;
-}
-#endif
-
-#ifdef RT_OS_LINUX
-RTDECL(int) USBProxyDeviceLinuxGetFD(PUSBPROXYDEV pProxyDev);
-#endif
-
-RT_C_DECLS_END
-
-#endif
-
Index: trunk/src/VBox/RDP/client/vrdp/runtime.h
===================================================================
--- trunk/src/VBox/RDP/client/vrdp/runtime.h	(revision 31538)
+++ trunk/src/VBox/RDP/client/vrdp/runtime.h	(revision 31557)
@@ -48,8 +48,8 @@
 
 #define OPSTATIC
-// #define RDPUSB_DEBUG
+#define RDPUSB_DEBUG
 #ifdef RDPUSB_DEBUG
 #define DoLog(a) do { \
-        printf("Time %llu: ", RTTimeMilliTS()); \
+        printf("Time %llu: ", (long long unsigned) RTTimeMilliTS()); \
         printf a; \
 } while(0)
@@ -89,8 +89,21 @@
 #define VINF_SUCCESS 0
 #define VERR_NO_MEMORY        (-8)
+#define VERR_INVALID_POINTER  (-6)
 #define VERR_UNRESOLVED_ERROR (-35)
 #define VERR_NOT_SUPPORTED    (-37)
 #define VERR_ACCESS_DENIED    (-38)
 #define VERR_VUSB_USBFS_PERMISSION (-2005)
+
+static inline const char *RTErrGetShort(int iErr)
+{
+    return   iErr == VINF_SUCCESS               ? "VINF_SUCCESS"
+           : iErr == VERR_NO_MEMORY             ? "VERR_NO_MEMORY"
+           : iErr == VERR_INVALID_POINTER       ? "VERR_INVALID_POINTER"
+           : iErr == VERR_UNRESOLVED_ERROR      ? "VERR_UNRESOLVED_ERROR"
+           : iErr == VERR_NOT_SUPPORTED         ? "VERR_NOT_SUPPORTED"
+           : iErr == VERR_ACCESS_DENIED         ? "VERR_ACCESS_DENIED"
+           : iErr == VERR_VUSB_USBFS_PERMISSION ? "VERR_VUSB_USBFS_PERMISSION"
+           : "Unknown error";
+}
 
 static inline int RTErrConvertFromErrno(int iErrno)
@@ -136,4 +149,6 @@
 #define NOREF(_a) ((void)_a)
 
+#define VALID_PTR(ptr) ((ptr) != NULL)
+
 #define RT_C_DECLS_BEGIN
 #define RT_C_DECLS_END
Index: trunk/src/VBox/RDP/client/vrdp/vusb.h
===================================================================
--- trunk/src/VBox/RDP/client/vrdp/vusb.h	(revision 31538)
+++ 	(revision )
@@ -1,1046 +1,0 @@
-/** @file
- * VUSB - VirtualBox USB. (DEV,VMM)
- */
-
-/*
- * Copyright (C) 2006-2007 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.
- */
-
-#ifndef ___VBox_vusb_h
-#define ___VBox_vusb_h
-
-#ifndef RDESKTOP
-# include <VBox/cdefs.h>
-# include <VBox/types.h>
-#else
-# include "runtime.h"
-#endif
-
-RT_C_DECLS_BEGIN
-
-/** @defgroup grp_vusb  VBox USB API
- * @{
- */
-
-/** @defgroup grp_vusb_std  Standard Stuff
- * @{ */
-
-/** Frequency of USB bus (from spec). */
-#define VUSB_BUS_HZ                 12000000
-
-
-/** @name USB Descriptor types (from spec)
- * @{ */
-#define VUSB_DT_DEVICE                  0x01
-#define VUSB_DT_CONFIG                  0x02
-#define VUSB_DT_STRING                  0x03
-#define VUSB_DT_INTERFACE               0x04
-#define VUSB_DT_ENDPOINT                0x05
-#define VUSB_DT_DEVICE_QUALIFIER        0x06
-#define VUSB_DT_OTHER_SPEED_CFG         0x07
-#define VUSB_DT_INTERFACE_POWER         0x08
-/** @} */
-
-/** @name USB Descriptor minimum sizes (from spec)
- * @{ */
-#define VUSB_DT_DEVICE_MIN_LEN          18
-#define VUSB_DT_CONFIG_MIN_LEN          9
-#define VUSB_DT_CONFIG_STRING_MIN_LEN   2
-#define VUSB_DT_INTERFACE_MIN_LEN       9
-#define VUSB_DT_ENDPOINT_MIN_LEN        7
-/** @} */
-
-
-#pragma pack(1) /* ensure byte packing of the descriptors. */
-
-/**
- * USB language id descriptor (from specs).
- */
-typedef struct VUSBDESCLANGID
-{
-    uint8_t bLength;
-    uint8_t bDescriptorType;
-} VUSBDESCLANGID;
-/** Pointer to a USB language id descriptor. */
-typedef VUSBDESCLANGID *PVUSBDESCLANGID;
-/** Pointer to a const USB language id descriptor. */
-typedef const VUSBDESCLANGID *PCVUSBDESCLANGID;
-
-
-/**
- * USB string descriptor (from specs).
- */
-typedef struct VUSBDESCSTRING
-{
-    uint8_t bLength;
-    uint8_t bDescriptorType;
-} VUSBDESCSTRING;
-/** Pointer to a USB string descriptor. */
-typedef VUSBDESCSTRING *PVUSBDESCSTRING;
-/** Pointer to a const USB string descriptor. */
-typedef const VUSBDESCSTRING *PCVUSBDESCSTRING;
-
-
-/**
- * USB device descriptor (from spec)
- */
-typedef struct VUSBDESCDEVICE
-{
-    uint8_t  bLength;
-    uint8_t  bDescriptorType;
-    uint16_t bcdUSB;
-    uint8_t  bDeviceClass;
-    uint8_t  bDeviceSubClass;
-    uint8_t  bDeviceProtocol;
-    uint8_t  bMaxPacketSize0;
-    uint16_t idVendor;
-    uint16_t idProduct;
-    uint16_t bcdDevice;
-    uint8_t  iManufacturer;
-    uint8_t  iProduct;
-    uint8_t  iSerialNumber;
-    uint8_t  bNumConfigurations;
-} VUSBDESCDEVICE;
-/** Pointer to a USB device descriptor. */
-typedef VUSBDESCDEVICE *PVUSBDESCDEVICE;
-/** Pointer to a const USB device descriptor. */
-typedef const VUSBDESCDEVICE *PCVUSBDESCDEVICE;
-
-
-/**
- * USB configuration descriptor (from spec).
- */
-typedef struct VUSBDESCCONFIG
-{
-    uint8_t  bLength;
-    uint8_t  bDescriptorType;
-    uint16_t wTotalLength; /**< recalculated by VUSB when involved in URB. */
-    uint8_t  bNumInterfaces;
-    uint8_t  bConfigurationValue;
-    uint8_t  iConfiguration;
-    uint8_t  bmAttributes;
-    uint8_t  MaxPower;
-} VUSBDESCCONFIG;
-/** Pointer to a USB configuration descriptor. */
-typedef VUSBDESCCONFIG *PVUSBDESCCONFIG;
-/** Pointer to a readonly USB configuration descriptor. */
-typedef const VUSBDESCCONFIG *PCVUSBDESCCONFIG;
-
-
-/**
- * USB interface descriptor (from spec)
- */
-typedef struct VUSBDESCINTERFACE
-{
-    uint8_t  bLength;
-    uint8_t  bDescriptorType;
-    uint8_t  bInterfaceNumber;
-    uint8_t  bAlternateSetting;
-    uint8_t  bNumEndpoints;
-    uint8_t  bInterfaceClass;
-    uint8_t  bInterfaceSubClass;
-    uint8_t  bInterfaceProtocol;
-    uint8_t  iInterface;
-} VUSBDESCINTERFACE;
-/** Pointer to an USB interface descriptor. */
-typedef VUSBDESCINTERFACE *PVUSBDESCINTERFACE;
-/** Pointer to a const USB interface descriptor. */
-typedef const VUSBDESCINTERFACE *PCVUSBDESCINTERFACE;
-
-
-/**
- * USB endpoint descriptor (from spec)
- */
-typedef struct VUSBDESCENDPOINT
-{
-    uint8_t  bLength;
-    uint8_t  bDescriptorType;
-    uint8_t  bEndpointAddress;
-    uint8_t  bmAttributes;
-    uint16_t wMaxPacketSize;
-    uint8_t  bInterval;
-} VUSBDESCENDPOINT;
-/** Pointer to an USB endpoint descriptor. */
-typedef VUSBDESCENDPOINT *PVUSBDESCENDPOINT;
-/** Pointer to a const USB endpoint descriptor. */
-typedef const VUSBDESCENDPOINT *PCVUSBDESCENDPOINT;
-
-#pragma pack() /* end of the byte packing. */
-
-
-/**
- * USB configuration descriptor, the parsed variant used by VUSB.
- */
-typedef struct VUSBDESCCONFIGEX
-{
-    /** The USB descriptor data.
-     * @remark  The wTotalLength member is recalculated before the data is passed to the guest. */
-    VUSBDESCCONFIG Core;
-    /** Pointer to additional descriptor bytes following what's covered by VUSBDESCCONFIG. */
-    void *pvMore;
-    /** Pointer to an array of the interfaces referenced in the configuration.
-     * Core.bNumInterfaces in size. */
-    const struct VUSBINTERFACE *paIfs;
-} VUSBDESCCONFIGEX;
-/** Pointer to a parsed USB configuration descriptor. */
-typedef VUSBDESCCONFIGEX *PVUSBDESCCONFIGEX;
-/** Pointer to a const parsed USB configuration descriptor. */
-typedef const VUSBDESCCONFIGEX *PCVUSBDESCCONFIGEX;
-
-
-/**
- * For tracking the alternate interface settings of a configuration.
- */
-typedef struct VUSBINTERFACE
-{
-    /** Pointer to an array of interfaces. */
-    const struct VUSBDESCINTERFACEEX *paSettings;
-    /** The number of entries in the array. */
-    uint32_t cSettings;
-} VUSBINTERFACE;
-/** Pointer to a VUSBINTERFACE. */
-typedef VUSBINTERFACE *PVUSBINTERFACE;
-/** Pointer to a const VUSBINTERFACE. */
-typedef const VUSBINTERFACE *PCVUSBINTERFACE;
-
-
-/**
- * USB interface descriptor, the parsed variant used by VUSB.
- */
-typedef struct VUSBDESCINTERFACEEX
-{
-    /** The USB descriptor data. */
-    VUSBDESCINTERFACE Core;
-    /** Pointer to additional descriptor bytes following what's covered by VUSBDESCINTERFACE. */
-    const void *pvMore;
-    /** Pointer to additional class- or vendor-specific interface descriptors. */
-    const void *pvClass;
-    /** Size of class- or vendor-specific descriptors. */
-    uint16_t cbClass;
-    /** Pointer to an array of the endpoints referenced by the interface.
-     * Core.bNumEndpoints in size. */
-    const struct VUSBDESCENDPOINTEX *paEndpoints;
-} VUSBDESCINTERFACEEX;
-/** Pointer to an prased USB interface descriptor. */
-typedef VUSBDESCINTERFACEEX *PVUSBDESCINTERFACEEX;
-/** Pointer to a const parsed USB interface descriptor. */
-typedef const VUSBDESCINTERFACEEX *PCVUSBDESCINTERFACEEX;
-
-
-/**
- * USB endpoint descriptor, the parsed variant used by VUSB.
- */
-typedef struct VUSBDESCENDPOINTEX
-{
-    /** The USB descriptor data.
-     * @remark The wMaxPacketSize member is converted to native endian. */
-    VUSBDESCENDPOINT Core;
-    /** Pointer to additional descriptor bytes following what's covered by VUSBDESCENDPOINT. */
-    const void *pvMore;
-    /** Pointer to additional class- or vendor-specific interface descriptors. */
-    const void *pvClass;
-    /** Size of class- or vendor-specific descriptors. */
-    uint16_t cbClass;
-} VUSBDESCENDPOINTEX;
-/** Pointer to a parsed USB endpoint descriptor. */
-typedef VUSBDESCENDPOINTEX *PVUSBDESCENDPOINTEX;
-/** Pointer to a const parsed USB endpoint descriptor. */
-typedef const VUSBDESCENDPOINTEX *PCVUSBDESCENDPOINTEX;
-
-
-/** @name USB Control message recipient codes (from spec)
- * @{ */
-#define VUSB_TO_DEVICE          0x0
-#define VUSB_TO_INTERFACE       0x1
-#define VUSB_TO_ENDPOINT        0x2
-#define VUSB_TO_OTHER           0x3
-#define VUSB_RECIP_MASK         0x1f
-/** @} */
-
-/** @name USB control pipe setup packet structure (from spec)
- * @{ */
-#define VUSB_REQ_SHIFT          (5)
-#define VUSB_REQ_STANDARD       (0x0 << VUSB_REQ_SHIFT)
-#define VUSB_REQ_CLASS          (0x1 << VUSB_REQ_SHIFT)
-#define VUSB_REQ_VENDOR         (0x2 << VUSB_REQ_SHIFT)
-#define VUSB_REQ_RESERVED       (0x3 << VUSB_REQ_SHIFT)
-#define VUSB_REQ_MASK           (0x3 << VUSB_REQ_SHIFT)
-/** @} */
-
-#define VUSB_DIR_TO_DEVICE      0x00
-#define VUSB_DIR_TO_HOST        0x80
-#define VUSB_DIR_MASK           0x80
-
-/**
- * USB Setup request (from spec)
- */
-typedef struct vusb_setup
-{
-    uint8_t  bmRequestType;
-    uint8_t  bRequest;
-    uint16_t wValue;
-    uint16_t wIndex;
-    uint16_t wLength;
-} VUSBSETUP;
-/** Pointer to a setup request. */
-typedef VUSBSETUP *PVUSBSETUP;
-/** Pointer to a const setup request. */
-typedef const VUSBSETUP *PCVUSBSETUP;
-
-/** @name USB Standard device requests (from spec)
- * @{ */
-#define VUSB_REQ_GET_STATUS         0x00
-#define VUSB_REQ_CLEAR_FEATURE      0x01
-#define VUSB_REQ_SET_FEATURE        0x03
-#define VUSB_REQ_SET_ADDRESS        0x05
-#define VUSB_REQ_GET_DESCRIPTOR     0x06
-#define VUSB_REQ_SET_DESCRIPTOR     0x07
-#define VUSB_REQ_GET_CONFIGURATION  0x08
-#define VUSB_REQ_SET_CONFIGURATION  0x09
-#define VUSB_REQ_GET_INTERFACE      0x0a
-#define VUSB_REQ_SET_INTERFACE      0x0b
-#define VUSB_REQ_SYNCH_FRAME        0x0c
-#define VUSB_REQ_MAX                0x0d
-/** @} */
-
-/** @} */ /* end of grp_vusb_std */
-
-
-
-/** @name USB Standard version flags.
- * @{ */
-/** Indicates USB 1.1 support. */
-#define VUSB_STDVER_11              RT_BIT(1)
-/** Indicates USB 2.0 support. */
-#define VUSB_STDVER_20              RT_BIT(2)
-/** @} */
-
-
-/** Pointer to a VBox USB device interface. */
-typedef struct VUSBIDEVICE      *PVUSBIDEVICE;
-
-/** Pointer to a VUSB RootHub port interface. */
-typedef struct VUSBIROOTHUBPORT *PVUSBIROOTHUBPORT;
-
-/** Pointer to an USB request descriptor. */
-typedef struct VUSBURB          *PVUSBURB;
-
-
-
-/**
- * VBox USB port bitmap.
- *
- * Bit 0 == Port 0, ... , Bit 127 == Port 127.
- */
-typedef struct VUSBPORTBITMAP
-{
-    /** 128 bits */
-    char ach[16];
-} VUSBPORTBITMAP;
-/** Pointer to a VBox USB port bitmap. */
-typedef VUSBPORTBITMAP *PVUSBPORTBITMAP;
-
-#ifndef RDESKTOP
-
-/**
- * The VUSB RootHub port interface provided by the HCI (down).
- * Pair with VUSBIROOTCONNECTOR
- */
-typedef struct VUSBIROOTHUBPORT
-{
-    /**
-     * Get the number of avilable ports in the hub.
-     *
-     * @returns The number of ports available.
-     * @param   pInterface      Pointer to this structure.
-     * @param   pAvailable      Bitmap indicating the available ports. Set bit == available port.
-     */
-    DECLR3CALLBACKMEMBER(unsigned, pfnGetAvailablePorts,(PVUSBIROOTHUBPORT pInterface, PVUSBPORTBITMAP pAvailable));
-
-    /**
-     * Gets the supported USB versions.
-     *
-     * @returns The mask of supported USB versions.
-     * @param   pInterface      Pointer to this structure.
-     */
-    DECLR3CALLBACKMEMBER(uint32_t, pfnGetUSBVersions,(PVUSBIROOTHUBPORT pInterface));
-
-    /**
-     * A device is being attached to a port in the roothub.
-     *
-     * @param   pInterface      Pointer to this structure.
-     * @param   pDev            Pointer to the device being attached.
-     * @param   uPort           The port number assigned to the device.
-     */
-    DECLR3CALLBACKMEMBER(int, pfnAttach,(PVUSBIROOTHUBPORT pInterface, PVUSBIDEVICE pDev, unsigned uPort));
-
-    /**
-     * A device is being detached from a port in the roothub.
-     *
-     * @param   pInterface      Pointer to this structure.
-     * @param   pDev            Pointer to the device being detached.
-     * @param   uPort           The port number assigned to the device.
-     */
-    DECLR3CALLBACKMEMBER(void, pfnDetach,(PVUSBIROOTHUBPORT pInterface, PVUSBIDEVICE pDev, unsigned uPort));
-
-    /**
-     * Reset the root hub.
-     *
-     * @returns VBox status code.
-     * @param   pInterface      Pointer to this structure.
-     * @param   pResetOnLinux   Whether or not to do real reset on linux.
-     */
-    DECLR3CALLBACKMEMBER(int, pfnReset,(PVUSBIROOTHUBPORT pInterface, bool fResetOnLinux));
-
-    /**
-     * Transfer completion callback routine.
-     *
-     * VUSB will call this when a transfer have been completed
-     * in a one or another way.
-     *
-     * @param   pInterface      Pointer to this structure.
-     * @param   pUrb            Pointer to the URB in question.
-     */
-    DECLR3CALLBACKMEMBER(void, pfnXferCompletion,(PVUSBIROOTHUBPORT pInterface, PVUSBURB urb));
-
-    /**
-     * Handle transfer errors.
-     *
-     * VUSB calls this when a transfer attempt failed. This function will respond
-     * indicating wheter to retry or complete the URB with failure.
-     *
-     * @returns Retry indicator.
-     * @param   pInterface      Pointer to this structure.
-     * @param   pUrb            Pointer to the URB in question.
-     */
-    DECLR3CALLBACKMEMBER(bool, pfnXferError,(PVUSBIROOTHUBPORT pInterface, PVUSBURB pUrb));
-
-    /** Alignment dummy. */
-    RTR3PTR Alignment;
-
-} VUSBIROOTHUBPORT;
-/** VUSBIROOTHUBPORT interface ID. */
-#define VUSBIROOTHUBPORT_IID                    "e38e2978-7aa2-4860-94b6-9ef4a066d8a0"
-
-
-/** Pointer to a VUSB RootHub connector interface. */
-typedef struct VUSBIROOTHUBCONNECTOR *PVUSBIROOTHUBCONNECTOR;
-/**
- * The VUSB RootHub connector interface provided by the VBox USB RootHub driver
- * (up).
- * Pair with VUSBIROOTHUBPORT.
- */
-typedef struct VUSBIROOTHUBCONNECTOR
-{
-    /**
-     * Allocates a new URB for a transfer.
-     *
-     * Either submit using pfnSubmitUrb or free using VUSBUrbFree().
-     *
-     * @returns Pointer to a new URB.
-     * @returns NULL on failure - try again later.
-     *          This will not fail if the device wasn't found. We'll fail it
-     *          at submit time, since that makes the usage of this api simpler.
-     * @param   pInterface  Pointer to this struct.
-     * @param   DstAddress  The destination address of the URB.
-     * @param   cbData      The amount of data space required.
-     * @param   cTds        The amount of TD space.
-     */
-    DECLR3CALLBACKMEMBER(PVUSBURB, pfnNewUrb,(PVUSBIROOTHUBCONNECTOR pInterface, uint8_t DstAddress, uint32_t cbData, uint32_t cTds));
-
-    /**
-     * Submits a URB for transfer.
-     * The transfer will do asynchronously if possible.
-     *
-     * @returns VBox status code.
-     * @param   pInterface  Pointer to this struct.
-     * @param   pUrb        Pointer to the URB returned by pfnNewUrb.
-     *                      The URB will be freed in case of failure.
-     * @param   pLed        Pointer to USB Status LED
-     */
-    DECLR3CALLBACKMEMBER(int, pfnSubmitUrb,(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb, struct PDMLED *pLed));
-
-    /**
-     * Call to service asynchronous URB completions in a polling fashion.
-     *
-     * Reaped URBs will be finished by calling the completion callback,
-     * thus there is no return code or input or anything from this function
-     * except for potential state changes elsewhere.
-     *
-     * @returns VINF_SUCCESS if no URBs are pending upon return.
-     * @returns VERR_TIMEOUT if one or more URBs are still in flight upon returning.
-     * @returns Other VBox status code.
-     *
-     * @param   pInterface  Pointer to this struct.
-     * @param   cMillies    Number of milliseconds to poll for completion.
-     */
-    DECLR3CALLBACKMEMBER(void, pfnReapAsyncUrbs,(PVUSBIROOTHUBCONNECTOR pInterface, RTMSINTERVAL cMillies));
-
-    /**
-     * Cancels and completes - with CRC failure - all in-flight async URBs.
-     * This is typically done before saving a state.
-     *
-     * @param   pInterface  Pointer to this struct.
-     */
-    DECLR3CALLBACKMEMBER(void, pfnCancelAllUrbs,(PVUSBIROOTHUBCONNECTOR pInterface));
-
-    /**
-     * Attach the device to the root hub.
-     * The device must not be attached to any hub for this call to succeed.
-     *
-     * @returns VBox status code.
-     * @param   pInterface  Pointer to this struct.
-     * @param   pDevice     Pointer to the device (interface) attach.
-     */
-    DECLR3CALLBACKMEMBER(int, pfnAttachDevice,(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice));
-
-    /**
-     * Detach the device from the root hub.
-     * The device must already be attached for this call to succeed.
-     *
-     * @returns VBox status code.
-     * @param   pInterface  Pointer to this struct.
-     * @param   pDevice     Pointer to the device (interface) to detach.
-     */
-    DECLR3CALLBACKMEMBER(int, pfnDetachDevice,(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice));
-
-} VUSBIROOTHUBCONNECTOR;
-/** VUSBIROOTHUBCONNECTOR interface ID. */
-#define VUSBIROOTHUBCONNECTOR_IID               "d9a90c59-e3ff-4dff-9754-844557c3f7a0"
-
-
-#ifdef IN_RING3
-/** @copydoc VUSBIROOTHUBCONNECTOR::pfnNewUrb */
-DECLINLINE(PVUSBURB) VUSBIRhNewUrb(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t DstAddress, uint32_t cbData, uint32_t cTds)
-{
-    return pInterface->pfnNewUrb(pInterface, DstAddress, cbData, cTds);
-}
-
-/** @copydoc VUSBIROOTHUBCONNECTOR::pfnSubmitUrb */
-DECLINLINE(int) VUSBIRhSubmitUrb(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb, struct PDMLED *pLed)
-{
-    return pInterface->pfnSubmitUrb(pInterface, pUrb, pLed);
-}
-
-/** @copydoc VUSBIROOTHUBCONNECTOR::pfnReapAsyncUrbs */
-DECLINLINE(void) VUSBIRhReapAsyncUrbs(PVUSBIROOTHUBCONNECTOR pInterface, RTMSINTERVAL cMillies)
-{
-    pInterface->pfnReapAsyncUrbs(pInterface, cMillies);
-}
-
-/** @copydoc VUSBIROOTHUBCONNECTOR::pfnCancelAllUrbs */
-DECLINLINE(void) VUSBIRhCancelAllUrbs(PVUSBIROOTHUBCONNECTOR pInterface)
-{
-    pInterface->pfnCancelAllUrbs(pInterface);
-}
-
-/** @copydoc VUSBIROOTHUBCONNECTOR::pfnAttachDevice */
-DECLINLINE(int) VUSBIRhAttachDevice(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice)
-{
-    return pInterface->pfnAttachDevice(pInterface, pDevice);
-}
-
-/** @copydoc VUSBIROOTHUBCONNECTOR::pfnDetachDevice */
-DECLINLINE(int) VUSBIRhDetachDevice(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice)
-{
-    return pInterface->pfnDetachDevice(pInterface, pDevice);
-}
-#endif /* IN_RING3 */
-
-
-
-/** Pointer to a Root Hub Configuration Interface. */
-typedef struct VUSBIRHCONFIG *PVUSBIRHCONFIG;
-/**
- * Root Hub Configuration Interface (intended for MAIN).
- * No interface pair.
- */
-typedef struct VUSBIRHCONFIG
-{
-    /**
-     * Creates a USB proxy device and attaches it to the root hub.
-     *
-     * @returns VBox status code.
-     * @param   pInterface      Pointer to the root hub configuration interface structure.
-     * @param   pUuid           Pointer to the UUID for the new device.
-     * @param   fRemote         Whether the device must use the VRDP backend.
-     * @param   pszAddress      OS specific device address.
-     * @param   pvBackend       An opaque pointer for the backend. Only used by
-     *                          the VRDP backend so far.
-     */
-    DECLR3CALLBACKMEMBER(int, pfnCreateProxyDevice,(PVUSBIRHCONFIG pInterface, PCRTUUID pUuid, bool fRemote, const char *pszAddress, void *pvBackend));
-
-    /**
-     * Removes a USB proxy device from the root hub and destroys it.
-     *
-     * @returns VBox status code.
-     * @param   pInterface      Pointer to the root hub configuration interface structure.
-     * @param   pUuid           Pointer to the UUID for the device.
-     */
-    DECLR3CALLBACKMEMBER(int, pfnDestroyProxyDevice,(PVUSBIRHCONFIG pInterface, PCRTUUID pUuid));
-
-} VUSBIRHCONFIG;
-/** VUSBIRHCONFIG interface ID. */
-#define VUSBIRHCONFIG_IID                       "c354cd97-e85f-465e-bc12-b58798465f52"
-
-
-#ifdef IN_RING3
-/** @copydoc  VUSBIRHCONFIG::pfnCreateProxyDevice */
-DECLINLINE(int) VUSBIRhCreateProxyDevice(PVUSBIRHCONFIG pInterface, PCRTUUID pUuid, bool fRemote, const char *pszAddress, void *pvBackend)
-{
-    return pInterface->pfnCreateProxyDevice(pInterface, pUuid, fRemote, pszAddress, pvBackend);
-}
-
-/** @copydoc VUSBIRHCONFIG::pfnDestroyProxyDevice */
-DECLINLINE(int) VUSBIRhDestroyProxyDevice(PVUSBIRHCONFIG pInterface, PCRTUUID pUuid)
-{
-    return pInterface->pfnDestroyProxyDevice(pInterface, pUuid);
-}
-#endif /* IN_RING3 */
-
-#endif /* ! RDESKTOP */
-
-
-/**
- * VUSB device reset completion callback function.
- * This is called by the reset thread when the reset has been completed.
- *
- * @param   pDev        Pointer to the virtual USB device core.
- * @param   rc      The VBox status code of the reset operation.
- * @param   pvUser      User specific argument.
- *
- * @thread  The reset thread or EMT.
- */
-typedef DECLCALLBACK(void) FNVUSBRESETDONE(PVUSBIDEVICE pDevice, int rc, void *pvUser);
-/** Pointer to a device reset completion callback function (FNUSBRESETDONE). */
-typedef FNVUSBRESETDONE *PFNVUSBRESETDONE;
-
-/**
- * The state of a VUSB Device.
- *
- * @remark  The order of these states is vital.
- */
-typedef enum VUSBDEVICESTATE
-{
-    VUSB_DEVICE_STATE_INVALID = 0,
-    VUSB_DEVICE_STATE_DETACHED,
-    VUSB_DEVICE_STATE_ATTACHED,
-    VUSB_DEVICE_STATE_POWERED,
-    VUSB_DEVICE_STATE_DEFAULT,
-    VUSB_DEVICE_STATE_ADDRESS,
-    VUSB_DEVICE_STATE_CONFIGURED,
-    VUSB_DEVICE_STATE_SUSPENDED,
-    /** The device is being reset. Don't mess with it.
-     * Next states: VUSB_DEVICE_STATE_DEFAULT, VUSB_DEVICE_STATE_DESTROYED
-     */
-    VUSB_DEVICE_STATE_RESET,
-    /** The device has been destroy. */
-    VUSB_DEVICE_STATE_DESTROYED,
-    /** The usual 32-bit hack. */
-    VUSB_DEVICE_STATE_32BIT_HACK = 0x7fffffff
-} VUSBDEVICESTATE;
-
-#ifndef RDESKTOP
-
-/**
- * USB Device Interface (up).
- * No interface pair.
- */
-typedef struct VUSBIDEVICE
-{
-    /**
-     * Resets the device.
-     *
-     * Since a device reset shall take at least 10ms from the guest point of view,
-     * it must be performed asynchronously. We create a thread which performs this
-     * operation and ensures it will take at least 10ms.
-     *
-     * At times - like init - a synchronous reset is required, this can be done
-     * by passing NULL for pfnDone.
-     *
-     * -- internal stuff, move it --
-     * While the device is being reset it is in the VUSB_DEVICE_STATE_RESET state.
-     * On completion it will be in the VUSB_DEVICE_STATE_DEFAULT state if successful,
-     * or in the VUSB_DEVICE_STATE_DETACHED state if the rest failed.
-     * -- internal stuff, move it --
-     *
-     * @returns VBox status code.
-     * @param   pInterface      Pointer to this structure.
-     * @param   fResetOnLinux   Set if we can permit a real reset and a potential logical
-     *                          device reconnect on linux hosts.
-     * @param   pfnDone         Pointer to the completion routine. If NULL a synchronous
-     *                          reset  is preformed not respecting the 10ms.
-     * @param   pvUser          User argument to the completion routine.
-     * @param   pVM             Pointer to the VM handle if callback in EMT is required. (optional)
-     */
-    DECLR3CALLBACKMEMBER(int, pfnReset,(PVUSBIDEVICE pInterface, bool fResetOnLinux,
-                                        PFNVUSBRESETDONE pfnDone, void *pvUser, PVM pVM));
-
-    /**
-     * Powers on the device.
-     *
-     * @returns VBox status code.
-     * @param   pInterface      Pointer to the device interface structure.
-     */
-    DECLR3CALLBACKMEMBER(int, pfnPowerOn,(PVUSBIDEVICE pInterface));
-
-    /**
-     * Powers off the device.
-     *
-     * @returns VBox status code.
-     * @param   pInterface      Pointer to the device interface structure.
-     */
-    DECLR3CALLBACKMEMBER(int, pfnPowerOff,(PVUSBIDEVICE pInterface));
-
-    /**
-     * Get the state of the device.
-     *
-     * @returns Device state.
-     * @param   pInterface      Pointer to the device interface structure.
-     */
-    DECLR3CALLBACKMEMBER(VUSBDEVICESTATE, pfnGetState,(PVUSBIDEVICE pInterface));
-
-} VUSBIDEVICE;
-/** VUSBIDEVICE interface ID. */
-#define VUSBIDEVICE_IID                         "88732dd3-0ccd-4625-b040-48804ac7a217"
-
-
-#ifdef IN_RING3
-/**
- * Resets the device.
- *
- * Since a device reset shall take at least 10ms from the guest point of view,
- * it must be performed asynchronously. We create a thread which performs this
- * operation and ensures it will take at least 10ms.
- *
- * At times - like init - a synchronous reset is required, this can be done
- * by passing NULL for pfnDone.
- *
- * -- internal stuff, move it --
- * While the device is being reset it is in the VUSB_DEVICE_STATE_RESET state.
- * On completion it will be in the VUSB_DEVICE_STATE_DEFAULT state if successful,
- * or in the VUSB_DEVICE_STATE_DETACHED state if the rest failed.
- * -- internal stuff, move it --
- *
- * @returns VBox status code.
- * @param   pInterface      Pointer to the device interface structure.
- * @param   fResetOnLinux   Set if we can permit a real reset and a potential logical
- *                          device reconnect on linux hosts.
- * @param   pfnDone         Pointer to the completion routine. If NULL a synchronous
- *                          reset  is preformed not respecting the 10ms.
- * @param   pvUser          User argument to the completion routine.
- * @param   pVM             Pointer to the VM handle if callback in EMT is required. (optional)
- */
-DECLINLINE(int) VUSBIDevReset(PVUSBIDEVICE pInterface, bool fResetOnLinux, PFNVUSBRESETDONE pfnDone, void *pvUser, PVM pVM)
-{
-    return pInterface->pfnReset(pInterface, fResetOnLinux, pfnDone, pvUser, pVM);
-}
-
-/**
- * Powers on the device.
- *
- * @returns VBox status code.
- * @param   pInterface      Pointer to the device interface structure.
- */
-DECLINLINE(int) VUSBIDevPowerOn(PVUSBIDEVICE pInterface)
-{
-    return pInterface->pfnPowerOn(pInterface);
-}
-
-/**
- * Powers off the device.
- *
- * @returns VBox status code.
- * @param   pInterface      Pointer to the device interface structure.
- */
-DECLINLINE(int) VUSBIDevPowerOff(PVUSBIDEVICE pInterface)
-{
-    return pInterface->pfnPowerOff(pInterface);
-}
-
-/**
- * Get the state of the device.
- *
- * @returns Device state.
- * @param   pInterface      Pointer to the device interface structure.
- */
-DECLINLINE(VUSBDEVICESTATE) VUSBIDevGetState(PVUSBIDEVICE pInterface)
-{
-    return pInterface->pfnGetState(pInterface);
-}
-#endif /* IN_RING3 */
-
-#endif /* ! RDESKTOP */
-
-/** @name URB
- * @{ */
-
-/**
- * VUSB Transfer status codes.
- */
-typedef enum VUSBSTATUS
-{
-    /** Transer was ok. */
-    VUSBSTATUS_OK = 0,
-    /** Transfer stalled, endpoint halted. */
-    VUSBSTATUS_STALL,
-    /** Device not responding. */
-    VUSBSTATUS_DNR,
-    /** CRC error. */
-    VUSBSTATUS_CRC,
-    /** Data overrun error. */
-    VUSBSTATUS_DATA_UNDERRUN,
-    /** Data overrun error. */
-    VUSBSTATUS_DATA_OVERRUN,
-    /** The isochronous buffer hasn't been touched. */
-    VUSBSTATUS_NOT_ACCESSED,
-    /** Invalid status. */
-    VUSBSTATUS_INVALID = 0x7f
-} VUSBSTATUS;
-
-
-/**
- * VUSB Transfer types.
- */
-typedef enum VUSBXFERTYPE
-{
-    /** Control message. Used to represent a single control transfer. */
-    VUSBXFERTYPE_CTRL = 0,
-    /* Isochronous transfer. */
-    VUSBXFERTYPE_ISOC,
-    /** Bulk transfer. */
-    VUSBXFERTYPE_BULK,
-    /** Interrupt transfer. */
-    VUSBXFERTYPE_INTR,
-    /** Complete control message. Used to represent an entire control message. */
-    VUSBXFERTYPE_MSG,
-    /** Invalid transfer type. */
-    VUSBXFERTYPE_INVALID = 0x7f
-} VUSBXFERTYPE;
-
-
-/**
- * VUSB transfer direction.
- */
-typedef enum VUSBDIRECTION
-{
-    /** Setup */
-    VUSBDIRECTION_SETUP = 0,
-#define VUSB_DIRECTION_SETUP    VUSBDIRECTION_SETUP
-    /** In - Device to host. */
-    VUSBDIRECTION_IN = 1,
-#define VUSB_DIRECTION_IN       VUSBDIRECTION_IN
-    /** Out - Host to device. */
-    VUSBDIRECTION_OUT = 2,
-#define VUSB_DIRECTION_OUT  VUSBDIRECTION_OUT
-    /** Invalid direction */
-    VUSBDIRECTION_INVALID = 0x7f
-} VUSBDIRECTION;
-
-/**
- * The URB states
- */
-typedef enum VUSBURBSTATE
-{
-    /** The usual invalid state. */
-    VUSBURBSTATE_INVALID = 0,
-    /** The URB is free, i.e. not in use.
-     * Next state: ALLOCATED */
-    VUSBURBSTATE_FREE,
-    /** The URB is allocated, i.e. being prepared for submission.
-     * Next state: FREE, IN_FLIGHT */
-    VUSBURBSTATE_ALLOCATED,
-    /** The URB is in flight.
-     * Next state: REAPED, CANCELLED */
-    VUSBURBSTATE_IN_FLIGHT,
-    /** The URB has been reaped and is being completed.
-     * Next state: FREE */
-    VUSBURBSTATE_REAPED,
-    /** The URB has been cancelled and is awaiting reaping and immediate freeing.
-     * Next state: FREE */
-    VUSBURBSTATE_CANCELLED,
-    /** The end of the valid states (exclusive). */
-    VUSBURBSTATE_END,
-    /** The usual 32-bit blow up. */
-    VUSBURBSTATE_32BIT_HACK = 0x7fffffff
-} VUSBURBSTATE;
-
-
-/**
- * Information about a isochronous packet.
- */
-typedef struct VUSBURBISOCPKT
-{
-    /** The size of the packet.
-     * IN: The packet size. I.e. the number of bytes to the next packet or end of buffer.
-     * OUT: The actual size transfered. */
-    uint16_t        cb;
-    /** The offset of the packet. (Relative to VUSBURB::abData[0].)
-     * OUT: This can be changed by the USB device if it does some kind of buffer squeezing. */
-    uint16_t        off;
-    /** The status of the transfer.
-     * IN: VUSBSTATUS_INVALID
-     * OUT: VUSBSTATUS_INVALID if nothing was done, otherwise the correct status. */
-    VUSBSTATUS      enmStatus;
-} VUSBURBISOCPKT;
-/** Pointer to a isochronous packet. */
-typedef VUSBURBISOCPKT *PVUSBURBISOCPTK;
-/** Pointer to a const isochronous packet. */
-typedef const VUSBURBISOCPKT *PCVUSBURBISOCPKT;
-
-/**
- * Asynchronous USB request descriptor
- */
-typedef struct VUSBURB
-{
-    /** URB magic value. */
-    uint32_t        u32Magic;
-    /** The USR state. */
-    VUSBURBSTATE    enmState;
-    /** URB description, can be null. intended for logging. */
-    char           *pszDesc;
-
-#ifdef RDESKTOP
-    /** The next URB in rdesktop-vrdp's linked list */
-    PVUSBURB        pNext;
-    /** The previous URB in rdesktop-vrdp's linked list */
-    PVUSBURB        pPrev;
-    /** The vrdp handle for the URB */
-    uint32_t        handle;
-    /** Pointer used to find the usb proxy device */
-    struct VUSBDEV *pDev;
-#endif
-
-    /** The VUSB data. */
-    struct VUSBURBVUSB
-    {
-        /** URB chain pointer. */
-        PVUSBURB        pNext;
-        /** URB chain pointer. */
-        PVUSBURB       *ppPrev;
-        /** Pointer to the original for control messages. */
-        PVUSBURB        pCtrlUrb;
-        /** Pointer to the VUSB device.
-         * This may be NULL if the destination address is invalid. */
-        struct VUSBDEV *pDev;
-        /** Sepcific to the pfnFree function. */
-        void           *pvFreeCtx;
-        /**
-         * Callback which will free the URB once it's reaped and completed.
-         * @param   pUrb    The URB.
-         */
-        DECLCALLBACKMEMBER(void, pfnFree)(PVUSBURB pUrb);
-        /** Submit timestamp. (logging only) */
-        uint64_t        u64SubmitTS;
-        /** The allocated data length. */
-        uint32_t        cbDataAllocated;
-        /** The allocated TD length. */
-        uint32_t        cTdsAllocated;
-    } VUsb;
-
-    /** The host controller data. */
-    struct VUSBURBHCI
-    {
-        /** The endpoint descriptor address. */
-        RTGCPHYS32      EdAddr;
-        /** Number of Tds in the array. */
-        uint32_t        cTds;
-        /** Pointer to an array of TD info items.*/
-        struct VUSBURBHCITD
-        {
-            /** Type of TD (private) */
-            uint32_t        TdType;
-            /** The address of the */
-            RTGCPHYS32      TdAddr;
-            /** A copy of the TD. */
-            uint32_t        TdCopy[16];
-        }              *paTds;
-        /** URB chain pointer. */
-        PVUSBURB        pNext;
-        /** When this URB was created.
-         * (Used for isochronous frames and for logging.) */
-        uint32_t        u32FrameNo;
-        /** Flag indicating that the TDs have been unlinked. */
-        bool            fUnlinked;
-    } Hci;
-
-    /** The device data. */
-    struct VUSBURBDEV
-    {
-        /** Pointer to private device specific data.  */
-        void           *pvPrivate;
-        /** Used by the device when linking the URB in some list of its own.   */
-        PVUSBURB        pNext;
-    } Dev;
-
-#ifndef RDESKTOP
-    /** The USB device instance this belongs to.
-     * This is NULL if the device address is invalid, in which case this belongs to the hub. */
-    PPDMUSBINS      pUsbIns;
-#endif
-    /** The device address.
-     * This is set at allocation time. */
-    uint8_t         DstAddress;
-
-    /** The endpoint.
-     * IN: Must be set before submitting the URB.
-     * @remark This does not have the high bit (direction) set! */
-    uint8_t         EndPt;
-    /** The transfer type.
-     * IN: Must be set before submitting the URB. */
-    VUSBXFERTYPE    enmType;
-    /** The transfer direction.
-     * IN: Must be set before submitting the URB. */
-    VUSBDIRECTION   enmDir;
-    /** Indicates whether it is OK to receive/send less data than requested.
-     * IN: Must be initialized before submitting the URB. */
-    bool            fShortNotOk;
-    /** The transfer status.
-     * OUT: This is set when reaping the URB. */
-    VUSBSTATUS      enmStatus;
-
-    /** The number of isochronous packets describe in aIsocPkts.
-     * This is ignored when enmType isn't VUSBXFERTYPE_ISOC. */
-    uint32_t        cIsocPkts;
-    /** The iso packets within abData.
-     * This is ignored when enmType isn't VUSBXFERTYPE_ISOC. */
-    VUSBURBISOCPKT  aIsocPkts[8];
-
-    /** The message length.
-     * IN: The amount of data to send / receive - set at allocation time.
-     * OUT: The amount of data sent / received. */
-    uint32_t        cbData;
-    /** The message data.
-     * IN: On host to device transfers, the data to send.
-     * OUT: On device to host transfers, the data to received. */
-    uint8_t         abData[8*_1K];
-} VUSBURB;
-
-/** The magic value of a valid VUSBURB. (Murakami Haruki) */
-#define VUSBURB_MAGIC       UINT32_C(0x19490112)
-
-/** @} */
-
-
-/** @} */
-
-RT_C_DECLS_END
-
-#endif
