VirtualBox

Changeset 31247 in vbox for trunk


Ignore:
Timestamp:
Jul 30, 2010 1:37:49 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
64261
Message:

RDP/client: updates to the RDP client code

Location:
trunk/src/VBox/RDP/client/vrdp
Files:
1 added
4 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/RDP/client/vrdp/USBProxyDevice-linux.c

    r28800 r31247  
     1/* $Id$ */
    12/** @file
    2  *
    3  * VUSB Device - USB Device Proxy, the Linux backend.
     3 * USB device proxy - the Linux backend.
    44 */
    55
     
    77 * Copyright (C) 2006-2007 Oracle Corporation
    88 *
    9  * This file is part of VirtualBox Open Source Edition (OSE), as
    10  * available from http://www.virtualbox.org. This file is free software;
    11  * you can redistribute it and/or modify it under the terms of the GNU
    12  * General Public License (GPL) as published by the Free Software
    13  * Foundation, in version 2 as it comes in the "COPYING" file of the
    14  * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
    15  * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
     9 * Oracle Corporation confidential
     10 * All rights reserved
    1611 */
    1712
     
    3126*******************************************************************************/
    3227#define LOG_GROUP LOG_GROUP_DRV_USBPROXY
    33 #if defined(VBOX) && !defined(RDESKTOP)
     28#ifndef RDESKTOP
    3429# include <iprt/stdint.h>
    3530#endif
     
    4742#include <fcntl.h>
    4843#include <errno.h>
    49 #include <ctype.h>
    5044#ifdef VBOX_WITH_LINUX_COMPILER_H
    5145# include <linux/compiler.h>
     
    7165#endif
    7266
    73 #if defined(VBOX) && !defined(RDESKTOP)
     67#ifndef RDESKTOP
    7468# include <VBox/pdm.h>
    7569# include <VBox/err.h>
    7670# include <VBox/log.h>
     71# include <iprt/alloc.h>
    7772# include <iprt/assert.h>
     73# include <iprt/asm.h>
     74# include <iprt/ctype.h>
     75# include <iprt/file.h>
     76# include <iprt/linux/sysfs.h>
    7877# include <iprt/stream.h>
    79 # include <iprt/alloc.h>
     78# include <iprt/string.h>
    8079# include <iprt/thread.h>
    8180# include <iprt/time.h>
    82 # include <iprt/asm.h>
    83 # include <iprt/string.h>
    84 # include <iprt/file.h>
    8581# include "../USBProxyDevice.h"
    8682#else
    8783
    8884# include "../rdesktop.h"
    89 # include "vrdpusb.h"
     85# include "runtime.h"
     86# include "USBProxyDevice.h"
     87# ifdef VBOX_USB_WITH_SYSFS
     88#  include "sysfs.h"
     89# endif
    9090#endif
    9191
     
    102102    /** The kernel URB data */
    103103    struct usbdevfs_urb     KUrb;
     104    /** Space filler for the isochronous packets. */
     105    struct usbdevfs_iso_packet_desc aIsocPktsDonUseTheseUseTheOnesInKUrb[8];
    104106    /** The millisecond timestamp when this URB was submitted. */
    105107    uint64_t                u64SubmitTS;
     
    120122    /** This split element is reaped. */
    121123    bool                    fSplitElementReaped;
     124    /** Size to transfer in remaining fragments of a split URB */
     125    uint32_t                cbSplitRemaining;
    122126} USBPROXYURBLNX, *PUSBPROXYURBLNX;
    123127
     
    142146    /** The tail of the landed linux URBs. */
    143147    PUSBPROXYURBLNX     pTaxingTail;
     148    /** Are we using sysfs to find the active configuration? */
     149    bool                fUsingSysfs;
     150    /** The device node/sysfs path of the device.
     151     * Used to figure out the configuration after a reset. */
     152    char                szPath[1];
    144153} USBPROXYDEVLNX, *PUSBPROXYDEVLNX;
    145154
     
    148157*   Internal Functions                                                         *
    149158*******************************************************************************/
    150 static int usbProxyLinuxDoIoCtl(PUSBPROXYDEV pProxyDev, int iCmd, void *pvArg, bool fHandleNoDev, uint32_t cTries);
     159static int usbProxyLinuxDoIoCtl(PUSBPROXYDEV pProxyDev, unsigned long iCmd, void *pvArg, bool fHandleNoDev, uint32_t cTries);
    151160static void usbProxLinuxUrbUnplugged(PUSBPROXYDEV pProxyDev);
    152161static void usbProxyLinuxSetConnected(PUSBPROXYDEV pProyxDev, int iIf, bool fConnect, bool fQuiet);
     
    154163static void usbProxyLinuxUrbFree(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pUrbLnx);
    155164static void usbProxyLinuxUrbFreeSplitList(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pUrbLnx);
    156 static int usbProxyLinuxFindActiveConfig(PUSBPROXYDEV pProxyDev, const char *pszAddress, int *iFirstCfg);
     165static int usbProxyLinuxFindActiveConfig(PUSBPROXYDEV pProxyDev, const char *pszPath, int *piFirstCfg);
    157166
    158167
     
    172181 * @internal
    173182 */
    174 static int usbProxyLinuxDoIoCtl(PUSBPROXYDEV pProxyDev, int iCmd, void *pvArg, bool fHandleNoDev, uint32_t cTries)
     183static int usbProxyLinuxDoIoCtl(PUSBPROXYDEV pProxyDev, unsigned long iCmd, void *pvArg, bool fHandleNoDev, uint32_t cTries)
    175184{
    176185    int rc;
     
    188197        {
    189198            usbProxLinuxUrbUnplugged(pProxyDev);
    190             Log(("usb-linux: ENODEV -> unplugged. pProxyDev=%p[%s]\n", pProxyDev, pProxyDev->Dev.pszName));
     199            Log(("usb-linux: ENODEV -> unplugged. pProxyDev=%s\n", usbProxyGetName(pProxyDev)));
    191200            errno = ENODEV;
    192201            break;
     
    212221     */
    213222    RTCritSectEnter(&pDevLnx->CritSect);
     223    pProxyDev->fDetached = true;
    214224
    215225    PUSBPROXYURBLNX pUrbTaxing = NULL;
     
    250260
    251261    RTCritSectLeave(&pDevLnx->CritSect);
    252 
    253     vusbDevUnplugged(&pProxyDev->Dev);
    254262}
    255263
     
    261269static void usbProxyLinuxSetConnected(PUSBPROXYDEV pProxyDev, int iIf, bool fConnect, bool fQuiet)
    262270{
    263     struct usbdevfs_ioctl IoCtl;
    264     if (!fQuiet)
    265         LogFlow(("usbProxyLinuxSetConnected: pProxyDev=%p[%s] iIf=%#x fConnect=%d\n",
    266                  pProxyDev, pProxyDev->Dev.pszName, iIf, fConnect));
    267 
    268     IoCtl.ifno = iIf;
    269     IoCtl.ioctl_code = fConnect ? USBDEVFS_CONNECT : USBDEVFS_DISCONNECT;
    270     IoCtl.data = NULL;
    271     if (    usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_IOCTL, &IoCtl, true, UINT32_MAX)
    272         &&  !fQuiet)
    273         Log(("usbProxyLinuxSetConnected: failure, errno=%d. pProxyDev=%p[%s]\n",
    274              errno, pProxyDev, pProxyDev->Dev.pszName));
     271    if (    iIf >= 32
     272        ||  !(pProxyDev->fMaskedIfs & RT_BIT(iIf)))
     273    {
     274        struct usbdevfs_ioctl IoCtl;
     275        if (!fQuiet)
     276            LogFlow(("usbProxyLinuxSetConnected: pProxyDev=%s iIf=%#x fConnect=%RTbool\n",
     277                     usbProxyGetName(pProxyDev), iIf, fConnect));
     278
     279        IoCtl.ifno = iIf;
     280        IoCtl.ioctl_code = fConnect ? USBDEVFS_CONNECT : USBDEVFS_DISCONNECT;
     281        IoCtl.data = NULL;
     282        if (    usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_IOCTL, &IoCtl, true, UINT32_MAX)
     283            &&  !fQuiet)
     284            Log(("usbProxyLinuxSetConnected: failure, errno=%d. pProxyDev=%s\n",
     285                 errno, usbProxyGetName(pProxyDev)));
     286    }
    275287}
    276288
     
    400412 * @returns The Cfg#.
    401413 * @returns -1 if no active config.
    402  * @param   pszAddress      The path to the device. We infere the location of the
    403  *                          devices file, which bus and device number we're looking for.
     414 * @param   pszDevNode      The path to the device. We infere the location of
     415 *                          the devices file, which bus and device number we're
     416 *                          looking for.
    404417 * @param   iFirstCfg       The first configuration. (optional)
    405418 * @internal
    406419 */
    407 static int usbProxyLinuxFindActiveConfig(PUSBPROXYDEV pProxyDev, const char *pszAddress, int *piFirstCfg)
     420static int usbProxyLinuxFindActiveConfigUsbfs(PUSBPROXYDEV pProxyDev, const char *pszDevNode, int *piFirstCfg)
    408421{
    409422    /*
     
    415428
    416429    /*
    417      * Interpret the address and turn it into a path to the devices file.
    418      */
    419     size_t cchAddress = strlen(pszAddress);
    420     char *pszDevices = (char *)RTMemDupEx(pszAddress, cchAddress, sizeof("devices"));
     430     * Parse the usbfs device node path and turn it into a path to the "devices" file,
     431     * picking up the device number and bus along the way.
     432     */
     433    size_t cchDevNode = strlen(pszDevNode);
     434    char *pszDevices = (char *)RTMemDupEx(pszDevNode, cchDevNode, sizeof("devices"));
    421435    AssertReturn(pszDevices, iActiveCfg);
    422436
    423437    /* the device number */
    424     char *psz = pszDevices + cchAddress;
     438    char *psz = pszDevices + cchDevNode;
    425439    while (*psz != '/')
    426440        psz--;
     
    525539}
    526540
    527 int dev2fd (PUSBPROXYDEV pProxyDev)
    528 {
    529     if (pProxyDev)
    530     {
    531         PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
    532 
    533         if (pDevLnx)
    534         {
    535             return pDevLnx->File;
    536         }
    537     }
     541
     542/**
     543 * This finds the active configuration from sysfs.
     544 *
     545 * @returns The Cfg#.
     546 * @returns -1 if no active config.
     547 * @param   pszPath         The sysfs path for the device.
     548 * @param   piFirstCfg      The first configuration. (optional)
     549 * @internal
     550 */
     551static int usbProxyLinuxFindActiveConfigSysfs(PUSBPROXYDEV pProxyDev, const char *pszPath, int *piFirstCfg)
     552{
     553#ifdef VBOX_USB_WITH_SYSFS
     554    if (piFirstCfg != NULL)
     555        *piFirstCfg = pProxyDev->paCfgDescs != NULL
     556                    ? pProxyDev->paCfgDescs[0].Core.bConfigurationValue
     557                    : 1;
     558    return RTLinuxSysFsReadIntFile(10, "%s/bConfigurationValue", pszPath); /* returns -1 on failure */
     559#else  /* !VBOX_USB_WITH_SYSFS */
    538560    return -1;
    539 }
    540 
    541 /**
    542  * Opens the /proc/bus/usb/bus/addr file.
     561#endif /* !VBOX_USB_WITH_SYSFS */
     562}
     563
     564
     565/**
     566 * This finds the active configuration.
     567 *
     568 * @returns The Cfg#.
     569 * @returns -1 if no active config.
     570 * @param   pszPath         The sysfs path for the device, or the usbfs device
     571 *                          node path.
     572 * @param   iFirstCfg       The first configuration. (optional)
     573 * @internal
     574 */
     575static int usbProxyLinuxFindActiveConfig(PUSBPROXYDEV pProxyDev, const char *pszPath, int *piFirstCfg)
     576{
     577    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
     578    if (pDevLnx->fUsingSysfs)
     579        return usbProxyLinuxFindActiveConfigSysfs(pProxyDev, pszPath, piFirstCfg);
     580    return usbProxyLinuxFindActiveConfigUsbfs(pProxyDev, pszPath, piFirstCfg);
     581}
     582
     583
     584/**
     585 * Extracts the Linux file descriptor associated with the kernel USB device.
     586 * This is used by rdesktop-vrdp for polling for events.
     587 * @returns  the FD, or asserts and returns -1 on error
     588 * @param    pProxyDev    The device instance
     589 */
     590RTDECL(int) USBProxyDeviceLinuxGetFD(PUSBPROXYDEV pProxyDev)
     591{
     592    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
     593    AssertReturn(pDevLnx->File != NIL_RTFILE, -1);
     594    return pDevLnx->File;
     595}
     596
     597
     598/**
     599 * Opens the device file.
    543600 *
    544601 * @returns VBox status code.
    545602 * @param   pProxyDev       The device instance.
    546  * @param   pszAddress      The path to the device.
     603 * @param   pszAddress      If we are using usbfs, this is the path to the
     604 *                          device.  If we are using sysfs, this is a string of
     605 *                          the form "sysfs:<sysfs path>//device:<device node>".
     606 *                          In the second case, the two paths are guaranteed
     607 *                          not to contain the substring "//".
    547608 * @param   pvBackend       Backend specific pointer, unused for the linux backend.
    548609 */
     
    550611{
    551612    LogFlow(("usbProxyLinuxOpen: pProxyDev=%p pszAddress=%s\n", pProxyDev, pszAddress));
     613    const char *pszDevNode;
     614    const char *pszPath;
     615    size_t      cchPath;
     616    bool        fUsingSysfs;
     617
     618    /*
     619     * Are we using sysfs or usbfs?
     620     */
     621#ifdef VBOX_USB_WITH_SYSFS
     622    fUsingSysfs = strncmp(pszAddress, "sysfs:", sizeof("sysfs:") - 1) == 0;
     623    if (fUsingSysfs)
     624    {
     625        pszDevNode = strstr(pszAddress, "//device:");
     626        if (!pszDevNode)
     627        {
     628            LogRel(("usbProxyLinuxOpen: Invalid device address: '%s'\n", pszAddress));
     629            pProxyDev->Backend.pv = NULL;
     630            return VERR_INVALID_PARAMETER;
     631        }
     632
     633        pszPath = pszAddress + sizeof("sysfs:") - 1;
     634        cchPath = pszDevNode - pszPath;
     635        pszDevNode += sizeof("//device:") - 1;
     636    }
     637    else
     638#endif  /* VBOX_USB_WITH_SYSFS */
     639    {
     640#ifndef VBOX_USB_WITH_SYSFS
     641        fUsingSysfs = false;
     642#endif
     643        pszPath = pszDevNode = pszAddress;
     644        cchPath = strlen(pszPath);
     645    }
     646
     647    /*
     648     * Try open the device node.
     649     */
    552650    RTFILE File;
    553     int rc = RTFileOpen(&File, pszAddress, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
     651    int rc = RTFileOpen(&File, pszDevNode, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
    554652    if (RT_SUCCESS(rc))
    555653    {
     
    557655         * Allocate and initialize the linux backend data.
    558656         */
    559         PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)RTMemAllocZ(sizeof(*pDevLnx));
     657        PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)RTMemAllocZVar(sizeof(*pDevLnx) + cchPath);
    560658        if (pDevLnx)
    561659        {
     660            pDevLnx->fUsingSysfs = fUsingSysfs;
     661            memcpy(&pDevLnx->szPath[0], pszPath, cchPath);
     662            pDevLnx->szPath[cchPath] = '\0';
    562663            pDevLnx->File = File;
    563664            rc = RTCritSectInit(&pDevLnx->CritSect);
     
    566667                pProxyDev->Backend.pv = pDevLnx;
    567668
    568                 /* brute force rulez */
    569                 unsigned iIf;
    570                 for (iIf = 0; iIf < 256; iIf++)
    571                     usbProxyLinuxSetConnected(pProxyDev, iIf, false, true);
    572 
    573                 /*
    574                  * Determin the active configuration.
    575                  *
    576                  * If there isn't any active configuration, we will get EHOSTUNREACH (113) errors
    577                  * when trying to read the device descriptors in usbProxyDevCreate. So, we'll make
    578                  * the first one active (usually 1) then.
    579                  */
    580                 pProxyDev->cIgnoreSetConfigs = 1;
    581                 int iFirstCfg;
    582                 pProxyDev->iActiveCfg = usbProxyLinuxFindActiveConfig(pProxyDev, pszAddress, &iFirstCfg);
    583                 if (pProxyDev->iActiveCfg == -1)
    584                 {
    585                     usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_SETCONFIGURATION, &iFirstCfg, false, UINT32_MAX);
    586                     pProxyDev->iActiveCfg = usbProxyLinuxFindActiveConfig(pProxyDev, pszAddress, NULL);
    587                     Log(("usbProxyLinuxOpen: No active config! Tried to set %d: iActiveCfg=%d\n", iFirstCfg, pProxyDev->iActiveCfg));
    588                 }
    589 
    590669                LogFlow(("usbProxyLinuxOpen(%p, %s): returns successfully File=%d iActiveCfg=%d\n",
    591670                         pProxyDev, pszAddress, pDevLnx->File, pProxyDev->iActiveCfg));
     
    603682        rc = VERR_VUSB_USBFS_PERMISSION;
    604683
    605     Log(("usbProxyLinuxOpen(%p, %s) failed, rc=%d!\n", pProxyDev, pszAddress, rc));
     684    Log(("usbProxyLinuxOpen(%p, %s) failed, rc=%Rrc!\n", pProxyDev, pszAddress, rc));
    606685    pProxyDev->Backend.pv = NULL;
    607686
     
    612691
    613692/**
     693 * Claims all the interfaces and figures out the
     694 * current configuration.
     695 *
     696 * @returns VINF_SUCCESS.
     697 * @param   pProxyDev       The proxy device.
     698 */
     699static int usbProxyLinuxInit(PUSBPROXYDEV pProxyDev)
     700{
     701    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
     702
     703    /*
     704     * Brute force rulez.
     705     * usbProxyLinuxSetConnected check for masked interfaces.
     706     */
     707    unsigned iIf;
     708    for (iIf = 0; iIf < 256; iIf++)
     709        usbProxyLinuxSetConnected(pProxyDev, iIf, false, true);
     710
     711    /*
     712     * Determin the active configuration.
     713     *
     714     * If there isn't any active configuration, we will get EHOSTUNREACH (113) errors
     715     * when trying to read the device descriptors in usbProxyDevCreate. So, we'll make
     716     * the first one active (usually 1) then.
     717     */
     718    pProxyDev->cIgnoreSetConfigs = 1;
     719    int iFirstCfg;
     720    pProxyDev->iActiveCfg = usbProxyLinuxFindActiveConfig(pProxyDev, pDevLnx->szPath, &iFirstCfg);
     721    if (pProxyDev->iActiveCfg == -1)
     722    {
     723        usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_SETCONFIGURATION, &iFirstCfg, false, UINT32_MAX);
     724        pProxyDev->iActiveCfg = usbProxyLinuxFindActiveConfig(pProxyDev, pDevLnx->szPath, NULL);
     725        Log(("usbProxyLinuxInit: No active config! Tried to set %d: iActiveCfg=%d\n", iFirstCfg, pProxyDev->iActiveCfg));
     726    }
     727    else
     728        Log(("usbProxyLinuxInit(%p): iActiveCfg=%d\n", pProxyDev, pProxyDev->iActiveCfg));
     729    return VINF_SUCCESS;
     730}
     731
     732
     733/**
    614734 * Closes the proxy device.
    615735 */
    616736static void usbProxyLinuxClose(PUSBPROXYDEV pProxyDev)
    617737{
    618     LogFlow(("usbProxyLinuxClose: pProxyDev=%p[%s]\n", pProxyDev, pProxyDev->Dev.pszName));
     738    LogFlow(("usbProxyLinuxClose: pProxyDev=%s\n", usbProxyGetName(pProxyDev)));
    619739    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
    620740    Assert(pDevLnx);
     
    626746     * Resetting it would be a nice start, although we must remember
    627747     * that it might have been disconnected...
    628      */
    629     /* ASSUMES: thread == EMT */
    630     if (!usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_RESET, NULL, false, 10))
    631     {
    632         /* Connect drivers. */
    633         unsigned iIf;
    634         for (iIf = 0; iIf < 256; iIf++)
    635             usbProxyLinuxSetConnected(pProxyDev, iIf, true, true);
    636     }
    637     else
    638         Log(("usbProxyLinuxClose: Reset failed, errno=%d.\n", errno));
    639 
    640     /*
    641      * Now we can close it and free all the resources.
    642      */
    643     RTFileClose(pDevLnx->File);
    644     pDevLnx->File = NIL_RTFILE;
    645 
     748     *
     749     * Don't reset if we're masking interfaces or if construction failed.
     750     */
     751    if (pProxyDev->fInited)
     752    {
     753        /* ASSUMES: thread == EMT */
     754        if (    pProxyDev->fMaskedIfs
     755            ||  !usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_RESET, NULL, false, 10))
     756        {
     757            /* Connect drivers. */
     758            unsigned iIf;
     759            for (iIf = 0; iIf < 256; iIf++)
     760                usbProxyLinuxSetConnected(pProxyDev, iIf, true, true);
     761            LogRel(("USB: Successfully reset device pProxyDev=%s\n", usbProxyGetName(pProxyDev)));
     762        }
     763        else if (errno != ENODEV)
     764            LogRel(("USB: Reset failed, errno=%d, pProxyDev=%s.\n", errno, usbProxyGetName(pProxyDev)));
     765        else
     766            Log(("USB: Reset failed, errno=%d (ENODEV), pProxyDev=%s.\n", errno, usbProxyGetName(pProxyDev)));
     767    }
     768
     769    /*
     770     * Now we can free all the resources and close the device.
     771     */
    646772    RTCritSectDelete(&pDevLnx->CritSect);
    647773
     
    679805        RTMemFree(pUrbLnx);
    680806    }
     807
     808    RTFileClose(pDevLnx->File);
     809    pDevLnx->File = NIL_RTFILE;
    681810
    682811    RTMemFree(pDevLnx);
     
    808937                /* Skip past "S:" and then the whitespace */
    809938                for(psz = buf + 2; *psz != '\0'; psz++)
    810                     if ( !isspace(*psz) )
     939                    if ( !RT_C_IS_SPACE(*psz) )
    811940                        break;
    812941
     
    8781007 * @param   pDev    The device to reset.
    8791008 */
    880 static int usbProxyLinuxReset(PUSBPROXYDEV pProxyDev)
     1009static int usbProxyLinuxReset(PUSBPROXYDEV pProxyDev, bool fResetOnLinux)
    8811010{
    8821011#ifdef NO_PORT_RESET
    883     LogFlow(("usbProxyLinuxReset: pProxyDev=%p[%s] - NO_PORT_RESET\n", pProxyDev, pProxyDev->Dev.pszName));
     1012    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
     1013
     1014    /*
     1015     * Specific device resets are NOPs.
     1016     * Root hub resets that affects all devices are executed.
     1017     *
     1018     * The reasoning is that when a root hub reset is done, the guest shouldn't
     1019     * will have to re enumerate the devices after doing this kind of reset.
     1020     * So, it doesn't really matter if a device is 'logically disconnected'.
     1021     */
     1022    if (    !fResetOnLinux
     1023        ||  pProxyDev->fMaskedIfs)
     1024        LogFlow(("usbProxyLinuxReset: pProxyDev=%s - NO_PORT_RESET\n", usbProxyGetName(pProxyDev)));
     1025    else
     1026    {
     1027        LogFlow(("usbProxyLinuxReset: pProxyDev=%s - Real Reset!\n", usbProxyGetName(pProxyDev)));
     1028        if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_RESET, NULL, false, 10))
     1029        {
     1030            int rc = errno;
     1031            Log(("usb-linux: Reset failed, rc=%Rrc errno=%d.\n", RTErrConvertFromErrno(rc), rc));
     1032            pProxyDev->iActiveCfg = -1;
     1033            return RTErrConvertFromErrno(rc);
     1034        }
     1035
     1036        /* find the active config - damn annoying. */
     1037        pProxyDev->iActiveCfg = usbProxyLinuxFindActiveConfig(pProxyDev, pDevLnx->szPath, NULL);
     1038        LogFlow(("usbProxyLinuxReset: returns successfully iActiveCfg=%d\n", pProxyDev->iActiveCfg));
     1039    }
    8841040    pProxyDev->cIgnoreSetConfigs = 2;
    8851041
    8861042#else /* !NO_PORT_RESET */
    887     LogFlow(("usbProxyLinuxReset: pProxyDev=%p[%s]\n", pProxyDev, pProxyDev->Dev.pszName));
     1043
     1044    /*
     1045     * This is the alternative, we will allways reset when asked to do so.
     1046     *
     1047     * The problem we're facing here is that on reset failure linux will do
     1048     * a 'logical reconnect' on the device. This will invalidate the current
     1049     * handle and we'll have to reopen the device. This is problematic to say
     1050     * the least, especially since it happens pretty often.
     1051     */
     1052    LogFlow(("usbProxyLinuxReset: pProxyDev=%s\n", usbProxyGetName(pProxyDev)));
    8881053# ifndef NO_LOGICAL_RECONNECT
    8891054    ASMAtomicIncU32(&g_cResetActive);
     
    9411106static int usbProxyLinuxSetConfig(PUSBPROXYDEV pProxyDev, int iCfg)
    9421107{
    943     LogFlow(("usbProxyLinuxSetConfig: pProxyDev=%p[%s] cfg=%#x\n",
    944              pProxyDev, pProxyDev->Dev.pszName, iCfg));
     1108    LogFlow(("usbProxyLinuxSetConfig: pProxyDev=%s cfg=%#x\n",
     1109             usbProxyGetName(pProxyDev), iCfg));
    9451110
    9461111    if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_SETCONFIGURATION, &iCfg, true, UINT32_MAX))
     
    9591124static int usbProxyLinuxClaimInterface(PUSBPROXYDEV pProxyDev, int iIf)
    9601125{
    961     LogFlow(("usbProxyLinuxClaimInterface: pProxyDev=%p[%s] ifnum=%#x\n", pProxyDev, pProxyDev->Dev.pszName, iIf));
     1126    LogFlow(("usbProxyLinuxClaimInterface: pProxyDev=%s ifnum=%#x\n", usbProxyGetName(pProxyDev), iIf));
    9621127    usbProxyLinuxSetConnected(pProxyDev, iIf, false, false);
    9631128
    9641129    if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_CLAIMINTERFACE, &iIf, true, UINT32_MAX))
    9651130    {
    966         Log(("usb-linux: Claim interface. errno=%d pProxyDev=%p[%s]\n", errno, pProxyDev, pProxyDev->Dev.pszName));
     1131        Log(("usb-linux: Claim interface. errno=%d pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev)));
    9671132        return false;
    9681133    }
     
    9771142static int usbProxyLinuxReleaseInterface(PUSBPROXYDEV pProxyDev, int iIf)
    9781143{
    979     LogFlow(("usbProxyLinuxReleaseInterface: pProxyDev=%p[%s] ifnum=%#x\n", pProxyDev, pProxyDev->Dev.pszName, iIf));
     1144    LogFlow(("usbProxyLinuxReleaseInterface: pProxyDev=%s ifnum=%#x\n", usbProxyGetName(pProxyDev), iIf));
    9801145
    9811146    if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_RELEASEINTERFACE, &iIf, true, UINT32_MAX))
    9821147    {
    983         Log(("usb-linux: Release interface, errno=%d. pProxyDev=%p[%s]\n", errno, pProxyDev, pProxyDev->Dev.pszName));
     1148        Log(("usb-linux: Release interface, errno=%d. pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev)));
    9841149        return false;
    9851150    }
     
    10021167    if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_SETINTERFACE, &SetIf, true, UINT32_MAX))
    10031168    {
    1004         Log(("usb-linux: Set interface, errno=%d. pProxyDev=%p[%s]\n", errno, pProxyDev, pProxyDev->Dev.pszName));
     1169        Log(("usb-linux: Set interface, errno=%d. pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev)));
    10051170        return false;
    10061171    }
     
    10141179static bool usbProxyLinuxClearHaltedEp(PUSBPROXYDEV pProxyDev, unsigned int EndPt)
    10151180{
    1016     LogFlow(("usbProxyLinuxClearHaltedEp: pProxyDev=%p[%s] EndPt=%u\n", pProxyDev, pProxyDev->Dev.pszName, EndPt));
     1181    LogFlow(("usbProxyLinuxClearHaltedEp: pProxyDev=%s EndPt=%u\n", usbProxyGetName(pProxyDev), EndPt));
    10171182
    10181183    if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_CLEAR_HALT, &EndPt, true, UINT32_MAX))
     
    10251190        if (errno == ENOENT)
    10261191        {
    1027             Log(("usb-linux: clear_halted_ep failed errno=%d. pProxyDev=%p[%s] ep=%d - IGNORED\n",
    1028                  errno, pProxyDev, pProxyDev->Dev.pszName, EndPt));
     1192            Log(("usb-linux: clear_halted_ep failed errno=%d. pProxyDev=%s ep=%d - IGNORED\n",
     1193                 errno, usbProxyGetName(pProxyDev), EndPt));
    10291194            return true;
    10301195        }
    1031         Log(("usb-linux: clear_halted_ep failed errno=%d. pProxyDev=%p[%s] ep=%d\n",
    1032              errno, pProxyDev, pProxyDev->Dev.pszName, EndPt));
     1196        Log(("usb-linux: clear_halted_ep failed errno=%d. pProxyDev=%s ep=%d\n",
     1197             errno, usbProxyGetName(pProxyDev), EndPt));
    10331198        return false;
    10341199    }
     
    10421207static void usbProxyLinuxUrbSwapSetup(PVUSBSETUP pSetup)
    10431208{
    1044     pSetup->wValue = RT_LE2H_U16(pSetup->wValue);
    1045     pSetup->wIndex = RT_LE2H_U16(pSetup->wIndex);
    1046     pSetup->wLength = RT_LE2H_U16(pSetup->wLength);
    1047 }
    1048 
    1049 
    1050 /** The split size. */
    1051 #define SPLIT_SIZE 0x2000
    1052 
    1053 /**
    1054  * Try split up a VUSB URB into smaller URBs which the
    1055  * linux kernel can deal with.
     1209    pSetup->wValue = RT_H2LE_U16(pSetup->wValue);
     1210    pSetup->wIndex = RT_H2LE_U16(pSetup->wIndex);
     1211    pSetup->wLength = RT_H2LE_U16(pSetup->wLength);
     1212}
     1213
     1214
     1215/**
     1216 * Clean up after a failed URB submit.
     1217 */
     1218static void usbProxyLinuxCleanupFailedSubmit(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pUrbLnx, PUSBPROXYURBLNX pCur, PVUSBURB pUrb, bool *pfUnplugged)
     1219{
     1220    if (pUrb->enmType == VUSBXFERTYPE_MSG)
     1221        usbProxyLinuxUrbSwapSetup((PVUSBSETUP)pUrb->abData);
     1222
     1223    /* discard and reap later (walking with pUrbLnx). */
     1224    if (pUrbLnx != pCur)
     1225    {
     1226        for (;;)
     1227        {
     1228            pUrbLnx->fCanceledBySubmit = true;
     1229            pUrbLnx->KUrb.usercontext = NULL;
     1230            if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_DISCARDURB, &pUrbLnx->KUrb, false, UINT32_MAX))
     1231            {
     1232                if (errno == ENODEV)
     1233                    *pfUnplugged = true;
     1234                else if (errno == ENOENT)
     1235                    pUrbLnx->fSplitElementReaped = true;
     1236                else
     1237                    LogRel(("USB: Failed to discard %p! errno=%d (pUrb=%p)\n", pUrbLnx->KUrb.usercontext, errno, pUrb)); /* serious! */
     1238            }
     1239            if (pUrbLnx->pSplitNext == pCur)
     1240            {
     1241                pUrbLnx->pSplitNext = NULL;
     1242                break;
     1243            }
     1244            pUrbLnx = pUrbLnx->pSplitNext; Assert(pUrbLnx);
     1245        }
     1246    }
     1247
     1248    /* free the unsubmitted ones. */
     1249    while (pCur)
     1250    {
     1251        PUSBPROXYURBLNX pFree = pCur;
     1252        pCur = pCur->pSplitNext;
     1253        usbProxyLinuxUrbFree(pProxyDev, pFree);
     1254    }
     1255
     1256    /* send unplug event if we failed with ENODEV originally. */
     1257    if (*pfUnplugged)
     1258        usbProxLinuxUrbUnplugged(pProxyDev);
     1259}
     1260
     1261/**
     1262 * Submit one URB through the usbfs IOCTL interface, with
     1263 * retries
     1264 *
     1265 * @returns true / false.
     1266 */
     1267static bool usbProxyLinuxSubmitURB(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pCur, PVUSBURB pUrb, bool *pfUnplugged)
     1268{
     1269    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
     1270    unsigned        cTries = 0;
     1271
     1272    while (ioctl(pDevLnx->File, USBDEVFS_SUBMITURB, &pCur->KUrb))
     1273    {
     1274        if (errno == EINTR)
     1275            continue;
     1276        if (errno == ENODEV)
     1277        {
     1278            Log(("usbProxyLinuxSubmitURB: ENODEV -> unplugged. pProxyDev=%s\n", usbProxyGetName(pProxyDev)));
     1279            *pfUnplugged = true;
     1280            return false;
     1281        }
     1282
     1283        Log(("usb-linux: Submit URB %p -> %d!!! type=%d ep=%#x buffer_length=%#x cTries=%d\n",
     1284             pUrb, errno, pCur->KUrb.type, pCur->KUrb.endpoint, pCur->KUrb.buffer_length, cTries));
     1285        if (errno != EBUSY && ++cTries < 3) /* this doesn't work for the floppy :/ */
     1286        {
     1287            pCur->u64SubmitTS = RTTimeMilliTS();
     1288            continue;
     1289        }
     1290        return false;
     1291    }
     1292    return true;
     1293}
     1294
     1295/** The split size. 16K in known Linux kernel versions. */
     1296#define SPLIT_SIZE 0x4000
     1297
     1298/**
     1299 * Create a URB fragment of up to SPLIT_SIZE size and hook it
     1300 * into the list of fragments.
     1301 *
     1302 * @returns pointer to newly allocated URB fragment or NULL.
     1303 */
     1304static PUSBPROXYURBLNX usbProxyLinuxSplitURBFragment(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pHead, PUSBPROXYURBLNX pCur)
     1305{
     1306    PUSBPROXYURBLNX     pNew;
     1307    uint32_t            cbLeft = pCur->cbSplitRemaining;
     1308    uint8_t             *pb = (uint8_t *)pCur->KUrb.buffer;
     1309
     1310    Assert(cbLeft != 0);
     1311    pNew = pCur->pSplitNext = usbProxyLinuxUrbAlloc(pProxyDev, pHead);
     1312    if (!pNew)
     1313    {
     1314        usbProxyLinuxUrbFreeSplitList(pProxyDev, pHead);
     1315        return NULL;
     1316    }
     1317    Assert(pHead->pNext != pNew); Assert(pHead->pPrev != pNew); Assert(pNew->pNext == pNew->pPrev);
     1318    Assert(pNew->pSplitHead == pHead);
     1319    Assert(pNew->pSplitNext == NULL);
     1320
     1321    pNew->KUrb = pHead->KUrb;
     1322    pNew->KUrb.buffer = pb + pCur->KUrb.buffer_length;
     1323    pNew->KUrb.buffer_length = RT_MIN(cbLeft, SPLIT_SIZE);
     1324    pNew->KUrb.actual_length = 0;
     1325
     1326    cbLeft -= pNew->KUrb.buffer_length;
     1327    Assert(cbLeft < INT32_MAX);
     1328    pNew->cbSplitRemaining = cbLeft;
     1329    return pNew;
     1330}
     1331
     1332/**
     1333 * Try splitting up a VUSB URB into smaller URBs which the
     1334 * linux kernel (usbfs) can deal with.
     1335 *
     1336 * NB: For ShortOK reads things get a little tricky - we don't
     1337 * know how much data is going to arrive and not all the
     1338 * fragment URBs might be filled. We can only safely set up one
     1339 * URB at a time -> worse performance but correct behaviour.
    10561340 *
    10571341 * @returns true / false.
     
    10621346static int usbProxyLinuxUrbQueueSplit(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pUrbLnx, PVUSBURB pUrb)
    10631347{
    1064     unsigned        cTries;
    1065     PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
    1066 
    10671348    /*
    10681349     * Split it up into SPLIT_SIZE sized blocks.
     
    10801361        case VUSBXFERTYPE_BULK: pUrbLnx->KUrb.type = USBDEVFS_URB_TYPE_BULK; break;
    10811362        case VUSBXFERTYPE_INTR: pUrbLnx->KUrb.type = USBDEVFS_URB_TYPE_INTERRUPT; break;
    1082         case VUSBXFERTYPE_ISOC: pUrbLnx->KUrb.type = USBDEVFS_URB_TYPE_ISO; break;
    10831363        case VUSBXFERTYPE_MSG:  pUrbLnx->KUrb.type = USBDEVFS_URB_TYPE_CONTROL; break;
     1364        case VUSBXFERTYPE_ISOC:
     1365            AssertMsgFailed(("We can't split isochronous URBs!\n"));
     1366            usbProxyLinuxUrbFree(pProxyDev, pUrbLnx);
     1367            return false;
    10841368    }
    10851369    pUrbLnx->KUrb.endpoint          = pUrb->EndPt;
     
    10891373    pUrbLnx->KUrb.flags             = pUrb->fShortNotOk ? USBDEVFS_URB_SHORT_NOT_OK : 0; /* ISO_ASAP too? */
    10901374    pUrbLnx->KUrb.buffer            = pb;
    1091     pUrbLnx->KUrb.buffer_length     = MIN(cbLeft, SPLIT_SIZE);
     1375    pUrbLnx->KUrb.buffer_length     = RT_MIN(cbLeft, SPLIT_SIZE);
    10921376    pUrbLnx->KUrb.actual_length     = 0;
    10931377    pUrbLnx->KUrb.start_frame       = 0;
     
    10991383    pUrbLnx->pSplitNext = NULL;
    11001384
    1101     pb += pUrbLnx->KUrb.buffer_length;
     1385    PUSBPROXYURBLNX pCur = pUrbLnx;
     1386
    11021387    cbLeft -= pUrbLnx->KUrb.buffer_length;
    1103 
    1104     /* the rest. */
    1105     unsigned i;
    1106     PUSBPROXYURBLNX pCur = pUrbLnx;
    1107     for (i = 1; i < cKUrbs; i++)
    1108     {
    1109         Assert(cbLeft != 0);
    1110         pCur = pCur->pSplitNext = usbProxyLinuxUrbAlloc(pProxyDev, pUrbLnx);
    1111         if (!pCur)
    1112         {
    1113             usbProxyLinuxUrbFreeSplitList(pProxyDev, pUrbLnx);
    1114             return false;
    1115         }
    1116         Assert(pUrbLnx->pNext != pCur); Assert(pUrbLnx->pPrev != pCur); Assert(pCur->pNext == pCur->pPrev);
    1117         Assert(pCur->pSplitHead == pUrbLnx);
    1118         Assert(pCur->pSplitNext == NULL);
    1119 
    1120         pCur->KUrb = pUrbLnx->KUrb;
    1121         pCur->KUrb.buffer = pb;
    1122         pCur->KUrb.buffer_length = MIN(cbLeft, SPLIT_SIZE);
    1123         pCur->KUrb.actual_length = 0;
    1124 
    1125         pb += pCur->KUrb.buffer_length;
    1126         cbLeft -= pCur->KUrb.buffer_length;
    1127     }
    1128     Assert(cbLeft == 0);
    1129 
    1130     /*
    1131      * Submit them.
    1132      */
     1388    pUrbLnx->cbSplitRemaining = cbLeft;
     1389
     1390    bool fSucceeded = false;
    11331391    bool fUnplugged = false;
    1134     bool fFailed = false;
    1135     pCur = pUrbLnx;
    1136     for (i = 0; i < cKUrbs; i++, pCur = pCur->pSplitNext)
    1137     {
    1138         cTries = 0;
    1139         while (ioctl(pDevLnx->File, USBDEVFS_SUBMITURB, &pCur->KUrb))
    1140         {
    1141             if (errno == EINTR)
    1142                 continue;
    1143             if (errno == ENODEV)
     1392    if (pUrb->enmDir == VUSBDIRECTION_IN && !pUrb->fShortNotOk)
     1393    {
     1394        /* Subsequent fragments will be queued only after the previous fragment is reaped
     1395         * and only if necessary.
     1396         */
     1397        fSucceeded = true;
     1398        Log(("usb-linux: Large ShortOK read, only queuing first fragment.\n"));
     1399        Assert(pUrbLnx->cbSplitRemaining > 0 && pUrbLnx->cbSplitRemaining < 256 * _1K);
     1400        fSucceeded = usbProxyLinuxSubmitURB(pProxyDev, pUrbLnx, pUrb, &fUnplugged);
     1401    }
     1402    else
     1403    {
     1404        /* the rest. */
     1405        unsigned i;
     1406        for (i = 1; i < cKUrbs; i++)
     1407        {
     1408            pCur = usbProxyLinuxSplitURBFragment(pProxyDev, pUrbLnx, pCur);
     1409            if (!pCur)
    11441410            {
    1145                 Log(("usbProxyLinuxUrbQueueSplit: ENODEV -> unplugged. pProxyDev=%p[%s]\n", pProxyDev, pProxyDev->Dev.pszName));
    1146                 fFailed = fUnplugged = true;
     1411                return false;
     1412            }
     1413        }
     1414        Assert(pCur->cbSplitRemaining == 0);
     1415
     1416        /* Submit the blocks. */
     1417        pCur = pUrbLnx;
     1418        for (i = 0; i < cKUrbs; i++, pCur = pCur->pSplitNext)
     1419        {
     1420            fSucceeded = usbProxyLinuxSubmitURB(pProxyDev, pCur, pUrb, &fUnplugged);
     1421            if (!fSucceeded)
    11471422                break;
    1148             }
    1149 
    1150             Log(("usb-linux: Queue URB %p -> %d!!! type=%d ep=%#x buffer_length=%#x cTries=%d\n",
    1151                  pUrb, errno, pCur->KUrb.type, pCur->KUrb.endpoint, pCur->KUrb.buffer_length, cTries));
    1152             if (errno != EBUSY && ++cTries < 3) /* this doesn't work for the floppy :/ */
    1153                 continue;
    1154             fFailed = true;
    1155             break;
    1156         }
    1157         if (fFailed)
    1158             break;
    1159         pCur->u64SubmitTS = RTTimeMilliTS();
    1160     }
    1161     if (!fFailed)
     1423        }
     1424    }
     1425
     1426    if (fSucceeded)
    11621427    {
    11631428        pUrb->Dev.pvPrivate = pUrbLnx;
     
    11661431    }
    11671432
    1168     /*
    1169      * Clean up.
    1170      */
    1171     if (pUrb->enmType == VUSBXFERTYPE_MSG)
    1172         usbProxyLinuxUrbSwapSetup((PVUSBSETUP)pUrb->abData);
    1173 
    1174     /* discard and reap later (walking with pUrbLnx). */
    1175     if (pUrbLnx != pCur)
    1176     {
    1177         for (;;)
    1178         {
    1179             pUrbLnx->fCanceledBySubmit = true;
    1180             pUrbLnx->KUrb.usercontext = NULL;
    1181             if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_DISCARDURB, &pUrbLnx->KUrb, false, UINT32_MAX))
    1182             {
    1183                 if (errno == ENODEV)
    1184                     fUnplugged = true;
    1185                 else if (errno == ENOENT)
    1186                     pUrbLnx->fSplitElementReaped = true;
    1187                 else
    1188                     LogRel(("SUB: Failed to discard %p! errno=%d (pUrb=%p)\n", pUrbLnx->KUrb.usercontext, errno, pUrb)); /* serious! */
    1189             }
    1190             if (pUrbLnx->pSplitNext == pCur)
    1191             {
    1192                 pUrbLnx->pSplitNext = NULL;
    1193                 break;
    1194             }
    1195             pUrbLnx = pUrbLnx->pSplitNext; Assert(pUrbLnx);
    1196         }
    1197     }
    1198 
    1199     /* free the unsubmitted ones. */
    1200     while (pCur)
    1201     {
    1202         PUSBPROXYURBLNX pFree = pCur;
    1203         pCur = pCur->pSplitNext;
    1204         usbProxyLinuxUrbFree(pProxyDev, pFree);
    1205     }
    1206 
    1207     /* send unplug event if we failed with ENODEV originally. */
    1208     if (fUnplugged)
    1209         usbProxLinuxUrbUnplugged(pProxyDev);
     1433    usbProxyLinuxCleanupFailedSubmit(pProxyDev, pUrbLnx, pCur, pUrb, &fUnplugged);
    12101434    return false;
    12111435}
     
    12131437
    12141438/**
    1215  * @copydoc USBPROXYBACK::pfbUrbQueue
     1439 * @copydoc USBPROXYBACK::pfnUrbQueue
    12161440 */
    12171441static int usbProxyLinuxUrbQueue(PVUSBURB pUrb)
    12181442{
    12191443    unsigned        cTries;
    1220     PUSBPROXYDEV    pProxyDev = (PUSBPROXYDEV)pUrb->pDev;
     1444#ifndef RDESKTOP
     1445    PUSBPROXYDEV    pProxyDev = PDMINS_2_DATA(pUrb->pUsbIns, PUSBPROXYDEV);
     1446#else
     1447    PUSBPROXYDEV    pProxyDev = usbProxyFromVusbDev(pUrb->pDev);
     1448#endif
    12211449    PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;
    1222     LogFlow(("usbProxyLinuxUrbQueue: pProxyDev=%p[%s] pUrb=%p EndPt=%d cbData=%d\n",
    1223              pProxyDev, pProxyDev->Dev.pszName, pUrb, pUrb->EndPt, pUrb->cbData));
     1450    LogFlow(("usbProxyLinuxUrbQueue: pProxyDev=%s pUrb=%p EndPt=%d cbData=%d\n",
     1451             usbProxyGetName(pProxyDev), pUrb, pUrb->EndPt, pUrb->cbData));
    12241452
    12251453    /*
     
    12291457    if (!pUrbLnx)
    12301458        return false;
     1459
     1460    pUrbLnx->KUrb.endpoint          = pUrb->EndPt | (pUrb->enmDir == VUSBDIRECTION_IN ? 0x80 : 0);
     1461    pUrbLnx->KUrb.status            = 0;
     1462    pUrbLnx->KUrb.flags             = pUrb->fShortNotOk ? USBDEVFS_URB_SHORT_NOT_OK : 0;
     1463    pUrbLnx->KUrb.buffer            = pUrb->abData;
     1464    pUrbLnx->KUrb.buffer_length     = pUrb->cbData;
     1465    pUrbLnx->KUrb.actual_length     = 0;
     1466    pUrbLnx->KUrb.start_frame       = 0;
     1467    pUrbLnx->KUrb.number_of_packets = 0;
     1468    pUrbLnx->KUrb.error_count       = 0;
     1469    pUrbLnx->KUrb.signr             = 0;
     1470    pUrbLnx->KUrb.usercontext       = pUrb;
    12311471
    12321472    switch (pUrb->enmType)
     
    12471487        case VUSBXFERTYPE_ISOC:
    12481488            pUrbLnx->KUrb.type = USBDEVFS_URB_TYPE_ISO;
     1489            pUrbLnx->KUrb.flags |= USBDEVFS_URB_ISO_ASAP;
     1490            pUrbLnx->KUrb.number_of_packets = pUrb->cIsocPkts;
     1491            unsigned i;
     1492            for (i = 0; i < pUrb->cIsocPkts; i++)
     1493            {
     1494                pUrbLnx->KUrb.iso_frame_desc[i].length = pUrb->aIsocPkts[i].cb;
     1495                pUrbLnx->KUrb.iso_frame_desc[i].actual_length = 0;
     1496                pUrbLnx->KUrb.iso_frame_desc[i].status = 0x7fff;
     1497            }
    12491498            break;
    12501499        case VUSBXFERTYPE_INTR:
     
    12541503            goto l_err;
    12551504    }
    1256     pUrbLnx->KUrb.endpoint          = pUrb->EndPt;
    1257     pUrbLnx->KUrb.status            = 0;
    1258     pUrbLnx->KUrb.flags             = pUrb->fShortNotOk ? USBDEVFS_URB_SHORT_NOT_OK : 0; /* ISO_ASAP too? */
    1259     pUrbLnx->KUrb.buffer            = pUrb->abData;
    1260     pUrbLnx->KUrb.buffer_length     = pUrb->cbData;
    1261     pUrbLnx->KUrb.actual_length     = 0;
    1262     pUrbLnx->KUrb.start_frame       = 0;
    1263     pUrbLnx->KUrb.number_of_packets = 0;
    1264     pUrbLnx->KUrb.error_count       = 0;
    1265     pUrbLnx->KUrb.signr             = 0;
    1266     pUrbLnx->KUrb.usercontext       = pUrb;
    1267     switch (pUrb->enmDir)
    1268     {
    1269         case VUSBDIRECTION_IN:
    1270             pUrbLnx->KUrb.endpoint |= 0x80;
    1271             break;
    1272         case VUSBDIRECTION_OUT:
    1273             break;
    1274         default:
    1275             AssertMsgFailed(("usbProxyLinuxUrbQueue: Invalid directorion %d\n", pUrb->enmDir));
    1276             goto l_err;
    1277     }
    12781505
    12791506    /*
     
    12871514        if (errno == ENODEV)
    12881515        {
    1289             Log(("usbProxyLinuxUrbQueue: ENODEV -> unplugged. pProxyDev=%p[%s]\n", pProxyDev, pProxyDev->Dev.pszName));
     1516            Log(("usbProxyLinuxUrbQueue: ENODEV -> unplugged. pProxyDev=%s\n", usbProxyGetName(pProxyDev)));
    12901517            if (pUrb->enmType == VUSBXFERTYPE_MSG)
    12911518                usbProxyLinuxUrbSwapSetup((PVUSBSETUP)pUrb->abData);
     
    13561583                Assert(pCur == pCur->pSplitHead);
    13571584                unsigned cFailures = 0;
    1358                 PUSBPROXYURBLNX pCur2;
    1359                 for ( pCur2 = pCur; pCur2; pCur2 = pCur2->pSplitNext)
     1585                PUSBPROXYURBLNX pCur2;
     1586                for (pCur2 = pCur; pCur2; pCur2 = pCur2->pSplitNext)
    13601587                {
    13611588                    if (pCur2->fSplitElementReaped)
     
    13701597                        goto l_leave; /* ENODEV means break and everything cancelled elsewhere. */
    13711598                }
    1372                 LogRel(("USB: Cancelled URB (%p) after %lldms!! (cFailures=%d)\n",
    1373                         pCur->KUrb.usercontext, u64MilliTS - pCur->u64SubmitTS, cFailures));
     1599                LogRel(("USB: Cancelled URB (%p) after %llums!! (cFailures=%d)\n",
     1600                        pCur->KUrb.usercontext, (long long unsigned) u64MilliTS - pCur->u64SubmitTS, cFailures));
    13741601            }
    13751602            else
     
    13801607                {
    13811608                    pCur->fCanceledByTimedOut = true;
    1382                     LogRel(("USB: Cancelled URB (%p) after %lldms!!\n", pCur->KUrb.usercontext, u64MilliTS - pCur->u64SubmitTS));
     1609                    LogRel(("USB: Cancelled URB (%p) after %llums!!\n", pCur->KUrb.usercontext, (long long unsigned) u64MilliTS - pCur->u64SubmitTS));
    13831610                }
    13841611                else if (errno != ENODEV)
     
    13881615            }
    13891616        }
     1617#if 0
     1618        /* Disabled for the time beeing as some USB devices have URBs pending for an unknown amount of time.
     1619         * One example is the OmniKey CardMan 3821. */
    13901620        else if (u64MilliTS - pCur->u64SubmitTS >= 200*1000 /* 200 sec (180 sec has been observed with XP) */)
    13911621            pCur->fTimedOut = true;
     1622#endif
    13921623    }
    13931624
     
    13981629
    13991630/**
    1400  * Get and translates the linux status to a VUSB status.
    1401  */
    1402 static VUSBSTATUS vusbProxyLinuxUrbGetStatus(PUSBPROXYURBLNX pUrbLnx)
    1403 {
    1404     switch (pUrbLnx->KUrb.status)
    1405     {
     1631 * Translate the linux status to a VUSB status.
     1632 *
     1633 * @remarks see cc_to_error in ohci.h, uhci_map_status in uhci-q.c,
     1634 *          sitd_complete+itd_complete in ehci-sched.c, and qtd_copy_status in
     1635 *          ehci-q.c.
     1636 */
     1637static VUSBSTATUS vusbProxyLinuxStatusToVUsbStatus(int iStatus)
     1638{
     1639    switch (iStatus)
     1640    {
     1641        /** @todo VUSBSTATUS_NOT_ACCESSED */
     1642        case -EXDEV: /* iso transfer, partial result. */
    14061643        case 0:
    1407             if (!pUrbLnx->fCanceledByTimedOut)
    1408                 return VUSBSTATUS_OK;
    1409             /* fall thru */
     1644            return VUSBSTATUS_OK;
    14101645
    14111646        case -EILSEQ:
     
    14131648
    14141649        case -EREMOTEIO: /* ehci and ohci uses this for underflow error. */
    1415             return VUSBSTATUS_UNDERFLOW;
    1416 
     1650            return VUSBSTATUS_DATA_UNDERRUN;
     1651        case -EOVERFLOW:
     1652            return VUSBSTATUS_DATA_OVERRUN;
     1653
     1654        case -ETIME:
    14171655        case -ENODEV:
    14181656            return VUSBSTATUS_DNR;
     
    14261664        //    return VUSBSTATUS_BIT_STUFFING;
    14271665
     1666        case -EPIPE:
     1667            Log(("vusbProxyLinuxStatusToVUsbStatus: STALL/EPIPE!!\n"));
     1668            return VUSBSTATUS_STALL;
     1669
     1670        case -ESHUTDOWN:
     1671            Log(("vusbProxyLinuxStatusToVUsbStatus: SHUTDOWN!!\n"));
     1672            return VUSBSTATUS_STALL;
     1673
    14281674        default:
    1429             Log(("usbProxyLinuxUrbReap: pKUrb status %d!!\n", pUrbLnx->KUrb.status));
     1675            Log(("vusbProxyLinuxStatusToVUsbStatus: status %d!!\n", iStatus));
    14301676            return VUSBSTATUS_STALL;
    14311677    }
     1678}
     1679
     1680
     1681/**
     1682 * Get and translates the linux status to a VUSB status.
     1683 */
     1684static VUSBSTATUS vusbProxyLinuxUrbGetStatus(PUSBPROXYURBLNX pUrbLnx)
     1685{
     1686    if (    pUrbLnx->fCanceledByTimedOut
     1687        &&  pUrbLnx->KUrb.status == 0)
     1688        return VUSBSTATUS_CRC;
     1689    return vusbProxyLinuxStatusToVUsbStatus(pUrbLnx->KUrb.status);
    14321690}
    14331691
     
    14411699 * @param   cMillies    Number of milliseconds to wait. Use 0 to not wait at all.
    14421700 */
    1443 static PVUSBURB usbProxyLinuxUrbReap(PUSBPROXYDEV pProxyDev, unsigned cMillies)
     1701static PVUSBURB usbProxyLinuxUrbReap(PUSBPROXYDEV pProxyDev, RTMSINTERVAL cMillies)
    14441702{
    14451703    PUSBPROXYURBLNX pUrbLnx = NULL;
     
    15111769                if (errno != EAGAIN)
    15121770                {
    1513                     Log(("usb-linux: Reap URB - poll -> %d errno=%d pProxyDev=%p[%s]\n", rc, errno, pProxyDev, pProxyDev->Dev.pszName));
     1771                    Log(("usb-linux: Reap URB - poll -> %d errno=%d pProxyDev=%s\n", rc, errno, usbProxyGetName(pProxyDev)));
    15141772                    return NULL;
    15151773                }
     
    15321790                        vusbProxyLinuxUrbDoTimeouts(pProxyDev, pDevLnx);
    15331791                    else
    1534                         Log(("usb-linux: Reap URB. errno=%d pProxyDev=%p[%s]\n", errno, pProxyDev, pProxyDev->Dev.pszName));
     1792                        Log(("usb-linux: Reap URB. errno=%d pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev)));
    15351793                    return NULL;
    15361794                }
     
    15411799            {
    15421800                pUrbLnx->fSplitElementReaped = true;
    1543                 PUSBPROXYURBLNX pCur;
     1801
     1802                /* for variable size URBs, we may need to queue more if the just-reaped URB was completely filled */
     1803                if (pUrbLnx->cbSplitRemaining && (pKUrb->actual_length == pKUrb->buffer_length) && !pUrbLnx->pSplitNext)
     1804                {
     1805                    bool fUnplugged = false;
     1806                    bool fSucceeded;
     1807
     1808                    Assert(pUrbLnx->pSplitHead);
     1809                    Assert((pKUrb->endpoint & 0x80) && (!pKUrb->flags & USBDEVFS_URB_SHORT_NOT_OK));
     1810                    PUSBPROXYURBLNX pNew = usbProxyLinuxSplitURBFragment(pProxyDev, pUrbLnx->pSplitHead, pUrbLnx);
     1811                    if (!pNew)
     1812                    {
     1813                        Log(("usb-linux: Allocating URB fragment failed. errno=%d pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev)));
     1814                        return NULL;
     1815                    }
     1816                    PVUSBURB pUrb = (PVUSBURB)pUrbLnx->KUrb.usercontext;
     1817                    fSucceeded = usbProxyLinuxSubmitURB(pProxyDev, pNew, pUrb, &fUnplugged);
     1818                    if (fUnplugged)
     1819                        usbProxLinuxUrbUnplugged(pProxyDev);
     1820                    if (!fSucceeded)
     1821                        return NULL;
     1822                    continue;   /* try reaping another URB */
     1823                }
     1824                PUSBPROXYURBLNX pCur;
    15441825                for (pCur = pUrbLnx->pSplitHead; pCur; pCur = pCur->pSplitNext)
    15451826                    if (!pCur->fSplitElementReaped)
     
    15691850            uint8_t *pbEnd = &pUrb->abData[0];
    15701851            pUrb->enmStatus = VUSBSTATUS_OK;
    1571             PUSBPROXYURBLNX pCur;
     1852            PUSBPROXYURBLNX pCur;
    15721853            for (pCur = pUrbLnx; pCur; pCur = pCur->pSplitNext)
    15731854            {
     
    15851866            pUrb->enmStatus = vusbProxyLinuxUrbGetStatus(pUrbLnx);
    15861867            pUrb->cbData = pUrbLnx->KUrb.actual_length;
     1868            if (pUrb->enmType == VUSBXFERTYPE_ISOC)
     1869            {
     1870                unsigned i, off;
     1871                for (i = 0, off = 0; i < pUrb->cIsocPkts; i++)
     1872                {
     1873                    pUrb->aIsocPkts[i].enmStatus = vusbProxyLinuxStatusToVUsbStatus(pUrbLnx->KUrb.iso_frame_desc[i].status);
     1874                    Assert(pUrb->aIsocPkts[i].off == off);
     1875                    pUrb->aIsocPkts[i].cb = pUrbLnx->KUrb.iso_frame_desc[i].actual_length;
     1876                    off += pUrbLnx->KUrb.iso_frame_desc[i].length;
     1877                }
     1878            }
    15871879            usbProxyLinuxUrbFree(pProxyDev, pUrbLnx);
    15881880        }
     
    16021894    }
    16031895
    1604     LogFlow(("usbProxyLinuxUrbReap: dev=%p[%s] returns %p\n", pProxyDev, pProxyDev->Dev.pszName, pUrb));
     1896    LogFlow(("usbProxyLinuxUrbReap: pProxyDev=%s returns %p\n", usbProxyGetName(pProxyDev), pUrb));
    16051897    return pUrb;
    16061898}
     
    16131905static void usbProxyLinuxUrbCancel(PVUSBURB pUrb)
    16141906{
    1615     PUSBPROXYDEV pProxyDev = (PUSBPROXYDEV)pUrb->pDev;
     1907#ifndef RDESKTOP
     1908    PUSBPROXYDEV pProxyDev = PDMINS_2_DATA(pUrb->pUsbIns, PUSBPROXYDEV);
     1909#else
     1910    PUSBPROXYDEV pProxyDev = usbProxyFromVusbDev(pUrb->pDev);
     1911#endif
    16161912    PUSBPROXYURBLNX pUrbLnx = (PUSBPROXYURBLNX)pUrb->Dev.pvPrivate;
    16171913    if (pUrbLnx->pSplitHead)
     
    16191915        /* split */
    16201916        Assert(pUrbLnx == pUrbLnx->pSplitHead);
    1621         PUSBPROXYURBLNX pCur;
     1917        PUSBPROXYURBLNX pCur;
    16221918        for (pCur = pUrbLnx; pCur; pCur = pCur->pSplitNext)
    16231919        {
     
    16291925            if (errno == ENODEV)
    16301926                break;
    1631             Log(("usb-linux: Discard URB %p failed, errno=%d. pProxyDev=%p[%s]!!! (split)\n",
    1632                  pUrb, errno, pProxyDev, pProxyDev->Dev.pszName));
     1927            Log(("usb-linux: Discard URB %p failed, errno=%d. pProxyDev=%s!!! (split)\n",
     1928                 pUrb, errno, usbProxyGetName(pProxyDev)));
    16331929        }
    16341930    }
     
    16391935            &&  errno != ENODEV /* deal with elsewhere. */
    16401936            &&  errno != ENOENT)
    1641             Log(("usb-linux: Discard URB %p failed, errno=%d. pProxyDev=%p[%s]!!!\n",
    1642                  pUrb, errno, pProxyDev, pProxyDev->Dev.pszName));
     1937            Log(("usb-linux: Discard URB %p failed, errno=%d. pProxyDev=%s!!!\n",
     1938                 pUrb, errno, usbProxyGetName(pProxyDev)));
    16431939    }
    16441940}
     
    16481944 * The Linux USB Proxy Backend.
    16491945 */
    1650 #ifdef __cplusplus
    1651 extern
    1652 #endif
    16531946const USBPROXYBACK g_USBProxyDeviceHost =
    16541947{
    16551948    "host",
    16561949    usbProxyLinuxOpen,
     1950    usbProxyLinuxInit,
    16571951    usbProxyLinuxClose,
    16581952    usbProxyLinuxReset,
  • trunk/src/VBox/RDP/client/vrdp/rdpusb.c

    r28800 r31247  
    2424#include <fcntl.h>
    2525
     26#include "runtime.h"
    2627#include "vrdpusb.h"
     28#include "USBProxyDevice.h"
    2729
    2830#define RDPUSB_REQ_OPEN              (0)
     
    6466#pragma pack ()
    6567
     68static inline int op_usbproxy_back_open(PUSBPROXYDEV p, const char *pszAddress)
     69{
     70     return g_USBProxyDeviceHost.pfnOpen (p, pszAddress, NULL);
     71}
     72
     73static inline void op_usbproxy_back_close(PUSBPROXYDEV pDev)
     74{
     75     return g_USBProxyDeviceHost.pfnClose (pDev);
     76}
     77
     78static inline int op_usbproxy_back_reset(PUSBPROXYDEV pDev)
     79{
     80    return g_USBProxyDeviceHost.pfnReset (pDev, false);
     81}
     82
     83static inline int op_usbproxy_back_set_config(PUSBPROXYDEV pDev, int cfg)
     84{
     85    return g_USBProxyDeviceHost.pfnSetConfig (pDev, cfg);
     86}
     87
     88static inline int op_usbproxy_back_claim_interface(PUSBPROXYDEV pDev, int ifnum)
     89{
     90    return g_USBProxyDeviceHost.pfnClaimInterface (pDev, ifnum);
     91}
     92
     93static inline int op_usbproxy_back_release_interface(PUSBPROXYDEV pDev, int ifnum)
     94{
     95    return g_USBProxyDeviceHost.pfnReleaseInterface (pDev, ifnum);
     96}
     97
     98static inline int op_usbproxy_back_interface_setting(PUSBPROXYDEV pDev, int ifnum, int setting)
     99{
     100    return g_USBProxyDeviceHost.pfnSetInterface (pDev, ifnum, setting);
     101}
     102
     103static inline int op_usbproxy_back_queue_urb(PVUSBURB pUrb)
     104{
     105    return g_USBProxyDeviceHost.pfnUrbQueue(pUrb);
     106}
     107
     108static inline PVUSBURB op_usbproxy_back_reap_urb(PUSBPROXYDEV pDev, unsigned cMillies)
     109{
     110    return g_USBProxyDeviceHost.pfnUrbReap (pDev, cMillies);
     111}
     112
     113static inline bool op_usbproxy_back_clear_halted_ep(PUSBPROXYDEV pDev, unsigned EndPoint)
     114{
     115    return g_USBProxyDeviceHost.pfnClearHaltedEndpoint (pDev, EndPoint);
     116}
     117
     118static inline void op_usbproxy_back_cancel_urb(PVUSBURB pUrb)
     119{
     120    return g_USBProxyDeviceHost.pfnUrbCancel (pUrb);
     121}
     122
    66123static uint16 getBcd (const char *str, const char *prefix)
    67124{
     
    405462vrdp_usb_status (int rc, VUSBDEV *pdev)
    406463{
    407         if (!rc || pdev->request_detach)
     464        if (!rc || usbProxyFromVusbDev(pdev)->fDetached)
    408465        {
    409466                return VRDP_USB_STATUS_DEVICE_REMOVED;
     
    413470}
    414471
    415 static struct usb_proxy *g_proxies = NULL;
    416 
    417 static struct usb_proxy *
     472static PUSBPROXYDEV g_proxies = NULL;
     473
     474static PUSBPROXYDEV
    418475devid2proxy (uint32_t devid)
    419476{
    420         struct usb_proxy *proxy = g_proxies;
     477        PUSBPROXYDEV proxy = g_proxies;
    421478
    422479        while (proxy && proxy->devid != devid)
    423480        {
    424                 proxy = proxy->next;
     481                proxy = proxy->pNext;
    425482        }
    426483
     
    435492        PVUSBURB pUrb = NULL;
    436493
    437         struct usb_proxy *proxy = g_proxies;
     494        PUSBPROXYDEV proxy = g_proxies;
    438495
    439496        while (proxy)
     
    467524                        rdpusb_send(s);
    468525
    469                         if (pUrb->prev || pUrb->next || pUrb == proxy->urbs)
     526                        if (pUrb->pPrev || pUrb->pNext || pUrb == proxy->pUrbs)
    470527                        {
    471528                                /* Remove the URB from list. */
    472                                 if (pUrb->prev)
    473                                 {
    474                                         pUrb->prev->next = pUrb->next;
     529                                if (pUrb->pPrev)
     530                                {
     531                                        pUrb->pPrev->pNext = pUrb->pNext;
    475532                                }
    476533                                else
    477534                                {
    478                                         proxy->urbs = pUrb->next;
     535                                        proxy->pUrbs = pUrb->pNext;
    479536                                }
    480537
    481                                 if (pUrb->next)
    482                                 {
    483                                         pUrb->next->prev = pUrb->prev;
     538                                if (pUrb->pNext)
     539                                {
     540                                        pUrb->pNext->pPrev = pUrb->pPrev;
    484541                                }
    485542                        }
     
    494551                }
    495552
    496                 proxy = proxy->next;
     553                proxy = proxy->pNext;
    497554        }
    498555
     
    509566        uint32 devid;
    510567
    511         struct usb_proxy *proxy = NULL;
     568        PUSBPROXYDEV proxy = NULL;
    512569
    513570#ifdef RDPUSB_DEBUG
     
    535592                        in_uint32_le(s, devid);
    536593
    537                         proxy = (struct usb_proxy *)xmalloc (sizeof (struct usb_proxy));
    538 
    539                         memset (proxy, 0, sizeof (struct usb_proxy));
     594                        proxy = (PUSBPROXYDEV )xmalloc (sizeof (USBPROXYDEV));
     595
     596                        memset (proxy, 0, sizeof (USBPROXYDEV));
    540597
    541598                        proxy->Dev.pszName = "Remote device";
     
    556613                                if (g_proxies)
    557614                                {
    558                                         g_proxies->prev = proxy;
     615                                        g_proxies->pPrev = proxy;
    559616                                }
    560617
    561                                 proxy->next = g_proxies;
     618                                proxy->pNext = g_proxies;
    562619                                g_proxies = proxy;
    563620                        }
     
    573630                                op_usbproxy_back_close(proxy);
    574631
    575                                 if (proxy->prev)
    576                                 {
    577                                         proxy->prev->next = proxy->next;
     632                                if (proxy->pPrev)
     633                                {
     634                                        proxy->pPrev->pNext = proxy->pNext;
    578635                                }
    579636                                else
    580637                                {
    581                                         g_proxies = proxy->next;
     638                                        g_proxies = proxy->pNext;
    582639                                }
    583640
    584                                 if (proxy->next)
    585                                 {
    586                                         proxy->next->prev = proxy->prev;
     641                                if (proxy->pNext)
     642                                {
     643                                        proxy->pNext->pPrev = proxy->pPrev;
    587644                                }
    588645
     
    760817                        if (rc)
    761818                        {
    762                                 if (proxy->urbs)
    763                                 {
    764                                         proxy->urbs->prev = pUrb;
     819                                if (proxy->pUrbs)
     820                                {
     821                                        proxy->pUrbs->pPrev = pUrb;
    765822                                }
    766823
    767                                 pUrb->next = proxy->urbs;
    768                                 proxy->urbs = pUrb;
     824                                pUrb->pNext = proxy->pUrbs;
     825                                proxy->pUrbs = pUrb;
    769826                        }
    770827                        else
     
    818875                        in_uint32_le(s, handle);
    819876
    820                         pUrb = proxy->urbs;
     877                        pUrb = proxy->pUrbs;
    821878
    822879                        while (pUrb && pUrb->handle != handle)
    823880                        {
    824                                 pUrb = pUrb->next;
     881                                pUrb = pUrb->pNext;
    825882                        }
    826883
     
    832889
    833890                                /* Remove URB from list. */
    834                                 if (pUrb->prev)
    835                                 {
    836                                         pUrb->prev->next = pUrb->next;
     891                                if (pUrb->pPrev)
     892                                {
     893                                        pUrb->pPrev->pNext = pUrb->pNext;
    837894                                }
    838895                                else
    839896                                {
    840                                         proxy->urbs = pUrb->next;
     897                                        proxy->pUrbs = pUrb->pNext;
    841898                                }
    842899
    843                                 if (pUrb->next)
    844                                 {
    845                                         pUrb->next->prev = pUrb->prev;
     900                                if (pUrb->pNext)
     901                                {
     902                                        pUrb->pNext->pPrev = pUrb->pPrev;
    846903                                }
    847904
    848                                 pUrb->next = pUrb->prev = NULL;
     905                                pUrb->pNext = pUrb->pPrev = NULL;
    849906
    850907                                Log(("Cancelled URB %p\n", pUrb));
     
    896953rdpusb_add_fds(int *n, fd_set * rfds, fd_set * wfds)
    897954{
    898         struct usb_proxy *proxy = g_proxies;
     955        PUSBPROXYDEV proxy = g_proxies;
    899956
    900957//      Log(("RDPUSB: rdpusb_add_fds: begin *n = %d\n", *n));
     
    902959        while (proxy)
    903960        {
    904                 int fd = dev2fd(proxy);
     961                int fd = USBProxyDeviceLinuxGetFD(proxy);
    905962
    906963                if (fd != -1)
     
    913970                }
    914971
    915                 proxy = proxy->next;
     972                proxy = proxy->pNext;
    916973        }
    917974
     
    924981rdpusb_check_fds(fd_set * rfds, fd_set * wfds)
    925982{
    926         (void)rfds;
    927         (void)wfds;
     983        PUSBPROXYDEV proxy = g_proxies;
     984        unsigned found = 0;
     985
     986        while (proxy)
     987        {
     988                int fd = USBProxyDeviceLinuxGetFD(proxy);
     989
     990                if (fd != -1)
     991                {
     992                        if (FD_ISSET(fd, rfds))
     993                found = 1;
     994                        if (FD_ISSET(fd, wfds))
     995                found = 1;
     996                }
     997
     998                proxy = proxy->pNext;
     999        }
    9281000
    9291001//      Log(("RDPUSB: rdpusb_check_fds: begin\n"));
    9301002
    931         rdpusb_reap_urbs ();
     1003        if (found)
     1004        rdpusb_reap_urbs ();
    9321005
    9331006//      Log(("RDPUSB: rdpusb_check_fds: end\n"));
     
    9481021rdpusb_close (void)
    9491022{
    950         struct usb_proxy *proxy = g_proxies;
     1023        PUSBPROXYDEV proxy = g_proxies;
    9511024
    9521025        while (proxy)
    9531026        {
    954                 struct usb_proxy *next = proxy->next;
     1027                PUSBPROXYDEV pNext = proxy->pNext;
    9551028
    9561029                Log(("RDPUSB: closing proxy %p\n", proxy));
     
    9591032                xfree (proxy);
    9601033
    961                 proxy = next;
     1034                proxy = pNext;
    9621035        }
    9631036
  • trunk/src/VBox/RDP/client/vrdp/runtime.h

    r30591 r31247  
    1515 */
    1616
    17 #ifndef __VRDPUSB__H
    18 #define __VRDPUSB__H
     17#ifndef __RUNTIME__H
     18#define __RUNTIME__H
    1919
    2020#include <endian.h>
    2121#include <byteswap.h>
     22#include <stdint.h>
     23#include <ctype.h>
     24#include <errno.h>
    2225
    2326#ifndef cpu_to_le16
     
    3437//#define cpu_to_le16 __cpu_to_le16
    3538
     39#if 0
    3640#define uint8_t uint8
    3741#define uint16_t uint16
    3842#define uint32_t uint32
    3943#define uint64_t long long
     44#endif
    4045#define bool int
    4146#define false 0
     
    4348
    4449#define OPSTATIC
     50#define RDPUSB_DEBUG
    4551#ifdef RDPUSB_DEBUG
    46 #define LogFlow(a) printf a
    47 #define Log(a) printf a
    48 #define Log2(a) printf a
     52#define DoLog(a) do { \
     53        printf("Time %llu: ", RTTimeMilliTS()); \
     54        printf a; \
     55} while(0)
     56
     57#define LogFlow(a) DoLog(a)
     58#define Log(a) DoLog(a)
     59#define Log2(a) DoLog(a)
    4960#else
    5061#define LogFlow(a) do {} while (0)
     
    6273#define _1K 1024
    6374
    64 #define RT_LE2H_U16(_le16) (cpu_to_le16 (_le16))
     75#ifdef RT_BIG_ENDIAN
     76# define RT_H2LE_U16(u16)   RT_BSWAP_U16(u16)
     77# define RT_LE2H_U16(u16)   RT_BSWAP_U16(u16)
     78#else
     79# define RT_H2LE_U16(u16)   (u16)
     80# define RT_LE2H_U16(u16)   (u16)
     81#endif
     82#define RT_BSWAP_U16(u16) RT_MAKE_U16(RT_HIBYTE(u16), RT_LOBYTE(u16))
     83#define RT_MAKE_U16(Lo, Hi) \
     84    ((uint16_t)(  (uint16_t)((uint8_t)(Hi)) << 8 \
     85                | (uint8_t)(Lo) ))
     86#define RT_LOBYTE(a)                            ( (a) & 0xff )
     87#define RT_HIBYTE(a)                            ( (a) >> 8 )
    6588
    6689#define VINF_SUCCESS 0
    67 #define VERR_NO_MEMORY     (-8)
    68 #define VERR_NOT_SUPPORTED (-37)
    69 #define VERR_ACCESS_DENIED (-38)
     90#define VERR_NO_MEMORY        (-8)
     91#define VERR_UNRESOLVED_ERROR (-35)
     92#define VERR_NOT_SUPPORTED    (-37)
     93#define VERR_ACCESS_DENIED    (-38)
    7094#define VERR_VUSB_USBFS_PERMISSION (-2005)
     95
     96static inline int RTErrConvertFromErrno(int iErrno)
     97{
     98    return   iErrno == 0 ? VINF_SUCCESS
     99           : iErrno == ENOMEM ? VERR_NO_MEMORY
     100           : iErrno == ENODEV ? VERR_NOT_SUPPORTED
     101           : iErrno == ENOSYS ? VERR_NOT_SUPPORTED
     102           : iErrno == EPERM ? VERR_ACCESS_DENIED
     103           : iErrno == EACCES ? VERR_ACCESS_DENIED
     104           : VERR_UNRESOLVED_ERROR;
     105}
    71106
    72107#define RT_SUCCESS(_rc) ((_rc) >= 0)
     
    101136#define NOREF(_a) ((void)_a)
    102137
    103 static inline int RTCritSectInit (RTCRITSECT *pCritSect)
    104 {
    105     return VINF_SUCCESS;
    106 }
    107 
    108 static inline int RTCritSectDelete (RTCRITSECT *pCritSect)
    109 {
    110     return VINF_SUCCESS;
    111 }
    112 
    113 static inline int RTCritSectEnter (RTCRITSECT *pCritSect)
    114 {
    115     return VINF_SUCCESS;
    116 }
    117 
    118 static inline int RTCritSectLeave (RTCRITSECT *pCritSect)
    119 {
    120     return VINF_SUCCESS;
    121 }
    122 
    123 static inline void *RTMemDupEx (const void *pvSrc, size_t cbSrc, size_t cbExtra)
    124 {
    125     void *p = RTMemAlloc (cbSrc + cbExtra);
    126 
    127     if (p)
    128     {
    129          memcpy (p, pvSrc, cbSrc);
    130          memset ((char *)p + cbSrc, 0, cbExtra);
    131     }
    132 
    133     return p;
    134 }
    135 
    136 static inline void *RTMemAllocZ (size_t cb)
    137 {
    138     void *p = RTMemAlloc (cb);
    139 
    140     if (p)
    141     {
    142          memset (p, 0, cb);
    143     }
    144 
    145     return p;
    146 }
    147 
    148 static inline int RTStrToUInt32Ex (const char *pszValue, char **ppszNext, unsigned uBase, uint32_t *pu32)
    149 {
    150     *pu32 = strtoul (pszValue, ppszNext, uBase);
    151     return VINF_SUCCESS;
    152 }
    153 
    154 #define PRTSTREAM FILE *
    155 
    156 static inline int RTStrmOpen (const char *pszFileName, const char *pszMode, PRTSTREAM *ppStream)
    157 {
    158     *ppStream = fopen (pszFileName, pszMode);
    159 
    160     if (*ppStream)
    161     {
    162         return VINF_SUCCESS;
    163     }
    164 
    165     return VERR_NOT_SUPPORTED;
    166 }
    167 
    168 static inline int RTStrmClose (PRTSTREAM pStream)
    169 {
    170     fclose (pStream);
    171     return VINF_SUCCESS;
    172 }
    173 
    174 static inline int RTStrmGetLine (PRTSTREAM pStream, char *pszString, size_t cchString)
    175 {
    176     if (fgets (pszString, cchString, pStream))
    177     {
    178         return VINF_SUCCESS;
    179     }
    180 
    181     return VERR_NOT_SUPPORTED;
    182 }
    183 
    184 static inline char *RTStrStripL (const char *psz)
    185 {
    186     while (isspace (*psz))
    187         psz++;
    188     return (char *)psz;
    189 }
    190 
    191 #define NIL_RTFILE -1
    192 
    193 #define RTFILE_O_READWRITE 0x00000003
    194 #define RTFILE_O_OPEN      0x00000000
    195 #define RTFILE_O_DENY_NONE 0x00000000
    196 
    197 static inline int RTFileOpen (RTFILE *pFile, const char *pszFileName, unsigned fOpen)
    198 {
    199     Assert (fOpen == RTFILE_O_READWRITE);
    200 
    201     *pFile = open (pszFileName, O_RDWR, 00600);
    202 
    203     if (*pFile != -1)
    204     {
    205         return VINF_SUCCESS;
    206     }
    207 
    208     return VERR_ACCESS_DENIED;
    209 }
    210 
    211 static inline int RTFileClose (RTFILE file)
    212 {
    213     close (file);
    214     return VINF_SUCCESS;
    215 }
     138#define RT_C_DECLS_BEGIN
     139#define RT_C_DECLS_END
     140
     141#define RTCALL
     142#define DECLR3CALLBACKMEMBER(type, name, args)  type (RTCALL * name) args
     143#define DECLINLINE(type) static __inline__ type
     144#define DECLCALLBACK(type)      type RTCALL
     145#define DECLCALLBACKMEMBER(type, name)  type (RTCALL * name)
     146#define RTDECL(type)       RTCALL type
     147
     148#define RT_BIT(bit)                             ( 1U << (bit) )
     149#define RT_MAX(Value1, Value2)                  ( (Value1) >= (Value2) ? (Value1) : (Value2) )
     150#define RT_MIN(Value1, Value2)                  ( (Value1) <= (Value2) ? (Value1) : (Value2) )
     151typedef uint32_t            RTGCPHYS32;
     152typedef uint32_t            RTMSINTERVAL;
    216153
    217154static inline uint64_t RTTimeMilliTS (void)
     
    223160}
    224161
    225 #define VRDP_USB_STATUS_SUCCESS         0
    226 #define VRDP_USB_STATUS_ACCESS_DENIED   1
    227 #define VRDP_USB_STATUS_DEVICE_REMOVED  2
    228 
    229 #define VRDP_USB_REAP_FLAG_CONTINUED (0)
    230 #define VRDP_USB_REAP_FLAG_LAST      (1)
    231 
    232 #define VRDP_USB_CAPS_FLAG_ASYNC    (0)
    233 #define VRDP_USB_CAPS_FLAG_POLL     (1)
    234 
    235 #pragma pack(1)
    236 
    237 #include "vusb.h"
    238 
    239 typedef struct VUSBDEV
    240 {
    241         char* pszName;
    242         int request_detach;
    243 } VUSBDEV, *PVUSBDEV;
    244 
    245 typedef struct usb_proxy {
    246     /* Note: the backend code assumes that the dev member is the first in the structure. */
    247     VUSBDEV Dev;
    248     /* 'union' because backend accesses the file handle as priv.File. */
    249     union {
    250         void *pv;
    251         int File;
    252     } Backend;
    253 
    254     struct usb_proxy *next;
    255     struct usb_proxy *prev;
    256 
    257     uint32_t devid;
    258 
    259     PVUSBURB urbs;
    260 
    261     int iActiveCfg;
    262     int cIgnoreSetConfigs;
    263 } *PUSBPROXYDEV;
    264 
    265 typedef struct vusb_setup {
    266         uint8_t  bmRequestType;
    267         uint8_t  bRequest;
    268         uint16_t wValue;
    269         uint16_t wIndex;
    270         uint16_t wLength;
    271 } VUSBSETUP, *PVUSBSETUP;
    272 #pragma pack()
    273 
    274 
    275 static inline void vusbDevUnplugged(PVUSBDEV dev)
    276 {
    277         dev->request_detach = 1;
    278 }
    279 
    280 int dev2fd (PUSBPROXYDEV pProxyDev);
    281 
    282 
    283 typedef struct USBPROXYBACK
    284 {
    285     /** Name of the backend. */
    286     const char *pszName;
    287 
    288     int  (* pfnOpen)(PUSBPROXYDEV pProxyDev, const char *pszAddress, void *pvBackend);
    289     void (* pfnClose)(PUSBPROXYDEV pProxyDev);
    290     int  (* pfnReset)(PUSBPROXYDEV pProxyDev);
    291     int  (* pfnSetConfig)(PUSBPROXYDEV pProxyDev, int iCfg);
    292     int  (* pfnClaimInterface)(PUSBPROXYDEV pProxyDev, int iIf);
    293     int  (* pfnReleaseInterface)(PUSBPROXYDEV pProxyDev, int iIf);
    294     int  (* pfnSetInterface)(PUSBPROXYDEV pProxyDev, int iIf, int setting);
    295     bool (* pfnClearHaltedEndpoint)(PUSBPROXYDEV  pDev, unsigned int iEp);
    296     int  (* pfnUrbQueue)(PVUSBURB urb);
    297     void (* pfnUrbCancel)(PVUSBURB pUrb);
    298     PVUSBURB (* pfnUrbReap)(PUSBPROXYDEV pProxyDev, unsigned cMillies);
    299     uint32_t uDummy;
    300 } USBPROXYBACK;
    301 
    302 typedef USBPROXYBACK *PUSBPROXYBACK;
    303 
    304 extern const USBPROXYBACK g_USBProxyDeviceHost;
    305 
    306 static inline int op_usbproxy_back_open(struct usb_proxy *p, const char *pszAddress)
    307 {
    308      return g_USBProxyDeviceHost.pfnOpen (p, pszAddress, NULL);
    309 }
    310 
    311 static inline void op_usbproxy_back_close(PUSBPROXYDEV pDev)
    312 {
    313      return g_USBProxyDeviceHost.pfnClose (pDev);
    314 }
    315 
    316 static inline int op_usbproxy_back_reset(PUSBPROXYDEV pDev)
    317 {
    318     return g_USBProxyDeviceHost.pfnReset (pDev);
    319 }
    320 
    321 static inline int op_usbproxy_back_set_config(PUSBPROXYDEV pDev, int cfg)
    322 {
    323     return g_USBProxyDeviceHost.pfnSetConfig (pDev, cfg);
    324 }
    325 
    326 static inline int op_usbproxy_back_claim_interface(PUSBPROXYDEV pDev, int ifnum)
    327 {
    328     return g_USBProxyDeviceHost.pfnClaimInterface (pDev, ifnum);
    329 }
    330 
    331 static inline int op_usbproxy_back_release_interface(PUSBPROXYDEV pDev, int ifnum)
    332 {
    333     return g_USBProxyDeviceHost.pfnReleaseInterface (pDev, ifnum);
    334 }
    335 
    336 static inline int op_usbproxy_back_interface_setting(PUSBPROXYDEV pDev, int ifnum, int setting)
    337 {
    338     return g_USBProxyDeviceHost.pfnSetInterface (pDev, ifnum, setting);
    339 }
    340 
    341 static inline int op_usbproxy_back_queue_urb(PVUSBURB pUrb)
    342 {
    343     return g_USBProxyDeviceHost.pfnUrbQueue(pUrb);
    344 }
    345 
    346 static inline PVUSBURB op_usbproxy_back_reap_urb(PUSBPROXYDEV pDev, unsigned cMillies)
    347 {
    348     return g_USBProxyDeviceHost.pfnUrbReap (pDev, cMillies);
    349 }
    350 
    351 static inline bool op_usbproxy_back_clear_halted_ep(PUSBPROXYDEV pDev, unsigned EndPoint)
    352 {
    353     return g_USBProxyDeviceHost.pfnClearHaltedEndpoint (pDev, EndPoint);
    354 }
    355 
    356 static inline void op_usbproxy_back_cancel_urb(PVUSBURB pUrb)
    357 {
    358     return g_USBProxyDeviceHost.pfnUrbCancel (pUrb);
    359 }
    360 
    361 #endif /* __VRDPUSB__H  */
     162static inline int RTCritSectInit (RTCRITSECT *pCritSect)
     163{
     164    return VINF_SUCCESS;
     165}
     166
     167static inline int RTCritSectDelete (RTCRITSECT *pCritSect)
     168{
     169    return VINF_SUCCESS;
     170}
     171
     172static inline int RTCritSectEnter (RTCRITSECT *pCritSect)
     173{
     174    return VINF_SUCCESS;
     175}
     176
     177static inline int RTCritSectLeave (RTCRITSECT *pCritSect)
     178{
     179    return VINF_SUCCESS;
     180}
     181
     182static inline void *RTMemDupEx (const void *pvSrc, size_t cbSrc, size_t cbExtra)
     183{
     184    void *p = RTMemAlloc (cbSrc + cbExtra);
     185
     186    if (p)
     187    {
     188         memcpy (p, pvSrc, cbSrc);
     189         memset ((char *)p + cbSrc, 0, cbExtra);
     190    }
     191
     192    return p;
     193}
     194
     195static inline void *RTMemAllocZ (size_t cb)
     196{
     197    void *p = RTMemAlloc (cb);
     198
     199    if (p)
     200    {
     201         memset (p, 0, cb);
     202    }
     203
     204    return p;
     205}
     206
     207static inline void *RTMemAllocZVar (size_t cbUnaligned)
     208{
     209    return RTMemAllocZ(cbUnaligned);
     210}
     211
     212static inline int RTStrToUInt32Ex (const char *pszValue, char **ppszNext, unsigned uBase, uint32_t *pu32)
     213{
     214    *pu32 = strtoul (pszValue, ppszNext, uBase);
     215    return VINF_SUCCESS;
     216}
     217
     218#define PRTSTREAM FILE *
     219
     220static inline int RTStrmOpen (const char *pszFileName, const char *pszMode, PRTSTREAM *ppStream)
     221{
     222    *ppStream = fopen (pszFileName, pszMode);
     223
     224    if (*ppStream)
     225    {
     226        return VINF_SUCCESS;
     227    }
     228
     229    return VERR_NOT_SUPPORTED;
     230}
     231
     232static inline int RTStrmClose (PRTSTREAM pStream)
     233{
     234    fclose (pStream);
     235    return VINF_SUCCESS;
     236}
     237
     238static inline int RTStrmGetLine (PRTSTREAM pStream, char *pszString, size_t cchString)
     239{
     240    if (fgets (pszString, cchString, pStream))
     241    {
     242        return VINF_SUCCESS;
     243    }
     244
     245    return VERR_NOT_SUPPORTED;
     246}
     247
     248static inline char *RTStrStripL (const char *psz)
     249{
     250    while (isspace (*psz))
     251        psz++;
     252    return (char *)psz;
     253}
     254
     255#define NIL_RTFILE -1
     256
     257#define RTFILE_O_READWRITE 0x00000003
     258#define RTFILE_O_OPEN      0x00000000
     259#define RTFILE_O_DENY_NONE 0x00000000
     260
     261static inline int RTFileOpen (RTFILE *pFile, const char *pszFileName, unsigned fOpen)
     262{
     263    Assert (fOpen == RTFILE_O_READWRITE);
     264
     265    *pFile = open (pszFileName, O_RDWR, 00600);
     266
     267    if (*pFile != -1)
     268    {
     269        return VINF_SUCCESS;
     270    }
     271
     272    return VERR_ACCESS_DENIED;
     273}
     274
     275static inline int RTFileClose (RTFILE file)
     276{
     277    close (file);
     278    return VINF_SUCCESS;
     279}
     280#endif /* __RUNTIME__H  */
  • trunk/src/VBox/RDP/client/vrdp/vrdpusb.h

    r28800 r31247  
    1818#define __VRDPUSB__H
    1919
    20 #include <endian.h>
    21 #include <byteswap.h>
    22 
    23 #ifndef cpu_to_le16
    24 #if __BYTE_ORDER == __LITTLE_ENDIAN
    25 #define cpu_to_le16(_le16) (_le16)
    26 #elif __BYTE_ORDER == __BIG_ENDIAN
    27 #define cpu_to_le16(_le16) bswap_16(_le16)
    28 #else
    29 #error Unsupported host byte order!
    30 #endif
    31 #endif /* cpu_to_le16 */
    32 
    33 //#include <asm/byteorder.h>
    34 //#define cpu_to_le16 __cpu_to_le16
    35 
    36 #define uint8_t uint8
    37 #define uint16_t uint16
    38 #define uint32_t uint32
    39 #define uint64_t long long
    40 #define bool int
    41 #define false 0
    42 #define true 1
    43 
    44 #define OPSTATIC
    45 #ifdef RDPUSB_DEBUG
    46 #define LogFlow(a) printf a
    47 #define Log(a) printf a
    48 #define Log2(a) printf a
    49 #else
    50 #define LogFlow(a) do {} while (0)
    51 #define Log(a)     do {} while (0)
    52 #define Log2(a)    do {} while (0)
    53 #endif
    54 
    55 #define LogRel(a) printf a
    56 
    57 /* Runtime wrappers. */
    58 #define RTMemAlloc xmalloc
    59 #define RTMemRealloc xrealloc
    60 #define RTMemFree xfree
    61 
    62 #define _1K 1024
    63 
    64 #define RT_LE2H_U16(_le16) (cpu_to_le16 (_le16))
    65 
    66 #define VINF_SUCCESS 0
    67 #define VERR_NO_MEMORY     (-8)
    68 #define VERR_NOT_SUPPORTED (-37)
    69 #define VERR_ACCESS_DENIED (-38)
    70 #define VERR_VUSB_USBFS_PERMISSION (-2005)
    71 
    72 #define RT_SUCCESS(_rc) ((_rc) >= 0)
    73 
    74 #define RTFILE int
    75 #define RTCRITSECT void *
    76 
    77 #define Assert(_expr) do {                            \
    78     if (!(_expr))                                     \
    79     {                                                 \
    80         Log(("Assertion failed: {%s}!!!\n", #_expr)); \
    81     }                                                 \
    82 } while (0)
    83 
    84 #define AssertMsgFailed(_msg) do {                    \
    85         Log(("Assertion failed msg:!!!\n"));          \
    86         Log(_msg);                                    \
    87 } while (0)
    88 
    89 #define AssertReturn(_expr, _retval) do {             \
    90     if (!(_expr))                                     \
    91     {                                                 \
    92         Log(("Assertion failed: {%s}, returning 0x%08X!!!\n", #_expr, _retval)); \
    93         return (_retval);                             \
    94     }                                                 \
    95 } while (0)
    96 
    97 #define AssertRC(_rc) Assert(RT_SUCCESS(_rc))
    98 
    99 #define RT_FAILURE(_rc) (!RT_SUCCESS(_rc))
    100 
    101 #define NOREF(_a) ((void)_a)
    102 
    103 static inline int RTCritSectInit (RTCRITSECT *pCritSect)
    104 {
    105     return VINF_SUCCESS;
    106 }
    107 
    108 static inline int RTCritSectDelete (RTCRITSECT *pCritSect)
    109 {
    110     return VINF_SUCCESS;
    111 }
    112 
    113 static inline int RTCritSectEnter (RTCRITSECT *pCritSect)
    114 {
    115     return VINF_SUCCESS;
    116 }
    117 
    118 static inline int RTCritSectLeave (RTCRITSECT *pCritSect)
    119 {
    120     return VINF_SUCCESS;
    121 }
    122 
    123 static inline void *RTMemDupEx (const void *pvSrc, size_t cbSrc, size_t cbExtra)
    124 {
    125     void *p = RTMemAlloc (cbSrc + cbExtra);
    126 
    127     if (p)
    128     {
    129          memcpy (p, pvSrc, cbSrc);
    130          memset ((char *)p + cbSrc, 0, cbExtra);
    131     }
    132 
    133     return p;
    134 }
    135 
    136 static inline void *RTMemAllocZ (size_t cb)
    137 {
    138     void *p = RTMemAlloc (cb);
    139 
    140     if (p)
    141     {
    142          memset (p, 0, cb);
    143     }
    144 
    145     return p;
    146 }
    147 
    148 static inline int RTStrToUInt32Ex (const char *pszValue, char **ppszNext, unsigned uBase, uint32_t *pu32)
    149 {
    150     *pu32 = strtoul (pszValue, ppszNext, uBase);
    151     return VINF_SUCCESS;
    152 }
    153 
    154 #define PRTSTREAM FILE *
    155 
    156 static inline int RTStrmOpen (const char *pszFileName, const char *pszMode, PRTSTREAM *ppStream)
    157 {
    158     *ppStream = fopen (pszFileName, pszMode);
    159 
    160     if (*ppStream)
    161     {
    162         return VINF_SUCCESS;
    163     }
    164 
    165     return VERR_NOT_SUPPORTED;
    166 }
    167 
    168 static inline int RTStrmClose (PRTSTREAM pStream)
    169 {
    170     fclose (pStream);
    171     return VINF_SUCCESS;
    172 }
    173 
    174 static inline int RTStrmGetLine (PRTSTREAM pStream, char *pszString, size_t cchString)
    175 {
    176     if (fgets (pszString, cchString, pStream))
    177     {
    178         return VINF_SUCCESS;
    179     }
    180 
    181     return VERR_NOT_SUPPORTED;
    182 }
    183 
    184 static inline char *RTStrStripL (const char *psz)
    185 {
    186     while (isspace (*psz))
    187         psz++;
    188     return (char *)psz;
    189 }
    190 
    191 #define NIL_RTFILE -1
    192 
    193 #define RTFILE_O_READWRITE 0x00000003
    194 #define RTFILE_O_OPEN      0x00000000
    195 #define RTFILE_O_DENY_NONE 0x00000000
    196 
    197 static inline int RTFileOpen (RTFILE *pFile, const char *pszFileName, unsigned fOpen)
    198 {
    199     Assert (fOpen == RTFILE_O_READWRITE);
    200 
    201     *pFile = open (pszFileName, O_RDWR, 00600);
    202 
    203     if (*pFile != -1)
    204     {
    205         return VINF_SUCCESS;
    206     }
    207 
    208     return VERR_ACCESS_DENIED;
    209 }
    210 
    211 static inline int RTFileClose (RTFILE file)
    212 {
    213     close (file);
    214     return VINF_SUCCESS;
    215 }
    216 
    217 static inline uint64_t RTTimeMilliTS (void)
    218 {
    219      struct timeval tv;
    220      gettimeofday (&tv, NULL);
    221      return (uint64_t)tv.tv_sec * (uint64_t)(1000)
    222             + (uint64_t)(tv.tv_usec / 1000);
    223 }
    224 
    22520#define VRDP_USB_STATUS_SUCCESS         0
    22621#define VRDP_USB_STATUS_ACCESS_DENIED   1
     
    23328#define VRDP_USB_CAPS_FLAG_POLL     (1)
    23429
    235 #pragma pack(1)
    236 
    237 #include "vusb.h"
    238 
    239 typedef struct VUSBDEV
    240 {
    241         char* pszName;
    242         int request_detach;
    243 } VUSBDEV, *PVUSBDEV;
    244 
    245 typedef struct usb_proxy {
    246     /* Note: the backend code assumes that the dev member is the first in the structure. */
    247     VUSBDEV Dev;
    248     /* 'union' because backend accesses the file handle as priv.File. */
    249     union {
    250         void *pv;
    251         int File;
    252     } Backend;
    253 
    254     struct usb_proxy *next;
    255     struct usb_proxy *prev;
    256 
    257     uint32_t devid;
    258 
    259     PVUSBURB urbs;
    260 
    261     int iActiveCfg;
    262     int cIgnoreSetConfigs;
    263 } *PUSBPROXYDEV;
    264 
    265 typedef struct vusb_setup {
    266         uint8_t  bmRequestType;
    267         uint8_t  bRequest;
    268         uint16_t wValue;
    269         uint16_t wIndex;
    270         uint16_t wLength;
    271 } VUSBSETUP, *PVUSBSETUP;
    272 #pragma pack()
    273 
    274 
    275 static inline void vusbDevUnplugged(PVUSBDEV dev)
    276 {
    277         dev->request_detach = 1;
    278 }
    279 
    280 int dev2fd (PUSBPROXYDEV pProxyDev);
    281 
    282 
    283 typedef struct USBPROXYBACK
    284 {
    285     /** Name of the backend. */
    286     const char *pszName;
    287 
    288     int  (* pfnOpen)(PUSBPROXYDEV pProxyDev, const char *pszAddress, void *pvBackend);
    289     void (* pfnClose)(PUSBPROXYDEV pProxyDev);
    290     int  (* pfnReset)(PUSBPROXYDEV pProxyDev);
    291     int  (* pfnSetConfig)(PUSBPROXYDEV pProxyDev, int iCfg);
    292     int  (* pfnClaimInterface)(PUSBPROXYDEV pProxyDev, int iIf);
    293     int  (* pfnReleaseInterface)(PUSBPROXYDEV pProxyDev, int iIf);
    294     int  (* pfnSetInterface)(PUSBPROXYDEV pProxyDev, int iIf, int setting);
    295     bool (* pfnClearHaltedEndpoint)(PUSBPROXYDEV  pDev, unsigned int iEp);
    296     int  (* pfnUrbQueue)(PVUSBURB urb);
    297     void (* pfnUrbCancel)(PVUSBURB pUrb);
    298     PVUSBURB (* pfnUrbReap)(PUSBPROXYDEV pProxyDev, unsigned cMillies);
    299     uint32_t uDummy;
    300 } USBPROXYBACK;
    301 
    302 typedef USBPROXYBACK *PUSBPROXYBACK;
    303 
    304 extern const USBPROXYBACK g_USBProxyDeviceHost;
    305 
    306 static inline int op_usbproxy_back_open(struct usb_proxy *p, const char *pszAddress)
    307 {
    308      return g_USBProxyDeviceHost.pfnOpen (p, pszAddress, NULL);
    309 }
    310 
    311 static inline void op_usbproxy_back_close(PUSBPROXYDEV pDev)
    312 {
    313      return g_USBProxyDeviceHost.pfnClose (pDev);
    314 }
    315 
    316 static inline int op_usbproxy_back_reset(PUSBPROXYDEV pDev)
    317 {
    318     return g_USBProxyDeviceHost.pfnReset (pDev);
    319 }
    320 
    321 static inline int op_usbproxy_back_set_config(PUSBPROXYDEV pDev, int cfg)
    322 {
    323     return g_USBProxyDeviceHost.pfnSetConfig (pDev, cfg);
    324 }
    325 
    326 static inline int op_usbproxy_back_claim_interface(PUSBPROXYDEV pDev, int ifnum)
    327 {
    328     return g_USBProxyDeviceHost.pfnClaimInterface (pDev, ifnum);
    329 }
    330 
    331 static inline int op_usbproxy_back_release_interface(PUSBPROXYDEV pDev, int ifnum)
    332 {
    333     return g_USBProxyDeviceHost.pfnReleaseInterface (pDev, ifnum);
    334 }
    335 
    336 static inline int op_usbproxy_back_interface_setting(PUSBPROXYDEV pDev, int ifnum, int setting)
    337 {
    338     return g_USBProxyDeviceHost.pfnSetInterface (pDev, ifnum, setting);
    339 }
    340 
    341 static inline int op_usbproxy_back_queue_urb(PVUSBURB pUrb)
    342 {
    343     return g_USBProxyDeviceHost.pfnUrbQueue(pUrb);
    344 }
    345 
    346 static inline PVUSBURB op_usbproxy_back_reap_urb(PUSBPROXYDEV pDev, unsigned cMillies)
    347 {
    348     return g_USBProxyDeviceHost.pfnUrbReap (pDev, cMillies);
    349 }
    350 
    351 static inline bool op_usbproxy_back_clear_halted_ep(PUSBPROXYDEV pDev, unsigned EndPoint)
    352 {
    353     return g_USBProxyDeviceHost.pfnClearHaltedEndpoint (pDev, EndPoint);
    354 }
    355 
    356 static inline void op_usbproxy_back_cancel_urb(PVUSBURB pUrb)
    357 {
    358     return g_USBProxyDeviceHost.pfnUrbCancel (pUrb);
    359 }
    360 
    36130#endif /* __VRDPUSB__H  */
  • trunk/src/VBox/RDP/client/vrdp/vusb.h

    r28800 r31247  
    11/** @file
    2  *
     2 * VUSB - VirtualBox USB. (DEV,VMM)
    33 */
    44
     
    1313 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
    1414 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
    15  */
     15 *
     16 * The contents of this file may alternatively be used under the terms
     17 * of the Common Development and Distribution License Version 1.0
     18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
     19 * VirtualBox OSE distribution, in which case the provisions of the
     20 * CDDL are applicable instead of those of the GPL.
     21 *
     22 * You may elect to license modified versions of this file under the
     23 * terms and conditions of either the GPL or the CDDL or both.
     24 */
     25
     26#ifndef ___VBox_vusb_h
     27#define ___VBox_vusb_h
     28
     29#ifndef RDESKTOP
     30# include <VBox/cdefs.h>
     31# include <VBox/types.h>
     32#else
     33# include "runtime.h"
     34#endif
     35
     36RT_C_DECLS_BEGIN
     37
     38/** @defgroup grp_vusb  VBox USB API
     39 * @{
     40 */
     41
     42/** @defgroup grp_vusb_std  Standard Stuff
     43 * @{ */
     44
     45/** Frequency of USB bus (from spec). */
     46#define VUSB_BUS_HZ                 12000000
     47
     48
     49/** @name USB Descriptor types (from spec)
     50 * @{ */
     51#define VUSB_DT_DEVICE                  0x01
     52#define VUSB_DT_CONFIG                  0x02
     53#define VUSB_DT_STRING                  0x03
     54#define VUSB_DT_INTERFACE               0x04
     55#define VUSB_DT_ENDPOINT                0x05
     56#define VUSB_DT_DEVICE_QUALIFIER        0x06
     57#define VUSB_DT_OTHER_SPEED_CFG         0x07
     58#define VUSB_DT_INTERFACE_POWER         0x08
     59/** @} */
     60
     61/** @name USB Descriptor minimum sizes (from spec)
     62 * @{ */
     63#define VUSB_DT_DEVICE_MIN_LEN          18
     64#define VUSB_DT_CONFIG_MIN_LEN          9
     65#define VUSB_DT_CONFIG_STRING_MIN_LEN   2
     66#define VUSB_DT_INTERFACE_MIN_LEN       9
     67#define VUSB_DT_ENDPOINT_MIN_LEN        7
     68/** @} */
     69
     70
     71#pragma pack(1) /* ensure byte packing of the descriptors. */
     72
     73/**
     74 * USB language id descriptor (from specs).
     75 */
     76typedef struct VUSBDESCLANGID
     77{
     78    uint8_t bLength;
     79    uint8_t bDescriptorType;
     80} VUSBDESCLANGID;
     81/** Pointer to a USB language id descriptor. */
     82typedef VUSBDESCLANGID *PVUSBDESCLANGID;
     83/** Pointer to a const USB language id descriptor. */
     84typedef const VUSBDESCLANGID *PCVUSBDESCLANGID;
     85
     86
     87/**
     88 * USB string descriptor (from specs).
     89 */
     90typedef struct VUSBDESCSTRING
     91{
     92    uint8_t bLength;
     93    uint8_t bDescriptorType;
     94} VUSBDESCSTRING;
     95/** Pointer to a USB string descriptor. */
     96typedef VUSBDESCSTRING *PVUSBDESCSTRING;
     97/** Pointer to a const USB string descriptor. */
     98typedef const VUSBDESCSTRING *PCVUSBDESCSTRING;
     99
     100
     101/**
     102 * USB device descriptor (from spec)
     103 */
     104typedef struct VUSBDESCDEVICE
     105{
     106    uint8_t  bLength;
     107    uint8_t  bDescriptorType;
     108    uint16_t bcdUSB;
     109    uint8_t  bDeviceClass;
     110    uint8_t  bDeviceSubClass;
     111    uint8_t  bDeviceProtocol;
     112    uint8_t  bMaxPacketSize0;
     113    uint16_t idVendor;
     114    uint16_t idProduct;
     115    uint16_t bcdDevice;
     116    uint8_t  iManufacturer;
     117    uint8_t  iProduct;
     118    uint8_t  iSerialNumber;
     119    uint8_t  bNumConfigurations;
     120} VUSBDESCDEVICE;
     121/** Pointer to a USB device descriptor. */
     122typedef VUSBDESCDEVICE *PVUSBDESCDEVICE;
     123/** Pointer to a const USB device descriptor. */
     124typedef const VUSBDESCDEVICE *PCVUSBDESCDEVICE;
     125
     126
     127/**
     128 * USB configuration descriptor (from spec).
     129 */
     130typedef struct VUSBDESCCONFIG
     131{
     132    uint8_t  bLength;
     133    uint8_t  bDescriptorType;
     134    uint16_t wTotalLength; /**< recalculated by VUSB when involved in URB. */
     135    uint8_t  bNumInterfaces;
     136    uint8_t  bConfigurationValue;
     137    uint8_t  iConfiguration;
     138    uint8_t  bmAttributes;
     139    uint8_t  MaxPower;
     140} VUSBDESCCONFIG;
     141/** Pointer to a USB configuration descriptor. */
     142typedef VUSBDESCCONFIG *PVUSBDESCCONFIG;
     143/** Pointer to a readonly USB configuration descriptor. */
     144typedef const VUSBDESCCONFIG *PCVUSBDESCCONFIG;
     145
     146
     147/**
     148 * USB interface descriptor (from spec)
     149 */
     150typedef struct VUSBDESCINTERFACE
     151{
     152    uint8_t  bLength;
     153    uint8_t  bDescriptorType;
     154    uint8_t  bInterfaceNumber;
     155    uint8_t  bAlternateSetting;
     156    uint8_t  bNumEndpoints;
     157    uint8_t  bInterfaceClass;
     158    uint8_t  bInterfaceSubClass;
     159    uint8_t  bInterfaceProtocol;
     160    uint8_t  iInterface;
     161} VUSBDESCINTERFACE;
     162/** Pointer to an USB interface descriptor. */
     163typedef VUSBDESCINTERFACE *PVUSBDESCINTERFACE;
     164/** Pointer to a const USB interface descriptor. */
     165typedef const VUSBDESCINTERFACE *PCVUSBDESCINTERFACE;
     166
     167
     168/**
     169 * USB endpoint descriptor (from spec)
     170 */
     171typedef struct VUSBDESCENDPOINT
     172{
     173    uint8_t  bLength;
     174    uint8_t  bDescriptorType;
     175    uint8_t  bEndpointAddress;
     176    uint8_t  bmAttributes;
     177    uint16_t wMaxPacketSize;
     178    uint8_t  bInterval;
     179} VUSBDESCENDPOINT;
     180/** Pointer to an USB endpoint descriptor. */
     181typedef VUSBDESCENDPOINT *PVUSBDESCENDPOINT;
     182/** Pointer to a const USB endpoint descriptor. */
     183typedef const VUSBDESCENDPOINT *PCVUSBDESCENDPOINT;
     184
     185#pragma pack() /* end of the byte packing. */
     186
     187
     188/**
     189 * USB configuration descriptor, the parsed variant used by VUSB.
     190 */
     191typedef struct VUSBDESCCONFIGEX
     192{
     193    /** The USB descriptor data.
     194     * @remark  The wTotalLength member is recalculated before the data is passed to the guest. */
     195    VUSBDESCCONFIG Core;
     196    /** Pointer to additional descriptor bytes following what's covered by VUSBDESCCONFIG. */
     197    void *pvMore;
     198    /** Pointer to an array of the interfaces referenced in the configuration.
     199     * Core.bNumInterfaces in size. */
     200    const struct VUSBINTERFACE *paIfs;
     201} VUSBDESCCONFIGEX;
     202/** Pointer to a parsed USB configuration descriptor. */
     203typedef VUSBDESCCONFIGEX *PVUSBDESCCONFIGEX;
     204/** Pointer to a const parsed USB configuration descriptor. */
     205typedef const VUSBDESCCONFIGEX *PCVUSBDESCCONFIGEX;
     206
     207
     208/**
     209 * For tracking the alternate interface settings of a configuration.
     210 */
     211typedef struct VUSBINTERFACE
     212{
     213    /** Pointer to an array of interfaces. */
     214    const struct VUSBDESCINTERFACEEX *paSettings;
     215    /** The number of entries in the array. */
     216    uint32_t cSettings;
     217} VUSBINTERFACE;
     218/** Pointer to a VUSBINTERFACE. */
     219typedef VUSBINTERFACE *PVUSBINTERFACE;
     220/** Pointer to a const VUSBINTERFACE. */
     221typedef const VUSBINTERFACE *PCVUSBINTERFACE;
     222
     223
     224/**
     225 * USB interface descriptor, the parsed variant used by VUSB.
     226 */
     227typedef struct VUSBDESCINTERFACEEX
     228{
     229    /** The USB descriptor data. */
     230    VUSBDESCINTERFACE Core;
     231    /** Pointer to additional descriptor bytes following what's covered by VUSBDESCINTERFACE. */
     232    const void *pvMore;
     233    /** Pointer to additional class- or vendor-specific interface descriptors. */
     234    const void *pvClass;
     235    /** Size of class- or vendor-specific descriptors. */
     236    uint16_t cbClass;
     237    /** Pointer to an array of the endpoints referenced by the interface.
     238     * Core.bNumEndpoints in size. */
     239    const struct VUSBDESCENDPOINTEX *paEndpoints;
     240} VUSBDESCINTERFACEEX;
     241/** Pointer to an prased USB interface descriptor. */
     242typedef VUSBDESCINTERFACEEX *PVUSBDESCINTERFACEEX;
     243/** Pointer to a const parsed USB interface descriptor. */
     244typedef const VUSBDESCINTERFACEEX *PCVUSBDESCINTERFACEEX;
     245
     246
     247/**
     248 * USB endpoint descriptor, the parsed variant used by VUSB.
     249 */
     250typedef struct VUSBDESCENDPOINTEX
     251{
     252    /** The USB descriptor data.
     253     * @remark The wMaxPacketSize member is converted to native endian. */
     254    VUSBDESCENDPOINT Core;
     255    /** Pointer to additional descriptor bytes following what's covered by VUSBDESCENDPOINT. */
     256    const void *pvMore;
     257    /** Pointer to additional class- or vendor-specific interface descriptors. */
     258    const void *pvClass;
     259    /** Size of class- or vendor-specific descriptors. */
     260    uint16_t cbClass;
     261} VUSBDESCENDPOINTEX;
     262/** Pointer to a parsed USB endpoint descriptor. */
     263typedef VUSBDESCENDPOINTEX *PVUSBDESCENDPOINTEX;
     264/** Pointer to a const parsed USB endpoint descriptor. */
     265typedef const VUSBDESCENDPOINTEX *PCVUSBDESCENDPOINTEX;
     266
     267
     268/** @name USB Control message recipient codes (from spec)
     269 * @{ */
     270#define VUSB_TO_DEVICE          0x0
     271#define VUSB_TO_INTERFACE       0x1
     272#define VUSB_TO_ENDPOINT        0x2
     273#define VUSB_TO_OTHER           0x3
     274#define VUSB_RECIP_MASK         0x1f
     275/** @} */
     276
     277/** @name USB control pipe setup packet structure (from spec)
     278 * @{ */
     279#define VUSB_REQ_SHIFT          (5)
     280#define VUSB_REQ_STANDARD       (0x0 << VUSB_REQ_SHIFT)
     281#define VUSB_REQ_CLASS          (0x1 << VUSB_REQ_SHIFT)
     282#define VUSB_REQ_VENDOR         (0x2 << VUSB_REQ_SHIFT)
     283#define VUSB_REQ_RESERVED       (0x3 << VUSB_REQ_SHIFT)
     284#define VUSB_REQ_MASK           (0x3 << VUSB_REQ_SHIFT)
     285/** @} */
     286
     287#define VUSB_DIR_TO_DEVICE      0x00
     288#define VUSB_DIR_TO_HOST        0x80
     289#define VUSB_DIR_MASK           0x80
     290
     291/**
     292 * USB Setup request (from spec)
     293 */
     294typedef struct vusb_setup
     295{
     296    uint8_t  bmRequestType;
     297    uint8_t  bRequest;
     298    uint16_t wValue;
     299    uint16_t wIndex;
     300    uint16_t wLength;
     301} VUSBSETUP;
     302/** Pointer to a setup request. */
     303typedef VUSBSETUP *PVUSBSETUP;
     304/** Pointer to a const setup request. */
     305typedef const VUSBSETUP *PCVUSBSETUP;
     306
     307/** @name USB Standard device requests (from spec)
     308 * @{ */
     309#define VUSB_REQ_GET_STATUS         0x00
     310#define VUSB_REQ_CLEAR_FEATURE      0x01
     311#define VUSB_REQ_SET_FEATURE        0x03
     312#define VUSB_REQ_SET_ADDRESS        0x05
     313#define VUSB_REQ_GET_DESCRIPTOR     0x06
     314#define VUSB_REQ_SET_DESCRIPTOR     0x07
     315#define VUSB_REQ_GET_CONFIGURATION  0x08
     316#define VUSB_REQ_SET_CONFIGURATION  0x09
     317#define VUSB_REQ_GET_INTERFACE      0x0a
     318#define VUSB_REQ_SET_INTERFACE      0x0b
     319#define VUSB_REQ_SYNCH_FRAME        0x0c
     320#define VUSB_REQ_MAX                0x0d
     321/** @} */
     322
     323/** @} */ /* end of grp_vusb_std */
     324
     325
     326
     327/** @name USB Standard version flags.
     328 * @{ */
     329/** Indicates USB 1.1 support. */
     330#define VUSB_STDVER_11              RT_BIT(1)
     331/** Indicates USB 2.0 support. */
     332#define VUSB_STDVER_20              RT_BIT(2)
     333/** @} */
     334
    16335
    17336/** Pointer to a VBox USB device interface. */
     
    25344
    26345
     346
     347/**
     348 * VBox USB port bitmap.
     349 *
     350 * Bit 0 == Port 0, ... , Bit 127 == Port 127.
     351 */
     352typedef struct VUSBPORTBITMAP
     353{
     354    /** 128 bits */
     355    char ach[16];
     356} VUSBPORTBITMAP;
     357/** Pointer to a VBox USB port bitmap. */
     358typedef VUSBPORTBITMAP *PVUSBPORTBITMAP;
     359
     360#ifndef RDESKTOP
     361
     362/**
     363 * The VUSB RootHub port interface provided by the HCI (down).
     364 * Pair with VUSBIROOTCONNECTOR
     365 */
     366typedef struct VUSBIROOTHUBPORT
     367{
     368    /**
     369     * Get the number of avilable ports in the hub.
     370     *
     371     * @returns The number of ports available.
     372     * @param   pInterface      Pointer to this structure.
     373     * @param   pAvailable      Bitmap indicating the available ports. Set bit == available port.
     374     */
     375    DECLR3CALLBACKMEMBER(unsigned, pfnGetAvailablePorts,(PVUSBIROOTHUBPORT pInterface, PVUSBPORTBITMAP pAvailable));
     376
     377    /**
     378     * Gets the supported USB versions.
     379     *
     380     * @returns The mask of supported USB versions.
     381     * @param   pInterface      Pointer to this structure.
     382     */
     383    DECLR3CALLBACKMEMBER(uint32_t, pfnGetUSBVersions,(PVUSBIROOTHUBPORT pInterface));
     384
     385    /**
     386     * A device is being attached to a port in the roothub.
     387     *
     388     * @param   pInterface      Pointer to this structure.
     389     * @param   pDev            Pointer to the device being attached.
     390     * @param   uPort           The port number assigned to the device.
     391     */
     392    DECLR3CALLBACKMEMBER(int, pfnAttach,(PVUSBIROOTHUBPORT pInterface, PVUSBIDEVICE pDev, unsigned uPort));
     393
     394    /**
     395     * A device is being detached from a port in the roothub.
     396     *
     397     * @param   pInterface      Pointer to this structure.
     398     * @param   pDev            Pointer to the device being detached.
     399     * @param   uPort           The port number assigned to the device.
     400     */
     401    DECLR3CALLBACKMEMBER(void, pfnDetach,(PVUSBIROOTHUBPORT pInterface, PVUSBIDEVICE pDev, unsigned uPort));
     402
     403    /**
     404     * Reset the root hub.
     405     *
     406     * @returns VBox status code.
     407     * @param   pInterface      Pointer to this structure.
     408     * @param   pResetOnLinux   Whether or not to do real reset on linux.
     409     */
     410    DECLR3CALLBACKMEMBER(int, pfnReset,(PVUSBIROOTHUBPORT pInterface, bool fResetOnLinux));
     411
     412    /**
     413     * Transfer completion callback routine.
     414     *
     415     * VUSB will call this when a transfer have been completed
     416     * in a one or another way.
     417     *
     418     * @param   pInterface      Pointer to this structure.
     419     * @param   pUrb            Pointer to the URB in question.
     420     */
     421    DECLR3CALLBACKMEMBER(void, pfnXferCompletion,(PVUSBIROOTHUBPORT pInterface, PVUSBURB urb));
     422
     423    /**
     424     * Handle transfer errors.
     425     *
     426     * VUSB calls this when a transfer attempt failed. This function will respond
     427     * indicating wheter to retry or complete the URB with failure.
     428     *
     429     * @returns Retry indicator.
     430     * @param   pInterface      Pointer to this structure.
     431     * @param   pUrb            Pointer to the URB in question.
     432     */
     433    DECLR3CALLBACKMEMBER(bool, pfnXferError,(PVUSBIROOTHUBPORT pInterface, PVUSBURB pUrb));
     434
     435    /** Alignment dummy. */
     436    RTR3PTR Alignment;
     437
     438} VUSBIROOTHUBPORT;
     439/** VUSBIROOTHUBPORT interface ID. */
     440#define VUSBIROOTHUBPORT_IID                    "e38e2978-7aa2-4860-94b6-9ef4a066d8a0"
     441
     442
     443/** Pointer to a VUSB RootHub connector interface. */
     444typedef struct VUSBIROOTHUBCONNECTOR *PVUSBIROOTHUBCONNECTOR;
     445/**
     446 * The VUSB RootHub connector interface provided by the VBox USB RootHub driver
     447 * (up).
     448 * Pair with VUSBIROOTHUBPORT.
     449 */
     450typedef struct VUSBIROOTHUBCONNECTOR
     451{
     452    /**
     453     * Allocates a new URB for a transfer.
     454     *
     455     * Either submit using pfnSubmitUrb or free using VUSBUrbFree().
     456     *
     457     * @returns Pointer to a new URB.
     458     * @returns NULL on failure - try again later.
     459     *          This will not fail if the device wasn't found. We'll fail it
     460     *          at submit time, since that makes the usage of this api simpler.
     461     * @param   pInterface  Pointer to this struct.
     462     * @param   DstAddress  The destination address of the URB.
     463     * @param   cbData      The amount of data space required.
     464     * @param   cTds        The amount of TD space.
     465     */
     466    DECLR3CALLBACKMEMBER(PVUSBURB, pfnNewUrb,(PVUSBIROOTHUBCONNECTOR pInterface, uint8_t DstAddress, uint32_t cbData, uint32_t cTds));
     467
     468    /**
     469     * Submits a URB for transfer.
     470     * The transfer will do asynchronously if possible.
     471     *
     472     * @returns VBox status code.
     473     * @param   pInterface  Pointer to this struct.
     474     * @param   pUrb        Pointer to the URB returned by pfnNewUrb.
     475     *                      The URB will be freed in case of failure.
     476     * @param   pLed        Pointer to USB Status LED
     477     */
     478    DECLR3CALLBACKMEMBER(int, pfnSubmitUrb,(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb, struct PDMLED *pLed));
     479
     480    /**
     481     * Call to service asynchronous URB completions in a polling fashion.
     482     *
     483     * Reaped URBs will be finished by calling the completion callback,
     484     * thus there is no return code or input or anything from this function
     485     * except for potential state changes elsewhere.
     486     *
     487     * @returns VINF_SUCCESS if no URBs are pending upon return.
     488     * @returns VERR_TIMEOUT if one or more URBs are still in flight upon returning.
     489     * @returns Other VBox status code.
     490     *
     491     * @param   pInterface  Pointer to this struct.
     492     * @param   cMillies    Number of milliseconds to poll for completion.
     493     */
     494    DECLR3CALLBACKMEMBER(void, pfnReapAsyncUrbs,(PVUSBIROOTHUBCONNECTOR pInterface, RTMSINTERVAL cMillies));
     495
     496    /**
     497     * Cancels and completes - with CRC failure - all in-flight async URBs.
     498     * This is typically done before saving a state.
     499     *
     500     * @param   pInterface  Pointer to this struct.
     501     */
     502    DECLR3CALLBACKMEMBER(void, pfnCancelAllUrbs,(PVUSBIROOTHUBCONNECTOR pInterface));
     503
     504    /**
     505     * Attach the device to the root hub.
     506     * The device must not be attached to any hub for this call to succeed.
     507     *
     508     * @returns VBox status code.
     509     * @param   pInterface  Pointer to this struct.
     510     * @param   pDevice     Pointer to the device (interface) attach.
     511     */
     512    DECLR3CALLBACKMEMBER(int, pfnAttachDevice,(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice));
     513
     514    /**
     515     * Detach the device from the root hub.
     516     * The device must already be attached for this call to succeed.
     517     *
     518     * @returns VBox status code.
     519     * @param   pInterface  Pointer to this struct.
     520     * @param   pDevice     Pointer to the device (interface) to detach.
     521     */
     522    DECLR3CALLBACKMEMBER(int, pfnDetachDevice,(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice));
     523
     524} VUSBIROOTHUBCONNECTOR;
     525/** VUSBIROOTHUBCONNECTOR interface ID. */
     526#define VUSBIROOTHUBCONNECTOR_IID               "d9a90c59-e3ff-4dff-9754-844557c3f7a0"
     527
     528
     529#ifdef IN_RING3
     530/** @copydoc VUSBIROOTHUBCONNECTOR::pfnNewUrb */
     531DECLINLINE(PVUSBURB) VUSBIRhNewUrb(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t DstAddress, uint32_t cbData, uint32_t cTds)
     532{
     533    return pInterface->pfnNewUrb(pInterface, DstAddress, cbData, cTds);
     534}
     535
     536/** @copydoc VUSBIROOTHUBCONNECTOR::pfnSubmitUrb */
     537DECLINLINE(int) VUSBIRhSubmitUrb(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb, struct PDMLED *pLed)
     538{
     539    return pInterface->pfnSubmitUrb(pInterface, pUrb, pLed);
     540}
     541
     542/** @copydoc VUSBIROOTHUBCONNECTOR::pfnReapAsyncUrbs */
     543DECLINLINE(void) VUSBIRhReapAsyncUrbs(PVUSBIROOTHUBCONNECTOR pInterface, RTMSINTERVAL cMillies)
     544{
     545    pInterface->pfnReapAsyncUrbs(pInterface, cMillies);
     546}
     547
     548/** @copydoc VUSBIROOTHUBCONNECTOR::pfnCancelAllUrbs */
     549DECLINLINE(void) VUSBIRhCancelAllUrbs(PVUSBIROOTHUBCONNECTOR pInterface)
     550{
     551    pInterface->pfnCancelAllUrbs(pInterface);
     552}
     553
     554/** @copydoc VUSBIROOTHUBCONNECTOR::pfnAttachDevice */
     555DECLINLINE(int) VUSBIRhAttachDevice(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice)
     556{
     557    return pInterface->pfnAttachDevice(pInterface, pDevice);
     558}
     559
     560/** @copydoc VUSBIROOTHUBCONNECTOR::pfnDetachDevice */
     561DECLINLINE(int) VUSBIRhDetachDevice(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice)
     562{
     563    return pInterface->pfnDetachDevice(pInterface, pDevice);
     564}
     565#endif /* IN_RING3 */
     566
     567
     568
     569/** Pointer to a Root Hub Configuration Interface. */
     570typedef struct VUSBIRHCONFIG *PVUSBIRHCONFIG;
     571/**
     572 * Root Hub Configuration Interface (intended for MAIN).
     573 * No interface pair.
     574 */
     575typedef struct VUSBIRHCONFIG
     576{
     577    /**
     578     * Creates a USB proxy device and attaches it to the root hub.
     579     *
     580     * @returns VBox status code.
     581     * @param   pInterface      Pointer to the root hub configuration interface structure.
     582     * @param   pUuid           Pointer to the UUID for the new device.
     583     * @param   fRemote         Whether the device must use the VRDP backend.
     584     * @param   pszAddress      OS specific device address.
     585     * @param   pvBackend       An opaque pointer for the backend. Only used by
     586     *                          the VRDP backend so far.
     587     */
     588    DECLR3CALLBACKMEMBER(int, pfnCreateProxyDevice,(PVUSBIRHCONFIG pInterface, PCRTUUID pUuid, bool fRemote, const char *pszAddress, void *pvBackend));
     589
     590    /**
     591     * Removes a USB proxy device from the root hub and destroys it.
     592     *
     593     * @returns VBox status code.
     594     * @param   pInterface      Pointer to the root hub configuration interface structure.
     595     * @param   pUuid           Pointer to the UUID for the device.
     596     */
     597    DECLR3CALLBACKMEMBER(int, pfnDestroyProxyDevice,(PVUSBIRHCONFIG pInterface, PCRTUUID pUuid));
     598
     599} VUSBIRHCONFIG;
     600/** VUSBIRHCONFIG interface ID. */
     601#define VUSBIRHCONFIG_IID                       "c354cd97-e85f-465e-bc12-b58798465f52"
     602
     603
     604#ifdef IN_RING3
     605/** @copydoc  VUSBIRHCONFIG::pfnCreateProxyDevice */
     606DECLINLINE(int) VUSBIRhCreateProxyDevice(PVUSBIRHCONFIG pInterface, PCRTUUID pUuid, bool fRemote, const char *pszAddress, void *pvBackend)
     607{
     608    return pInterface->pfnCreateProxyDevice(pInterface, pUuid, fRemote, pszAddress, pvBackend);
     609}
     610
     611/** @copydoc VUSBIRHCONFIG::pfnDestroyProxyDevice */
     612DECLINLINE(int) VUSBIRhDestroyProxyDevice(PVUSBIRHCONFIG pInterface, PCRTUUID pUuid)
     613{
     614    return pInterface->pfnDestroyProxyDevice(pInterface, pUuid);
     615}
     616#endif /* IN_RING3 */
     617
     618#endif /* ! RDESKTOP */
     619
     620
     621/**
     622 * VUSB device reset completion callback function.
     623 * This is called by the reset thread when the reset has been completed.
     624 *
     625 * @param   pDev        Pointer to the virtual USB device core.
     626 * @param   rc      The VBox status code of the reset operation.
     627 * @param   pvUser      User specific argument.
     628 *
     629 * @thread  The reset thread or EMT.
     630 */
     631typedef DECLCALLBACK(void) FNVUSBRESETDONE(PVUSBIDEVICE pDevice, int rc, void *pvUser);
     632/** Pointer to a device reset completion callback function (FNUSBRESETDONE). */
     633typedef FNVUSBRESETDONE *PFNVUSBRESETDONE;
     634
     635/**
     636 * The state of a VUSB Device.
     637 *
     638 * @remark  The order of these states is vital.
     639 */
     640typedef enum VUSBDEVICESTATE
     641{
     642    VUSB_DEVICE_STATE_INVALID = 0,
     643    VUSB_DEVICE_STATE_DETACHED,
     644    VUSB_DEVICE_STATE_ATTACHED,
     645    VUSB_DEVICE_STATE_POWERED,
     646    VUSB_DEVICE_STATE_DEFAULT,
     647    VUSB_DEVICE_STATE_ADDRESS,
     648    VUSB_DEVICE_STATE_CONFIGURED,
     649    VUSB_DEVICE_STATE_SUSPENDED,
     650    /** The device is being reset. Don't mess with it.
     651     * Next states: VUSB_DEVICE_STATE_DEFAULT, VUSB_DEVICE_STATE_DESTROYED
     652     */
     653    VUSB_DEVICE_STATE_RESET,
     654    /** The device has been destroy. */
     655    VUSB_DEVICE_STATE_DESTROYED,
     656    /** The usual 32-bit hack. */
     657    VUSB_DEVICE_STATE_32BIT_HACK = 0x7fffffff
     658} VUSBDEVICESTATE;
     659
     660#ifndef RDESKTOP
     661
     662/**
     663 * USB Device Interface (up).
     664 * No interface pair.
     665 */
     666typedef struct VUSBIDEVICE
     667{
     668    /**
     669     * Resets the device.
     670     *
     671     * Since a device reset shall take at least 10ms from the guest point of view,
     672     * it must be performed asynchronously. We create a thread which performs this
     673     * operation and ensures it will take at least 10ms.
     674     *
     675     * At times - like init - a synchronous reset is required, this can be done
     676     * by passing NULL for pfnDone.
     677     *
     678     * -- internal stuff, move it --
     679     * While the device is being reset it is in the VUSB_DEVICE_STATE_RESET state.
     680     * On completion it will be in the VUSB_DEVICE_STATE_DEFAULT state if successful,
     681     * or in the VUSB_DEVICE_STATE_DETACHED state if the rest failed.
     682     * -- internal stuff, move it --
     683     *
     684     * @returns VBox status code.
     685     * @param   pInterface      Pointer to this structure.
     686     * @param   fResetOnLinux   Set if we can permit a real reset and a potential logical
     687     *                          device reconnect on linux hosts.
     688     * @param   pfnDone         Pointer to the completion routine. If NULL a synchronous
     689     *                          reset  is preformed not respecting the 10ms.
     690     * @param   pvUser          User argument to the completion routine.
     691     * @param   pVM             Pointer to the VM handle if callback in EMT is required. (optional)
     692     */
     693    DECLR3CALLBACKMEMBER(int, pfnReset,(PVUSBIDEVICE pInterface, bool fResetOnLinux,
     694                                        PFNVUSBRESETDONE pfnDone, void *pvUser, PVM pVM));
     695
     696    /**
     697     * Powers on the device.
     698     *
     699     * @returns VBox status code.
     700     * @param   pInterface      Pointer to the device interface structure.
     701     */
     702    DECLR3CALLBACKMEMBER(int, pfnPowerOn,(PVUSBIDEVICE pInterface));
     703
     704    /**
     705     * Powers off the device.
     706     *
     707     * @returns VBox status code.
     708     * @param   pInterface      Pointer to the device interface structure.
     709     */
     710    DECLR3CALLBACKMEMBER(int, pfnPowerOff,(PVUSBIDEVICE pInterface));
     711
     712    /**
     713     * Get the state of the device.
     714     *
     715     * @returns Device state.
     716     * @param   pInterface      Pointer to the device interface structure.
     717     */
     718    DECLR3CALLBACKMEMBER(VUSBDEVICESTATE, pfnGetState,(PVUSBIDEVICE pInterface));
     719
     720} VUSBIDEVICE;
     721/** VUSBIDEVICE interface ID. */
     722#define VUSBIDEVICE_IID                         "88732dd3-0ccd-4625-b040-48804ac7a217"
     723
     724
     725#ifdef IN_RING3
     726/**
     727 * Resets the device.
     728 *
     729 * Since a device reset shall take at least 10ms from the guest point of view,
     730 * it must be performed asynchronously. We create a thread which performs this
     731 * operation and ensures it will take at least 10ms.
     732 *
     733 * At times - like init - a synchronous reset is required, this can be done
     734 * by passing NULL for pfnDone.
     735 *
     736 * -- internal stuff, move it --
     737 * While the device is being reset it is in the VUSB_DEVICE_STATE_RESET state.
     738 * On completion it will be in the VUSB_DEVICE_STATE_DEFAULT state if successful,
     739 * or in the VUSB_DEVICE_STATE_DETACHED state if the rest failed.
     740 * -- internal stuff, move it --
     741 *
     742 * @returns VBox status code.
     743 * @param   pInterface      Pointer to the device interface structure.
     744 * @param   fResetOnLinux   Set if we can permit a real reset and a potential logical
     745 *                          device reconnect on linux hosts.
     746 * @param   pfnDone         Pointer to the completion routine. If NULL a synchronous
     747 *                          reset  is preformed not respecting the 10ms.
     748 * @param   pvUser          User argument to the completion routine.
     749 * @param   pVM             Pointer to the VM handle if callback in EMT is required. (optional)
     750 */
     751DECLINLINE(int) VUSBIDevReset(PVUSBIDEVICE pInterface, bool fResetOnLinux, PFNVUSBRESETDONE pfnDone, void *pvUser, PVM pVM)
     752{
     753    return pInterface->pfnReset(pInterface, fResetOnLinux, pfnDone, pvUser, pVM);
     754}
     755
     756/**
     757 * Powers on the device.
     758 *
     759 * @returns VBox status code.
     760 * @param   pInterface      Pointer to the device interface structure.
     761 */
     762DECLINLINE(int) VUSBIDevPowerOn(PVUSBIDEVICE pInterface)
     763{
     764    return pInterface->pfnPowerOn(pInterface);
     765}
     766
     767/**
     768 * Powers off the device.
     769 *
     770 * @returns VBox status code.
     771 * @param   pInterface      Pointer to the device interface structure.
     772 */
     773DECLINLINE(int) VUSBIDevPowerOff(PVUSBIDEVICE pInterface)
     774{
     775    return pInterface->pfnPowerOff(pInterface);
     776}
     777
     778/**
     779 * Get the state of the device.
     780 *
     781 * @returns Device state.
     782 * @param   pInterface      Pointer to the device interface structure.
     783 */
     784DECLINLINE(VUSBDEVICESTATE) VUSBIDevGetState(PVUSBIDEVICE pInterface)
     785{
     786    return pInterface->pfnGetState(pInterface);
     787}
     788#endif /* IN_RING3 */
     789
     790#endif /* ! RDESKTOP */
     791
    27792/** @name URB
    28793 * @{ */
     
    35800    /** Transer was ok. */
    36801    VUSBSTATUS_OK = 0,
    37 #define VUSB_XFER_OK    VUSBSTATUS_OK
    38802    /** Transfer stalled, endpoint halted. */
    39803    VUSBSTATUS_STALL,
    40 #define VUSB_XFER_STALL VUSBSTATUS_STALL
    41804    /** Device not responding. */
    42805    VUSBSTATUS_DNR,
    43 #define VUSB_XFER_DNR   VUSBSTATUS_DNR
    44806    /** CRC error. */
    45807    VUSBSTATUS_CRC,
    46 #define VUSB_XFER_CRC   VUSBSTATUS_CRC
    47     /** Underflow error. */
    48     VUSBSTATUS_UNDERFLOW,
     808    /** Data overrun error. */
     809    VUSBSTATUS_DATA_UNDERRUN,
     810    /** Data overrun error. */
     811    VUSBSTATUS_DATA_OVERRUN,
     812    /** The isochronous buffer hasn't been touched. */
     813    VUSBSTATUS_NOT_ACCESSED,
    49814    /** Invalid status. */
    50815    VUSBSTATUS_INVALID = 0x7f
     
    59824    /** Control message. Used to represent a single control transfer. */
    60825    VUSBXFERTYPE_CTRL = 0,
    61 #define VUSB_TRANSFER_TYPE_CTRL VUSBXFERTYPE_CTRL
    62826    /* Isochronous transfer. */
    63827    VUSBXFERTYPE_ISOC,
    64 #define VUSB_TRANSFER_TYPE_ISOC VUSBXFERTYPE_ISOC
    65828    /** Bulk transfer. */
    66829    VUSBXFERTYPE_BULK,
    67 #define VUSB_TRANSFER_TYPE_BULK VUSBXFERTYPE_BULK
    68830    /** Interrupt transfer. */
    69831    VUSBXFERTYPE_INTR,
    70 #define VUSB_TRANSFER_TYPE_INTR VUSBXFERTYPE_INTR
    71832    /** Complete control message. Used to represent an entire control message. */
    72833    VUSBXFERTYPE_MSG,
    73 #define VUSB_TRANSFER_TYPE_MSG  VUSBXFERTYPE_MSG
    74834    /** Invalid transfer type. */
    75835    VUSBXFERTYPE_INVALID = 0x7f
     
    90850    /** Out - Host to device. */
    91851    VUSBDIRECTION_OUT = 2,
    92 #define VUSB_DIRECTION_OUT      VUSBDIRECTION_OUT
     852#define VUSB_DIRECTION_OUT  VUSBDIRECTION_OUT
    93853    /** Invalid direction */
    94854    VUSBDIRECTION_INVALID = 0x7f
     
    125885
    126886/**
     887 * Information about a isochronous packet.
     888 */
     889typedef struct VUSBURBISOCPKT
     890{
     891    /** The size of the packet.
     892     * IN: The packet size. I.e. the number of bytes to the next packet or end of buffer.
     893     * OUT: The actual size transfered. */
     894    uint16_t        cb;
     895    /** The offset of the packet. (Relative to VUSBURB::abData[0].)
     896     * OUT: This can be changed by the USB device if it does some kind of buffer squeezing. */
     897    uint16_t        off;
     898    /** The status of the transfer.
     899     * IN: VUSBSTATUS_INVALID
     900     * OUT: VUSBSTATUS_INVALID if nothing was done, otherwise the correct status. */
     901    VUSBSTATUS      enmStatus;
     902} VUSBURBISOCPKT;
     903/** Pointer to a isochronous packet. */
     904typedef VUSBURBISOCPKT *PVUSBURBISOCPTK;
     905/** Pointer to a const isochronous packet. */
     906typedef const VUSBURBISOCPKT *PCVUSBURBISOCPKT;
     907
     908/**
    127909 * Asynchronous USB request descriptor
    128910 */
     
    133915    /** The USR state. */
    134916    VUSBURBSTATE    enmState;
    135 
    136     /* Private fields not accessed by the backend. */
    137     PVUSBURB        next;
    138     PVUSBURB        prev;
     917    /** URB description, can be null. intended for logging. */
     918    char           *pszDesc;
     919
     920#ifdef RDESKTOP
     921    /** The next URB in rdesktop-vrdp's linked list */
     922    PVUSBURB        pNext;
     923    /** The previous URB in rdesktop-vrdp's linked list */
     924    PVUSBURB        pPrev;
     925    /** The vrdp handle for the URB */
    139926    uint32_t        handle;
     927    /** Pointer used to find the usb proxy device */
     928    struct VUSBDEV *pDev;
     929#endif
    140930
    141931    /** The VUSB data. */
     
    148938        /** Pointer to the original for control messages. */
    149939        PVUSBURB        pCtrlUrb;
     940        /** Pointer to the VUSB device.
     941         * This may be NULL if the destination address is invalid. */
     942        struct VUSBDEV *pDev;
    150943        /** Sepcific to the pfnFree function. */
    151944        void           *pvFreeCtx;
     945        /**
     946         * Callback which will free the URB once it's reaped and completed.
     947         * @param   pUrb    The URB.
     948         */
     949        DECLCALLBACKMEMBER(void, pfnFree)(PVUSBURB pUrb);
    152950        /** Submit timestamp. (logging only) */
    153951        uint64_t        u64SubmitTS;
     
    162960    {
    163961        /** The endpoint descriptor address. */
    164         uint32_t        EdAddr;
     962        RTGCPHYS32      EdAddr;
    165963        /** Number of Tds in the array. */
    166964        uint32_t        cTds;
     
    168966        struct VUSBURBHCITD
    169967        {
     968            /** Type of TD (private) */
     969            uint32_t        TdType;
    170970            /** The address of the */
    171             uint32_t        TdAddr;
     971            RTGCPHYS32      TdAddr;
    172972            /** A copy of the TD. */
    173             uint32_t        TdCopy[4];
     973            uint32_t        TdCopy[16];
    174974        }              *paTds;
    175975        /** URB chain pointer. */
    176976        PVUSBURB        pNext;
    177         /** When this URB was created. (logging only) */
     977        /** When this URB was created.
     978         * (Used for isochronous frames and for logging.) */
    178979        uint32_t        u32FrameNo;
    179980        /** Flag indicating that the TDs have been unlinked. */
     
    190991    } Dev;
    191992
    192     /** The device - can be NULL untill submit is attempted.
    193      * This is set when allocating the URB. */
    194     struct VUSBDEV *pDev;
     993#ifndef RDESKTOP
     994    /** The USB device instance this belongs to.
     995     * This is NULL if the device address is invalid, in which case this belongs to the hub. */
     996    PPDMUSBINS      pUsbIns;
     997#endif
    195998    /** The device address.
    196999     * This is set at allocation time. */
     
    1981001
    1991002    /** The endpoint.
    200      * IN: Must be set before submitting the URB. */
     1003     * IN: Must be set before submitting the URB.
     1004     * @remark This does not have the high bit (direction) set! */
    2011005    uint8_t         EndPt;
    2021006    /** The transfer type.
     
    2121016     * OUT: This is set when reaping the URB. */
    2131017    VUSBSTATUS      enmStatus;
     1018
     1019    /** The number of isochronous packets describe in aIsocPkts.
     1020     * This is ignored when enmType isn't VUSBXFERTYPE_ISOC. */
     1021    uint32_t        cIsocPkts;
     1022    /** The iso packets within abData.
     1023     * This is ignored when enmType isn't VUSBXFERTYPE_ISOC. */
     1024    VUSBURBISOCPKT  aIsocPkts[8];
     1025
    2141026    /** The message length.
    2151027     * IN: The amount of data to send / receive - set at allocation time.
     
    2231035
    2241036/** The magic value of a valid VUSBURB. (Murakami Haruki) */
    225 #define VUSBURB_MAGIC   0x19490112
     1037#define VUSBURB_MAGIC       UINT32_C(0x19490112)
    2261038
    2271039/** @} */
     1040
     1041
     1042/** @} */
     1043
     1044RT_C_DECLS_END
     1045
     1046#endif
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette