VirtualBox

Ignore:
Timestamp:
Nov 5, 2010 7:35:30 PM (14 years ago)
Author:
vboxsync
Message:

FreeBSD: USB support, contributed by Hans Petter Selasky (thanks)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/USB/freebsd/USBProxyDevice-freebsd.cpp

    r33595 r33813  
    66/*
    77 * Copyright (C) 2006-2007 Oracle Corporation
     8 * Copyright (C) 2010 Hans Petter Selasky
    89 *
    910 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1920*   Header Files                                                               *
    2021*******************************************************************************/
    21 #define LOG_GROUP LOG_GROUP_DRV_USBPROXY
     22#define    LOG_GROUP LOG_GROUP_DRV_USBPROXY
    2223#ifdef VBOX
    23 # include <iprt/stdint.h>
     24#include <iprt/stdint.h>
    2425#endif
    2526#include <sys/types.h>
     
    5455
    5556/** Maximum endpoints supported. */
    56 #define USBFBSD_MAXENDPOINTS       32
    57 #define USBFBSD_EPADDR_NUM_MASK  0x0F
    58 #define USBFBSD_EPADDR_DIR_MASK  0x80
    59 #define USBPROXY_FREEBSD_NO_ENTRY_FREE ((unsigned)~0)
     57#define USBFBSD_MAXENDPOINTS 127
     58#define USBFBSD_MAXFRAMES 56
     59
    6060/** This really needs to be defined in vusb.h! */
    6161#ifndef VUSB_DIR_TO_DEV
     
    6666*   Structures and Typedefs                                                    *
    6767*******************************************************************************/
    68 typedef struct VUSBURBFBSD
    69 {
     68typedef struct USBENDPOINTFBSD
     69{
     70    /** Flag whether it is opened. */
     71    bool     fOpen;
     72    /** Flag whether it is cancelling. */
     73    bool     fCancelling;
     74    /** Buffer pointers. */
     75    void    *apvData[USBFBSD_MAXFRAMES];
     76    /** Buffer lengths. */
     77    uint32_t acbData[USBFBSD_MAXFRAMES];
     78    /** Initial buffer length. */
     79    uint32_t cbData0;
    7080    /** Pointer to the URB. */
    71     PVUSBURB    pUrb;
    72     /** Buffer pointers. */
    73     void       *apvData[2];
    74     /** Buffer lengths. */
    75     uint32_t    acbData[2];
    76 } VUSBURBFBSD, *PVUSBURBFBSD;
    77 
    78 typedef struct USBENDPOINTFBSD
    79 {
    80     /** Flag whether it is opened. */
    81     bool        fOpen;
    82     /** Index in the endpoint list. */
    83     unsigned    iEndpoint;
    84     /** Associated endpoint. */
    85     struct usb_fs_endpoint *pXferEndpoint;
     81    PVUSBURB pUrb;
     82    /** Copy of endpoint number. */
     83    unsigned iEpNum;
     84    /** Maximum transfer length. */
     85    unsigned cMaxIo;
     86    /** Maximum frame count. */
     87    unsigned cMaxFrames;
    8688} USBENDPOINTFBSD, *PUSBENDPOINTFBSD;
    8789
     
    9294{
    9395    /** The open file. */
    94     RTFILE                  File;
    95     /** Critical section protecting the two lists. */
    96     RTCRITSECT              CritSect;
    97     /** Pointer to the array of USB endpoints. */
    98     struct usb_fs_endpoint *paXferEndpoints;
    99     /** Pointer to the array of URB structures.
    100      * They entries must be in sync with the above array. */
    101     PVUSBURBFBSD            paUrbs;
    102     /** Number of entries in both arrays. */
    103     unsigned                cXferEndpoints;
    104     /** Pointer to the Fifo containing the indexes for free Xfer
    105      * endpoints. */
    106     unsigned               *paXferFree;
    107     /** Index of the next free entry to write to. */
    108     unsigned                iXferFreeNextWrite;
    109     /** Index of the next entry to read from. */
    110     unsigned                iXferFreeNextRead;
    111     /** Status of opened endpoints. */
    112     USBENDPOINTFBSD         aEpOpened[USBFBSD_MAXENDPOINTS];
    113     /** The list of landed FreeBSD URBs. Doubly linked.
    114      * Only the split head will appear in this list. */
    115     PVUSBURB                pTaxingHead;
    116     /** The tail of the landed FreeBSD URBs. */
    117     PVUSBURB                pTaxingTail;
     96    RTFILE                 File;
     97    /** Software endpoint structures */
     98    USBENDPOINTFBSD        aSwEndpoint[USBFBSD_MAXENDPOINTS];
     99    /** Flag whether an URB is cancelling. */
     100    bool                   fCancelling;
     101    /** Flag whether initialised or not */
     102    bool                   fInit;
     103    /** Kernel endpoint structures */
     104    struct usb_fs_endpoint aHwEndpoint[USBFBSD_MAXENDPOINTS];
    118105} USBPROXYDEVFBSD, *PUSBPROXYDEVFBSD;
    119106
     
    121108*   Internal Functions                                                         *
    122109*******************************************************************************/
    123 static int usbProxyFreeBSDDoIoCtl(PUSBPROXYDEV pProxyDev, unsigned long iCmd, void *pvArg, bool fHandleNoDev, uint32_t cTries);
    124 static void usbProxFreeBSDUrbUnplugged(PUSBPROXYDEV pProxyDev);
    125 static PUSBENDPOINTFBSD usbProxyFreeBSDEndpointOpen(PUSBPROXYDEV pProxyDev, int Endpoint);
    126110static int usbProxyFreeBSDEndpointClose(PUSBPROXYDEV pProxyDev, int Endpoint);
    127111
     
    137121 * @param   pvArg           The ioctl argument / data.
    138122 * @param   fHandleNoDev    Whether to handle ENXIO.
    139  * @param   cTries          The number of retries. Use UINT32_MAX for (kind of) indefinite retries.
    140123 * @internal
    141124 */
    142 static int usbProxyFreeBSDDoIoCtl(PUSBPROXYDEV pProxyDev, unsigned long iCmd, void *pvArg, bool fHandleNoDev, uint32_t cTries)
     125static int usbProxyFreeBSDDoIoCtl(PUSBPROXYDEV pProxyDev, unsigned long iCmd,
     126                                  void *pvArg, bool fHandleNoDev)
    143127{
    144128    int rc = VINF_SUCCESS;
    145 
    146     PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv;
     129    PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv;
     130
     131    LogFlow(("usbProxyFreeBSDDoIoCtl: iCmd=%#x\n", iCmd));
     132
    147133    do
    148134    {
    149         do
    150         {
    151             rc = ioctl(pDevFBSD->File, iCmd, pvArg);
    152             if (rc >= 0)
    153                 return rc;
    154         } while (errno == EINTR);
    155 
    156         if (errno == ENXIO && fHandleNoDev)
    157         {
    158             usbProxFreeBSDUrbUnplugged(pProxyDev);
    159             Log(("usb-freebsd: ENXIO -> unplugged. pProxyDev=%s\n", pProxyDev->pUsbIns->pszName));
    160             errno = ENODEV;
    161             break;
    162         }
    163         if (errno != EAGAIN)
    164         {
    165             LogFlow(("usbProxyFreeBSDDoIoCtl returned %Rrc\n", RTErrConvertFromErrno(errno)));
    166             break;
    167         }
    168     } while (cTries-- > 0);
     135        rc = ioctl(pDevFBSD->File, iCmd, pvArg);
     136        if (rc >= 0)
     137            return VINF_SUCCESS;
     138    } while (errno == EINTR);
     139
     140    if (errno == ENXIO && fHandleNoDev)
     141    {
     142        Log(("usbProxyFreeBSDDoIoCtl: ENXIO -> unplugged. pProxyDev=%s\n",
     143             pProxyDev->pUsbIns->pszName));
     144        errno = ENODEV;
     145    }
     146    else if (errno != EAGAIN)
     147    {
     148        LogFlow(("usbProxyFreeBSDDoIoCtl: Returned %d. pProxyDev=%s\n",
     149                 errno, pProxyDev->pUsbIns->pszName));
     150    }
     151    return RTErrConvertFromErrno(errno);
     152}
     153
     154/**
     155 * Init USB subsystem.
     156 */
     157static int usbProxyFreeBSDFsInit(PUSBPROXYDEV pProxyDev)
     158{
     159    struct usb_fs_init UsbFsInit;
     160    PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv;
     161    int rc;
     162
     163    LogFlow(("usbProxyFreeBSDFsInit: pProxyDev=%p\n", (void *)pProxyDev));
     164
     165    /* Sanity check */
     166    AssertPtrReturn(pDevFBSD, VERR_INVALID_PARAMETER);
     167
     168    if (pDevFBSD->fInit == true)
     169        return VINF_SUCCESS;
     170
     171    /* Zero default */
     172    memset(&UsbFsInit, 0, sizeof(UsbFsInit));
     173
     174    UsbFsInit.pEndpoints = pDevFBSD->aHwEndpoint;
     175    UsbFsInit.ep_index_max = USBFBSD_MAXENDPOINTS;
     176
     177    /* Init USB subsystem */
     178    rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_INIT, &UsbFsInit, false);
     179    if (RT_SUCCESS(rc))
     180        pDevFBSD->fInit = true;
    169181
    170182    return rc;
     
    172184
    173185/**
     186 * Uninit USB subsystem.
     187 */
     188static int usbProxyFreeBSDFsUnInit(PUSBPROXYDEV pProxyDev)
     189{
     190    struct usb_fs_uninit UsbFsUninit;
     191    PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv;
     192    int rc;
     193
     194    LogFlow(("usbProxyFreeBSDFsUnInit: ProxyDev=%p\n", (void *)pProxyDev));
     195
     196    /* Sanity check */
     197    AssertPtrReturn(pDevFBSD, VERR_INVALID_PARAMETER);
     198
     199    if (pDevFBSD->fInit != true)
     200        return VINF_SUCCESS;
     201
     202    /* Close any open endpoints. */
     203    for (unsigned n = 0; n != USBFBSD_MAXENDPOINTS; n++)
     204        usbProxyFreeBSDEndpointClose(pProxyDev, n);
     205
     206    /* Zero default */
     207    memset(&UsbFsUninit, 0, sizeof(UsbFsUninit));
     208
     209    /* Uninit USB subsystem */
     210    rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_UNINIT, &UsbFsUninit, false);
     211    if (RT_SUCCESS(rc))
     212        pDevFBSD->fInit = false;
     213
     214    return rc;
     215}
     216
     217/**
    174218 * Setup a USB request packet.
    175219 */
    176 static void usbProxyFreeBSDSetupReq(struct usb_device_request *pSetupData, uint8_t bmRequestType, uint8_t bRequest,
    177                         uint16_t wValue, uint16_t wIndex, uint16_t wLength)
    178 {
    179     LogFlow(("usbProxyFreeBSDSetupReq: pSetupData=%p bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
    180                 pSetupData, bmRequestType, bRequest, wValue, wIndex, wLength));
     220static void usbProxyFreeBSDSetupReq(struct usb_device_request *pSetupData,
     221                                    uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue,
     222                                    uint16_t wIndex, uint16_t wLength)
     223{
     224    LogFlow(("usbProxyFreeBSDSetupReq: pSetupData=%p bmRequestType=%x "
     225             "bRequest=%x wValue=%x wIndex=%x wLength=%x\n", (void *)pSetupData,
     226             bmRequestType, bRequest, wValue, wIndex, wLength));
    181227
    182228    pSetupData->bmRequestType = bmRequestType;
    183     pSetupData->bRequest      = bRequest;
     229    pSetupData->bRequest = bRequest;
    184230
    185231    /* Handle endianess here. Currently no swapping is needed. */
    186     pSetupData->wValue[0]  = wValue & 0xff;
    187     pSetupData->wValue[1]  = (wValue >> 8) & 0xff;
    188     pSetupData->wIndex[0]  = wIndex & 0xff;
    189     pSetupData->wIndex[1]  = (wIndex >> 8) & 0xff;
    190     pSetupData->wLength[0]  = wLength & 0xff;
    191     pSetupData->wLength[1]  = (wLength >> 8) & 0xff;
    192 //    pSetupData->wIndex  = wIndex;
    193 //    pSetupData->wLength = wLength;
    194 }
    195 
    196 /**
    197  * The device has been unplugged.
    198  * Cancel all in-flight URBs and put them up for reaping.
    199  */
    200 static void usbProxFreeBSDUrbUnplugged(PUSBPROXYDEV pProxyDev)
    201 {
    202     PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv;
    203 
    204     /*
    205      * Shoot down all flying URBs.
    206      */
    207     RTCritSectEnter(&pDevFBSD->CritSect);
    208     pProxyDev->fDetached = true;
    209 
    210 #if 0 /** @todo */
    211     PUSBPROXYURBFBSD pUrbTaxing = NULL;
    212     PUSBPROXYURBFBSD pUrbFBSD = pDevLnx->pInFlightHead;
    213     pDevFBSD->pInFlightHead = NULL;
    214     while (pUrbFBSD)
    215     {
    216         PUSBPROXYURBFBSD pCur = pUrbFBSD;
    217         pUrbFBSD = pUrbFBSD->pNext;
    218 
    219         ioctl(pDevFBSD->File, USBDEVFS_DISCARDURB, &pCur->KUrb);
    220         if (!pCur->KUrb.status)
    221             pCur->KUrb.status = -ENODEV;
    222 
    223         /* insert into the taxing list. */
    224         pCur->pPrev = NULL;
    225         if (    !pCur->pSplitHead
    226             ||  pCur == pCur->pSplitHead)
    227         {
    228             pCur->pNext = pUrbTaxing;
    229             if (pUrbTaxing)
    230                 pUrbTaxing->pPrev = pCur;
    231             pUrbTaxing = pCur;
    232         }
    233         else
    234             pCur->pNext = NULL;
    235     }
    236 
    237     /* Append the URBs we shot down to the taxing queue. */
    238     if (pUrbTaxing)
    239     {
    240         pUrbTaxing->pPrev = pDevFBSD->pTaxingTail;
    241         if (pUrbTaxing->pPrev)
    242             pUrbTaxing->pPrev->pNext = pUrbTaxing;
    243         else
    244             pDevFBSD->pTaxingTail = pDevFBSD->pTaxingHead = pUrbTaxing;
    245     }
    246 #endif
    247     RTCritSectLeave(&pDevFBSD->CritSect);
    248 }
    249 
    250 DECLINLINE(void) usbProxyFreeBSDSetEntryFree(PUSBPROXYDEVFBSD pProxyDev, unsigned iEntry)
    251 {
    252     pProxyDev->paXferFree[pProxyDev->iXferFreeNextWrite] = iEntry;
    253     pProxyDev->iXferFreeNextWrite++;
    254     pProxyDev->iXferFreeNextWrite %= (pProxyDev->cXferEndpoints+1);
    255 }
    256 
    257 DECLINLINE(unsigned) usbProxyFreeBSDGetEntryFree(PUSBPROXYDEVFBSD pProxyDev)
    258 {
    259     unsigned iEntry;
    260 
    261     if (pProxyDev->iXferFreeNextWrite != pProxyDev->iXferFreeNextRead)
    262     {
    263         iEntry = pProxyDev->paXferFree[pProxyDev->iXferFreeNextRead];
    264         pProxyDev->iXferFreeNextRead++;
    265         pProxyDev->iXferFreeNextRead %= (pProxyDev->cXferEndpoints+1);
    266     }
    267     else
    268         iEntry = USBPROXY_FREEBSD_NO_ENTRY_FREE;
    269 
    270     return iEntry;
    271 }
    272 
    273 static PUSBENDPOINTFBSD usbProxyFreeBSDEndpointOpen(PUSBPROXYDEV pProxyDev, int Endpoint)
    274 {
    275     LogFlow(("usbProxyFreeBSDEndpointOpen: pProxyDev=%p Endpoint=%d\n", pProxyDev, Endpoint));
    276 
    277     int EndPtIndex = (Endpoint & USBFBSD_EPADDR_NUM_MASK) + ((Endpoint & USBFBSD_EPADDR_DIR_MASK) ? USBFBSD_MAXENDPOINTS / 2 : 0);
    278     PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv;
    279     PUSBENDPOINTFBSD pEndpointFBSD = &pDevFBSD->aEpOpened[EndPtIndex];
     232    pSetupData->wValue[0] = wValue & 0xff;
     233    pSetupData->wValue[1] = (wValue >> 8) & 0xff;
     234    pSetupData->wIndex[0] = wIndex & 0xff;
     235    pSetupData->wIndex[1] = (wIndex >> 8) & 0xff;
     236    pSetupData->wLength[0] = wLength & 0xff;
     237    pSetupData->wLength[1] = (wLength >> 8) & 0xff;
     238}
     239
     240static int usbProxyFreeBSDEndpointOpen(PUSBPROXYDEV pProxyDev, int Endpoint, bool fIsoc, int index)
     241{
     242    PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv;
     243    PUSBENDPOINTFBSD pEndpointFBSD;
    280244    struct usb_fs_endpoint *pXferEndpoint;
    281 
    282     AssertMsg(EndPtIndex < USBFBSD_MAXENDPOINTS, ("Endpoint index exceeds limit %d\n", EndPtIndex));
    283 
    284     if (!pEndpointFBSD->fOpen)
    285     {
    286         struct usb_fs_open UsbFsOpen;
    287 
    288         pEndpointFBSD->iEndpoint = usbProxyFreeBSDGetEntryFree(pDevFBSD);
    289         if (pEndpointFBSD->iEndpoint == USBPROXY_FREEBSD_NO_ENTRY_FREE)
    290             return NULL;
    291 
    292         LogFlow(("usbProxyFreeBSDEndpointOpen: ep_index=%d\n", pEndpointFBSD->iEndpoint));
    293 
    294         UsbFsOpen.ep_index    = pEndpointFBSD->iEndpoint;
    295         UsbFsOpen.ep_no       = Endpoint;
    296         UsbFsOpen.max_bufsize = 256 * _1K; /* Hardcoded assumption about the URBs we get. */
    297         UsbFsOpen.max_frames  = 2;
    298 
    299         int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_OPEN, &UsbFsOpen, true, UINT32_MAX);
    300         if (rc)
    301             return NULL;
    302 
    303         pEndpointFBSD->fOpen = true;
    304         pEndpointFBSD->pXferEndpoint = &pDevFBSD->paXferEndpoints[pEndpointFBSD->iEndpoint];
    305     }
    306     else
    307     {
    308         AssertMsgReturn(!pDevFBSD->paUrbs[pEndpointFBSD->iEndpoint].pUrb, ("Endpoint is busy"), NULL);
    309         pEndpointFBSD->pXferEndpoint = &pDevFBSD->paXferEndpoints[pEndpointFBSD->iEndpoint];
    310     }
    311 
    312     return pEndpointFBSD;
    313 }
    314 
     245    struct usb_fs_open UsbFsOpen;
     246    int rc;
     247
     248    LogFlow(("usbProxyFreeBSDEndpointOpen: pProxyDev=%p Endpoint=%d\n",
     249             (void *)pProxyDev, Endpoint));
     250
     251    for (; index < USBFBSD_MAXENDPOINTS; index++)
     252    {
     253        pEndpointFBSD = &pDevFBSD->aSwEndpoint[index];
     254        if (pEndpointFBSD->fCancelling)
     255            continue;
     256        if (   pEndpointFBSD->fOpen
     257            && !pEndpointFBSD->pUrb
     258            && (int)pEndpointFBSD->iEpNum == Endpoint)
     259            return index;
     260    }
     261
     262    if (index == USBFBSD_MAXENDPOINTS)
     263    {
     264        for (index = 0; index != USBFBSD_MAXENDPOINTS; index++)
     265        {
     266            pEndpointFBSD = &pDevFBSD->aSwEndpoint[index];
     267            if (pEndpointFBSD->fCancelling)
     268                continue;
     269            if (!pEndpointFBSD->fOpen)
     270                break;
     271        }
     272        if (index == USBFBSD_MAXENDPOINTS)
     273            return -1;
     274    }
     275    /* set ppBuffer and pLength */
     276
     277    pXferEndpoint = &pDevFBSD->aHwEndpoint[index];
     278    pXferEndpoint->ppBuffer = &pEndpointFBSD->apvData[0];
     279    pXferEndpoint->pLength = &pEndpointFBSD->acbData[0];
     280
     281    LogFlow(("usbProxyFreeBSDEndpointOpen: ep_index=%d ep_num=%d\n",
     282             index, Endpoint));
     283
     284    memset(&UsbFsOpen, 0, sizeof(UsbFsOpen));
     285
     286    UsbFsOpen.ep_index = index;
     287    UsbFsOpen.ep_no = Endpoint;
     288    UsbFsOpen.max_bufsize = 256 * 1024;
     289    /* Hardcoded assumption about the URBs we get. */
     290
     291    UsbFsOpen.max_frames = fIsoc ? USBFBSD_MAXFRAMES : 2;
     292
     293    rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_OPEN, &UsbFsOpen, true);
     294    if (RT_FAILURE(rc))
     295    {
     296        if (rc == VERR_RESOURCE_BUSY)
     297            LogFlow(("usbProxyFreeBSDEndpointOpen: EBUSY\n"));
     298
     299        return -1;
     300    }
     301    pEndpointFBSD->fOpen = true;
     302    pEndpointFBSD->pUrb = NULL;
     303    pEndpointFBSD->iEpNum = Endpoint;
     304    pEndpointFBSD->cMaxIo = UsbFsOpen.max_bufsize;
     305    pEndpointFBSD->cMaxFrames = UsbFsOpen.max_frames;
     306
     307    return index;
     308}
     309
     310/**
     311 * Close an endpoint.
     312 *
     313 * @returns VBox status code.
     314 */
    315315static int usbProxyFreeBSDEndpointClose(PUSBPROXYDEV pProxyDev, int Endpoint)
    316316{
    317     LogFlow(("usbProxyFreeBSDEndpointClose: pProxyDev=%p Endpoint=%d\n", pProxyDev, Endpoint));
    318 
    319     AssertMsg(Endpoint < USBFBSD_MAXENDPOINTS, ("Endpoint index exceeds limit %d\n", Endpoint));
    320 
    321     int EndPtIndex = (Endpoint & USBFBSD_EPADDR_NUM_MASK) + ((Endpoint & USBFBSD_EPADDR_DIR_MASK) ? USBFBSD_MAXENDPOINTS / 2 : 0);
    322     PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv;
    323     PUSBENDPOINTFBSD pEndpointFBSD = &pDevFBSD->aEpOpened[EndPtIndex];
    324 
     317    PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv;
     318    PUSBENDPOINTFBSD pEndpointFBSD = &pDevFBSD->aSwEndpoint[Endpoint];
     319    struct usb_fs_close UsbFsClose;
     320    int rc = VINF_SUCCESS;
     321
     322    LogFlow(("usbProxyFreeBSDEndpointClose: pProxyDev=%p Endpoint=%d\n",
     323             (void *)pProxyDev, Endpoint));
     324
     325    /* check for cancelling */
     326    if (pEndpointFBSD->pUrb != NULL)
     327    {
     328        pEndpointFBSD->fCancelling = true;
     329        pDevFBSD->fCancelling = true;
     330    }
     331
     332    /* check for opened */
    325333    if (pEndpointFBSD->fOpen)
    326334    {
    327         struct usb_fs_close UsbFsClose;
    328 
    329         AssertMsgReturn(!pDevFBSD->paUrbs[pEndpointFBSD->iEndpoint].pUrb, ("Endpoint is busy"), NULL);
    330 
    331         UsbFsClose.ep_index = pEndpointFBSD->iEndpoint;
    332 
    333         int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_CLOSE, &UsbFsClose, true, UINT32_MAX);
    334         if (rc)
    335         {
    336             LogFlow(("usbProxyFreeBSDEndpointClose: failed rc=%d errno=%Rrc\n", rc, RTErrConvertFromErrno(errno)));
    337             return RTErrConvertFromErrno(errno);
    338         }
    339 
    340         usbProxyFreeBSDSetEntryFree(pDevFBSD, pEndpointFBSD->iEndpoint);
    341335        pEndpointFBSD->fOpen = false;
    342     }
    343 
    344     return VINF_SUCCESS;
     336
     337        /* Zero default */
     338        memset(&UsbFsClose, 0, sizeof(UsbFsClose));
     339
     340        /* Set endpoint index */
     341        UsbFsClose.ep_index = Endpoint;
     342
     343        /* Close endpoint */
     344        rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_CLOSE, &UsbFsClose, true);
     345    }
     346    return rc;
    345347}
    346348
     
    357359 * @param   pvBackend       Backend specific pointer, unused for the linux backend.
    358360 */
    359 static int usbProxyFreeBSDOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, void *pvBackend)
    360 {
     361static int usbProxyFreeBSDOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress,
     362                               void *pvBackend)
     363{
     364    int rc;
     365
    361366    LogFlow(("usbProxyFreeBSDOpen: pProxyDev=%p pszAddress=%s\n", pProxyDev, pszAddress));
    362367
     
    365370     */
    366371    RTFILE File;
    367     int rc = RTFileOpen(&File, pszAddress, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
     372
     373    rc = RTFileOpen(&File, pszAddress, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
    368374    if (RT_SUCCESS(rc))
    369375    {
    370376        /*
    371          * Allocate and initialize the linux backend data.
    372          */
    373         PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)RTMemAllocZ(sizeof(USBPROXYDEVFBSD));
     377             * Allocate and initialize the linux backend data.
     378             */
     379        PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)
     380        RTMemAllocZ(sizeof(USBPROXYDEVFBSD));
     381
    374382        if (pDevFBSD)
    375383        {
    376384            pDevFBSD->File = File;
    377             rc = RTCritSectInit(&pDevFBSD->CritSect);
     385            pProxyDev->Backend.pv = pDevFBSD;
     386
     387            rc = usbProxyFreeBSDFsInit(pProxyDev);
    378388            if (RT_SUCCESS(rc))
    379389            {
    380                 unsigned cTransfersMax = 127; /* Maximum in the kernel atm. */
    381 
    382                 /* Allocate arrays for data transfers. */
    383                 pDevFBSD->paXferEndpoints = (struct usb_fs_endpoint *)RTMemAllocZ(cTransfersMax * sizeof(struct usb_fs_endpoint));
    384                 pDevFBSD->paUrbs          = (PVUSBURBFBSD)RTMemAllocZ(cTransfersMax * sizeof(VUSBURBFBSD));
    385                 pDevFBSD->paXferFree      = (unsigned *)RTMemAllocZ((cTransfersMax + 1) * sizeof(unsigned));
    386                 pDevFBSD->cXferEndpoints  = cTransfersMax;
    387 
    388                 if (pDevFBSD->paXferEndpoints && pDevFBSD->paUrbs && pDevFBSD->paXferFree)
    389                 {
    390                     /* Initialize the kernel side. */
    391                     struct usb_fs_init UsbFsInit;
    392 
    393                     UsbFsInit.pEndpoints   = pDevFBSD->paXferEndpoints;
    394                     UsbFsInit.ep_index_max = cTransfersMax;
    395                     rc = ioctl(File, USB_FS_INIT, &UsbFsInit);
    396                     if (!rc)
    397                     {
    398                         for (unsigned i = 0; i < cTransfersMax; i++)
    399                             usbProxyFreeBSDSetEntryFree(pDevFBSD, i);
    400 
    401                         for (unsigned i= 0; i < USBFBSD_MAXENDPOINTS; i++)
    402                             pDevFBSD->aEpOpened[i].fOpen = false;
    403 
    404                         pProxyDev->Backend.pv = pDevFBSD;
    405 
    406                         LogFlow(("usbProxyFreeBSDOpen(%p, %s): returns successfully File=%d iActiveCfg=%d\n",
    407                                  pProxyDev, pszAddress, pDevFBSD->File, pProxyDev->iActiveCfg));
    408 
    409                         return VINF_SUCCESS;
    410                     }
    411                     else
    412                         rc = RTErrConvertFromErrno(errno);
    413                 }
    414                 else
    415                     rc = VERR_NO_MEMORY;
    416 
    417                 if (pDevFBSD->paXferEndpoints)
    418                     RTMemFree(pDevFBSD->paXferEndpoints);
    419                 if (pDevFBSD->paUrbs)
    420                     RTMemFree(pDevFBSD->paUrbs);
    421                 if (pDevFBSD->paXferFree)
    422                     RTMemFree(pDevFBSD->paXferFree);
     390                LogFlow(("usbProxyFreeBSDOpen(%p, %s): returns "
     391                         "successfully File=%d iActiveCfg=%d\n",
     392                         pProxyDev, pszAddress,
     393                         pDevFBSD->File, pProxyDev->iActiveCfg));
     394
     395                return VINF_SUCCESS;
    423396            }
    424397
     
    427400        else
    428401            rc = VERR_NO_MEMORY;
     402
    429403        RTFileClose(File);
    430404    }
     
    432406        rc = VERR_VUSB_USBFS_PERMISSION;
    433407
    434     Log(("usbProxyFreeBSDOpen(%p, %s) failed, rc=%Rrc!\n", pProxyDev, pszAddress, rc));
     408    Log(("usbProxyFreeBSDOpen(%p, %s) failed, rc=%d!\n",
     409         pProxyDev, pszAddress, rc));
     410
    435411    pProxyDev->Backend.pv = NULL;
    436412
    437413    NOREF(pvBackend);
    438414    return rc;
    439 
    440     return VINF_SUCCESS;
    441415}
    442416
     
    451425static int usbProxyFreeBSDInit(PUSBPROXYDEV pProxyDev)
    452426{
    453     LogFlow(("usbProxyFreeBSDInit: pProxyDev=%s\n", pProxyDev->pUsbIns->pszName));
    454     PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv;
     427    PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv;
     428    int rc;
     429
     430    LogFlow(("usbProxyFreeBSDInit: pProxyDev=%s\n",
     431             pProxyDev->pUsbIns->pszName));
    455432
    456433    /* Retrieve current active configuration. */
    457     int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_GET_CONFIG, &pProxyDev->iActiveCfg, true, UINT32_MAX);
    458     if (RT_FAILURE(rc))
    459     {
     434    rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_GET_CONFIG,
     435                                &pProxyDev->iActiveCfg, true);
     436    if (RT_FAILURE(rc) || pProxyDev->iActiveCfg == 255)
     437    {
     438        pProxyDev->cIgnoreSetConfigs = 0;
    460439        pProxyDev->iActiveCfg = -1;
    461         return rc;
     440    }
     441    else
     442    {
     443        pProxyDev->cIgnoreSetConfigs = 1;
     444        pProxyDev->iActiveCfg++;
    462445    }
    463446
    464447    Log(("usbProxyFreeBSDInit: iActiveCfg=%d\n", pProxyDev->iActiveCfg));
    465     pProxyDev->cIgnoreSetConfigs = 1;
    466     pProxyDev->iActiveCfg++;
    467 
    468     return VINF_SUCCESS;
    469 }
    470 
     448
     449    return rc;
     450}
    471451
    472452/**
     
    475455static void usbProxyFreeBSDClose(PUSBPROXYDEV pProxyDev)
    476456{
     457    PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv;
     458
    477459    LogFlow(("usbProxyFreeBSDClose: pProxyDev=%s\n", pProxyDev->pUsbIns->pszName));
    478     PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv;
    479     Assert(pDevFBSD);
    480     if (!pDevFBSD)
    481         return;
    482 
    483     RTCritSectDelete(&pDevFBSD->CritSect);
    484 
    485     struct usb_fs_uninit UsbFsUninit;
    486     UsbFsUninit.dummy = 0;
    487 
    488     int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_UNINIT, &UsbFsUninit, false, 1);
    489     AssertMsg(!rc, ("Freeing kernel resources failed rc=%Rrc\n", RTErrConvertFromErrno(errno)));
    490 
    491     if (pDevFBSD->paXferEndpoints)
    492         RTMemFree(pDevFBSD->paXferEndpoints);
    493     if (pDevFBSD->paUrbs)
    494         RTMemFree(pDevFBSD->paUrbs);
    495     if (pDevFBSD->paXferFree)
    496         RTMemFree(pDevFBSD->paXferFree);
     460
     461    /* sanity check */
     462    AssertPtrReturnVoid(pDevFBSD);
     463
     464    usbProxyFreeBSDFsUnInit(pProxyDev);
    497465
    498466    RTFileClose(pDevFBSD->File);
     467
    499468    pDevFBSD->File = NIL_RTFILE;
    500469
    501470    RTMemFree(pDevFBSD);
     471
    502472    pProxyDev->Backend.pv = NULL;
    503473
    504474    LogFlow(("usbProxyFreeBSDClose: returns\n"));
    505475}
    506 
    507476
    508477/**
     
    514483static int usbProxyFreeBSDReset(PUSBPROXYDEV pProxyDev, bool fResetOnFreeBSD)
    515484{
    516     LogFlow(("usbProxyFreeBSDReset: pProxyDev=%s\n", pProxyDev->pUsbIns->pszName));
    517     PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv;
    518 
    519     /* Close any open endpoints. */
    520     for (unsigned i = 0; i < USBFBSD_MAXENDPOINTS; i++)
    521         usbProxyFreeBSDEndpointClose(pProxyDev, i);
    522 
    523     /* We need to release kernel resources first. */
    524     struct usb_fs_uninit UsbFsUninit;
    525     UsbFsUninit.dummy = 0;
    526 
    527     int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_UNINIT, &UsbFsUninit, false, 1);
    528     AssertMsg(!rc, ("Freeing kernel resources failed rc=%Rrc\n", RTErrConvertFromErrno(errno)));
    529 
    530     /* Resetting is not possible from a normal user account */
    531 #if 0
    532     int iUnused = 0;
    533     rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_DEVICEENUMERATE, &iUnused, true, UINT32_MAX);
    534     if (rc)
    535         return RTErrConvertFromErrno(errno);
    536 #endif
    537 
    538     /* Allocate kernel resources again. */
    539     struct usb_fs_init UsbFsInit;
    540 
    541     UsbFsInit.pEndpoints   = pDevFBSD->paXferEndpoints;
    542     UsbFsInit.ep_index_max = pDevFBSD->cXferEndpoints;
    543     rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_INIT, &UsbFsInit, true, UINT32_MAX);
    544     if (!rc)
    545     {
    546         /* Retrieve current active configuration. */
    547         rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_GET_CONFIG, &pProxyDev->iActiveCfg, true, UINT32_MAX);
    548         if (rc)
    549         {
    550             pProxyDev->iActiveCfg = -1;
    551             rc = RTErrConvertFromErrno(errno);
    552         }
    553         else
    554         {
    555             pProxyDev->cIgnoreSetConfigs = 2;
    556             pProxyDev->iActiveCfg++;
    557         }
    558     }
    559     else
    560         rc = RTErrConvertFromErrno(errno);
    561 
    562     Log(("usbProxyFreeBSDReset: iActiveCfg=%d\n", pProxyDev->iActiveCfg));
     485    PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv;
     486    int iParm;
     487    int rc = VINF_SUCCESS;
     488
     489    LogFlow(("usbProxyFreeBSDReset: pProxyDev=%s\n",
     490             pProxyDev->pUsbIns->pszName));
     491
     492    if (!fResetOnFreeBSD)
     493        goto done;
     494
     495    /* We need to release kernel ressources first. */
     496    rc = usbProxyFreeBSDFsUnInit(pProxyDev);
     497    if (RT_FAILURE(rc))
     498        goto done;
     499
     500    /* Resetting is only possible as super-user, ignore any failures: */
     501    iParm = 0;
     502    rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_DEVICEENUMERATE, &iParm, true);
     503    if (RT_FAILURE(rc))
     504    {
     505        /* Set the config instead of bus reset */
     506        iParm = 255;
     507        rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_SET_CONFIG, &iParm, true);
     508        if (RT_SUCCESS(rc))
     509        {
     510            iParm = 0;
     511            rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_SET_CONFIG, &iParm, true);
     512        }
     513    }
     514    usleep(10000); /* nice it! */
     515
     516    /* Allocate kernel ressources again. */
     517    rc = usbProxyFreeBSDFsInit(pProxyDev);
     518    if (RT_FAILURE(rc))
     519        goto done;
     520
     521    /* Retrieve current active configuration. */
     522    rc = usbProxyFreeBSDInit(pProxyDev);
     523
     524done:
     525    pProxyDev->cIgnoreSetConfigs = 2;
    563526
    564527    return rc;
    565528}
    566 
    567529
    568530/**
     
    578540static int usbProxyFreeBSDSetConfig(PUSBPROXYDEV pProxyDev, int iCfg)
    579541{
    580     PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv;
    581 
    582     LogFlow(("usbProxyFreeBSDSetConfig: pProxyDev=%s cfg=%#x\n",
     542    PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv;
     543    int iCfgIndex;
     544    int rc;
     545
     546    LogFlow(("usbProxyFreeBSDSetConfig: pProxyDev=%s cfg=%x\n",
    583547             pProxyDev->pUsbIns->pszName, iCfg));
    584548
    585     /* Close any open endpoints. */
    586     for (unsigned i = 0; i < USBFBSD_MAXENDPOINTS; i++)
    587         usbProxyFreeBSDEndpointClose(pProxyDev, i);
    588 
    589     /* We need to release kernel resources first. */
    590     struct usb_fs_uninit UsbFsUninit;
    591     UsbFsUninit.dummy = 0;
    592 
    593     int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_UNINIT, &UsbFsUninit, false, 1);
    594     AssertMsg(!rc, ("Freeing kernel resources failed rc=%Rrc\n", RTErrConvertFromErrno(errno)));
    595 
    596     int iCfgIndex = 0;
    597 
    598     /* Get the configuration index matching the value. */
    599     for (iCfgIndex = 0; iCfgIndex < pProxyDev->DevDesc.bNumConfigurations; iCfgIndex++)
    600     {
    601         if (pProxyDev->paCfgDescs[iCfgIndex].Core.bConfigurationValue == iCfg)
    602             break;
    603     }
    604 
    605     if (RT_UNLIKELY(iCfgIndex == pProxyDev->DevDesc.bNumConfigurations))
    606     {
    607         LogFlow(("usbProxyFreeBSDSetConfig: configuration %d not found\n", iCfg));
     549    /* We need to release kernel ressources first. */
     550    rc = usbProxyFreeBSDFsUnInit(pProxyDev);
     551    if (RT_FAILURE(rc))
     552    {
     553        LogFlow(("usbProxyFreeBSDSetInterface: Freeing kernel resources "
     554                 "failed failed rc=%d\n", rc));
    608555        return false;
    609556    }
    610557
     558    if (iCfg == 0)
     559    {
     560        /* Unconfigure */
     561        iCfgIndex = 255;
     562    }
     563    else
     564    {
     565        /* Get the configuration index matching the value. */
     566        for (iCfgIndex = 0; iCfgIndex < pProxyDev->DevDesc.bNumConfigurations; iCfgIndex++)
     567        {
     568            if (pProxyDev->paCfgDescs[iCfgIndex].Core.bConfigurationValue == iCfg)
     569                break;
     570        }
     571
     572        if (iCfgIndex == pProxyDev->DevDesc.bNumConfigurations)
     573        {
     574            LogFlow(("usbProxyFreeBSDSetConfig: configuration "
     575                     "%d not found\n", iCfg));
     576            return false;
     577        }
     578    }
     579
    611580    /* Set the config */
    612     rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_SET_CONFIG, &iCfgIndex, true, UINT32_MAX);
    613     if (RT_FAILURE(rc))
    614     {
    615         LogFlow(("usbProxyFreeBSDSetConfig: setting config index %d failed rc=%d errno=%Rrc\n", iCfgIndex, rc, RTErrConvertFromErrno(errno)));
     581    rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_SET_CONFIG, &iCfgIndex, true);
     582    if (RT_FAILURE(rc))
    616583        return false;
    617     }
    618 
    619     /* Allocate kernel resources again. */
    620     struct usb_fs_init UsbFsInit;
    621 
    622     UsbFsInit.pEndpoints   = pDevFBSD->paXferEndpoints;
    623     UsbFsInit.ep_index_max = pDevFBSD->cXferEndpoints;
    624     rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_INIT, &UsbFsInit, true, UINT32_MAX);
    625 
    626 
    627     LogFlow(("usbProxyFreeBSDSetConfig: rc=%d errno=%Rrc\n", rc, RTErrConvertFromErrno(errno)));
    628 
    629     if (!rc)
    630         return true;
    631     else
     584
     585    /* Allocate kernel ressources again. */
     586    rc = usbProxyFreeBSDFsInit(pProxyDev);
     587    if (RT_FAILURE(rc))
    632588        return false;
    633 }
    634 
     589
     590    return true;
     591}
    635592
    636593/**
     
    640597static int usbProxyFreeBSDClaimInterface(PUSBPROXYDEV pProxyDev, int iIf)
    641598{
    642     LogFlow(("usbProxyFreeBSDClaimInterface: pProxyDev=%s ifnum=%#x\n", pProxyDev->pUsbIns->pszName, iIf));
    643 
    644     int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_CLAIM_INTERFACE, &iIf, true, UINT32_MAX);
     599    int rc;
     600
     601    LogFlow(("usbProxyFreeBSDClaimInterface: pProxyDev=%s "
     602             "ifnum=%x\n", pProxyDev->pUsbIns->pszName, iIf));
     603
     604    /*
     605     * Try to detach kernel driver on this interface, ignore any
     606     * failures
     607     */
     608    rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_IFACE_DRIVER_DETACH, &iIf, true);
     609
     610    /* Try to claim interface */
     611    rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_CLAIM_INTERFACE, &iIf, true);
    645612    if (RT_FAILURE(rc))
    646613        return false;
     
    648615    return true;
    649616}
    650 
    651617
    652618/**
     
    656622static int usbProxyFreeBSDReleaseInterface(PUSBPROXYDEV pProxyDev, int iIf)
    657623{
    658     LogFlow(("usbProxyFreeBSDReleaseInterface: pProxyDev=%s ifnum=%#x\n", pProxyDev->pUsbIns->pszName, iIf));
    659 
    660     int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_RELEASE_INTERFACE, &iIf, true, UINT32_MAX);
     624    int rc;
     625
     626    LogFlow(("usbProxyFreeBSDReleaseInterface: pProxyDev=%s "
     627        "ifnum=%x\n", pProxyDev->pUsbIns->pszName, iIf));
     628
     629    rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_RELEASE_INTERFACE, &iIf, true);
    661630    if (RT_FAILURE(rc))
    662631        return false;
     
    664633    return true;
    665634}
    666 
    667635
    668636/**
     
    671639 * @returns success indicator.
    672640 */
    673 static int usbProxyFreeBSDSetInterface(PUSBPROXYDEV pProxyDev, int iIf, int iAlt)
    674 {
    675     PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv;
    676 
    677     LogFlow(("usbProxyFreeBSDSetInterface: pProxyDev=%p iIf=%#x iAlt=%#x\n", pProxyDev, iIf, iAlt));
    678 
    679     /* Close any open endpoints. */
    680     for (unsigned i = 0; i < USBFBSD_MAXENDPOINTS; i++)
    681         usbProxyFreeBSDEndpointClose(pProxyDev, i);
    682 
    683     /* We need to release kernel resources first. */
    684     struct usb_fs_uninit UsbFsUninit;
    685     UsbFsUninit.dummy = 0;
    686 
    687     int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_UNINIT, &UsbFsUninit, false, 1);
    688     AssertMsg(!rc, ("Freeing kernel resources failed rc=%Rrc\n", RTErrConvertFromErrno(errno)));
    689 
     641static int
     642usbProxyFreeBSDSetInterface(PUSBPROXYDEV pProxyDev, int iIf, int iAlt)
     643{
     644    PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv;
    690645    struct usb_alt_interface UsbIntAlt;
     646    int rc;
     647
     648    LogFlow(("usbProxyFreeBSDSetInterface: pProxyDev=%p iIf=%x iAlt=%x\n",
     649             pProxyDev, iIf, iAlt));
     650
     651    /* We need to release kernel ressources first. */
     652    rc = usbProxyFreeBSDFsUnInit(pProxyDev);
     653    if (RT_FAILURE(rc))
     654    {
     655        LogFlow(("usbProxyFreeBSDSetInterface: Freeing kernel resources "
     656                 "failed failed rc=%d\n", rc));
     657        return false;
     658    }
     659    memset(&UsbIntAlt, 0, sizeof(UsbIntAlt));
    691660    UsbIntAlt.uai_interface_index = iIf;
    692661    UsbIntAlt.uai_alt_index = iAlt;
    693     rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_SET_ALTINTERFACE, &UsbIntAlt, true, UINT32_MAX);
    694     if (rc)
    695     {
    696         LogFlow(("usbProxyFreeBSDSetInterface: Setting interface %d %d failed rc=%d errno=%Rrc\n", iIf, iAlt, rc,RTErrConvertFromErrno(errno)));
     662
     663    rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_SET_ALTINTERFACE, &UsbIntAlt, true);
     664    if (RT_FAILURE(rc))
     665    {
     666        LogFlow(("usbProxyFreeBSDSetInterface: Setting interface %d %d "
     667                 "failed rc=%d\n", iIf, iAlt, rc));
    697668        return false;
    698669    }
    699670
    700     /* Allocate kernel resources again. */
    701     struct usb_fs_init UsbFsInit;
    702 
    703     UsbFsInit.pEndpoints   = pDevFBSD->paXferEndpoints;
    704     UsbFsInit.ep_index_max = pDevFBSD->cXferEndpoints;
    705     rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_INIT, &UsbFsInit, true, UINT32_MAX);
    706 
    707     LogFlow(("usbProxyFreeBSDSetInterface: rc=%d errno=%Rrc\n", rc, RTErrConvertFromErrno(errno)));
    708 
    709     if (!rc)
     671    rc = usbProxyFreeBSDFsInit(pProxyDev);
     672    if (RT_FAILURE(rc))
     673        return false;
     674
     675    return true;
     676}
     677
     678/**
     679 * Clears the halted endpoint 'ep_num'.
     680 */
     681static bool usbProxyFreeBSDClearHaltedEp(PUSBPROXYDEV pProxyDev, unsigned int ep_num)
     682{
     683    struct usb_ctl_request Req;
     684    int rc;
     685
     686    LogFlow(("usbProxyFreeBSDClearHaltedEp: pProxyDev=%s ep_num=%u\n",
     687             pProxyDev->pUsbIns->pszName, ep_num));
     688
     689    /*
     690     * Clearing the zero control pipe doesn't make sense.
     691     * Just ignore it.
     692     */
     693    if ((ep_num & 0xF) == 0)
    710694        return true;
    711     else
     695
     696    memset(&Req, 0, sizeof(Req));
     697
     698    usbProxyFreeBSDSetupReq(&Req.ucr_request,
     699                            VUSB_DIR_TO_DEV | VUSB_TO_ENDPOINT,
     700                            VUSB_REQ_CLEAR_FEATURE, 0, ep_num, 0);
     701
     702    rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_DO_REQUEST, &Req, true);
     703
     704    LogFlow(("usbProxyFreeBSDClearHaltedEp: rc=%Rrc\n", rc));
     705
     706    if (RT_FAILURE(rc))
    712707        return false;
    713 }
    714 
    715 
    716 /**
    717  * Clears the halted endpoint 'EndPt'.
    718  */
    719 static bool usbProxyFreeBSDClearHaltedEp(PUSBPROXYDEV pProxyDev, unsigned int EndPt)
    720 {
    721     LogFlow(("usbProxyFreeBSDClearHaltedEp: pProxyDev=%s EndPt=%u\n", pProxyDev->pUsbIns->pszName, EndPt));
    722 
    723     /*
    724      * Clearing the zero control pipe doesn't make sense. Just ignore it.
    725      */
    726     if (EndPt == 0)
    727         return true;
    728 
    729     struct usb_ctl_request Req;
    730 
    731     memset(&Req, 0, sizeof(struct usb_ctl_request));
    732     usbProxyFreeBSDSetupReq(&Req.ucr_request, VUSB_DIR_TO_DEV | VUSB_TO_ENDPOINT, VUSB_REQ_CLEAR_FEATURE, 0, EndPt, 0);
    733 
    734     int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_DO_REQUEST, &Req, true, 1);
    735     if (rc)
    736     {
    737         LogFlow(("usbProxyFreeBSDClearHaltedEp: failed rc=%d errno=%Rrc\n", rc, RTErrConvertFromErrno(errno)));
    738         return false;
    739     }
    740 
    741     LogFlow(("usbProxyFreeBSDClearHaltedEp: succeeded\n"));
    742708
    743709    return true;
    744710}
    745711
    746 
    747712/**
    748713 * @copydoc USBPROXYBACK::pfnUrbQueue
     
    751716{
    752717    PUSBPROXYDEV pProxyDev = PDMINS_2_DATA(pUrb->pUsbIns, PUSBPROXYDEV);
    753     PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv;
    754 
    755     LogFlow(("usbProxyFreeBSDUrbQueue: pUrb=%p\n", pUrb));
    756 
    757     uint8_t EndPt = pUrb->EndPt;
    758     if (pUrb->EndPt)
    759         EndPt = pUrb->EndPt | (pUrb->enmDir == VUSBDIRECTION_IN ? 0x80 : 0);
    760 
    761     PUSBENDPOINTFBSD pEndpointFBSD = usbProxyFreeBSDEndpointOpen(pProxyDev, EndPt);
    762     if (!pEndpointFBSD)
    763         return false;
    764 
    765     PVUSBURBFBSD pUrbFBSD = &pDevFBSD->paUrbs[pEndpointFBSD->iEndpoint];
    766     AssertMsg(!pUrbFBSD->pUrb, ("Assigned entry is busy\n"));
    767     pUrbFBSD->pUrb = pUrb;
    768 
     718    PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv;
     719    PUSBENDPOINTFBSD pEndpointFBSD;
     720    struct usb_fs_endpoint *pXferEndpoint;
    769721    struct usb_fs_start UsbFsStart;
    770722    unsigned cFrames;
    771 
    772     if (pUrb->enmType == VUSBXFERTYPE_MSG)
    773     {
    774         PVUSBSETUP pSetup = (PVUSBSETUP)&pUrb->abData[0];
    775 
    776         pUrbFBSD->apvData[0] = pSetup;
    777         pUrbFBSD->acbData[0] = sizeof(VUSBSETUP);
    778 
    779         if (pSetup->wLength)
    780         {
    781             pUrbFBSD->apvData[1] = &pUrb->abData[sizeof(VUSBSETUP)];
    782             pUrbFBSD->acbData[1] = pSetup->wLength;
    783             cFrames = 2;
    784         }
    785         else
     723    uint8_t *pbData;
     724    int index;
     725    int ep_num;
     726    int rc;
     727
     728    LogFlow(("usbProxyFreeBSDUrbQueue: pUrb=%p EndPt=%u Dir=%u\n",
     729             pUrb, (unsigned)pUrb->EndPt, (unsigned)pUrb->enmDir));
     730
     731    ep_num = pUrb->EndPt;
     732
     733    if ((pUrb->enmType != VUSBXFERTYPE_MSG) && (pUrb->enmDir == VUSBDIRECTION_IN))
     734        ep_num |= 0x80;
     735
     736    index = 0;
     737
     738retry:
     739
     740    index = usbProxyFreeBSDEndpointOpen(pProxyDev, ep_num,
     741                                        (pUrb->enmType == VUSBXFERTYPE_ISOC),
     742                                        index);
     743
     744    if (index < 0)
     745        return false;
     746
     747    pEndpointFBSD = &pDevFBSD->aSwEndpoint[index];
     748    pXferEndpoint = &pDevFBSD->aHwEndpoint[index];
     749
     750    pbData = pUrb->abData;
     751
     752    switch (pUrb->enmType)
     753    {
     754        case VUSBXFERTYPE_MSG:
     755        {
     756            pEndpointFBSD->apvData[0] = pbData;
     757            pEndpointFBSD->acbData[0] = 8;
     758
     759            /* check wLength */
     760            if (pbData[6] || pbData[7])
     761            {
     762                pEndpointFBSD->apvData[1] = pbData + 8;
     763                pEndpointFBSD->acbData[1] = pbData[6] | (pbData[7] << 8);
     764                cFrames = 2;
     765            }
     766            else
     767            {
     768                pEndpointFBSD->apvData[1] = NULL;
     769                pEndpointFBSD->acbData[1] = 0;
     770                cFrames = 1;
     771            }
     772
     773            LogFlow(("usbProxyFreeBSDUrbQueue: pUrb->cbData=%u, 0x%02x, "
     774                     "0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
     775                     pUrb->cbData, pbData[0], pbData[1], pbData[2], pbData[3],
     776                     pbData[4], pbData[5], pbData[6], pbData[7]));
     777
     778            pXferEndpoint->timeout = USB_FS_TIMEOUT_NONE;
     779            pXferEndpoint->flags = USB_FS_FLAG_MULTI_SHORT_OK;
     780            break;
     781        }
     782        case VUSBXFERTYPE_ISOC:
     783        {
     784            unsigned i;
     785
     786            for (i = 0; i < pUrb->cIsocPkts; i++)
     787            {
     788                if (i >= pEndpointFBSD->cMaxFrames)
     789                    break;
     790                pEndpointFBSD->apvData[i] = pbData + pUrb->aIsocPkts[i].off;
     791                pEndpointFBSD->acbData[i] = pUrb->aIsocPkts[i].cb;
     792            }
     793            /* Timeout handling will be done during reap. */
     794            pXferEndpoint->timeout = USB_FS_TIMEOUT_NONE;
     795            pXferEndpoint->flags = USB_FS_FLAG_MULTI_SHORT_OK;
     796            cFrames = i;
     797            break;
     798        }
     799        default:
     800        {
     801            pEndpointFBSD->apvData[0] = pbData;
     802            pEndpointFBSD->cbData0 = pUrb->cbData;
     803
     804            /* XXX maybe we have to loop */
     805            if (pUrb->cbData > pEndpointFBSD->cMaxIo)
     806                pEndpointFBSD->acbData[0] = pEndpointFBSD->cMaxIo;
     807            else
     808                pEndpointFBSD->acbData[0] = pUrb->cbData;
     809
     810            /* Timeout handling will be done during reap. */
     811            pXferEndpoint->timeout = USB_FS_TIMEOUT_NONE;
     812            pXferEndpoint->flags = pUrb->fShortNotOk ? 0 : USB_FS_FLAG_MULTI_SHORT_OK;
    786813            cFrames = 1;
    787     }
    788     else
    789     {
    790         pUrbFBSD->apvData[0] = &pUrb->abData[0];
    791         pUrbFBSD->acbData[0] = pUrb->cbData;
    792         cFrames = 1;
    793     }
    794 
    795     struct usb_fs_endpoint *pXferEndpoint = pEndpointFBSD->pXferEndpoint;
    796     pXferEndpoint->ppBuffer = &pUrbFBSD->apvData[0];
    797     pXferEndpoint->pLength  = &pUrbFBSD->acbData[0];
    798     pXferEndpoint->nFrames  = cFrames;
    799     pXferEndpoint->timeout  = USB_FS_TIMEOUT_NONE; /* Timeout handling will be done during reap. */
    800     pXferEndpoint->flags    = pUrb->fShortNotOk ? 0 : USB_FS_FLAG_MULTI_SHORT_OK;
     814            break;
     815        }
     816    }
     817
     818    /* store number of frames */
     819    pXferEndpoint->nFrames = cFrames;
     820
     821    /* zero-default */
     822    memset(&UsbFsStart, 0, sizeof(UsbFsStart));
    801823
    802824    /* Start the transfer */
    803     UsbFsStart.ep_index = pEndpointFBSD->iEndpoint;
    804     int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_START, &UsbFsStart, true, UINT32_MAX);
    805 
    806     LogFlow(("usbProxyFreeBSDUrbQueue: USB_FS_START returned rc=%d errno=%Rrc\n", rc, RTErrConvertFromErrno(errno)));
    807     if (rc)
    808     {
     825    UsbFsStart.ep_index = index;
     826
     827    rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_START, &UsbFsStart, true);
     828
     829    LogFlow(("usbProxyFreeBSDUrbQueue: USB_FS_START returned rc=%d "
     830             "len[0]=%u len[1]=%u cbData=%u index=%u ep_num=%u\n", rc,
     831             (unsigned)pEndpointFBSD->acbData[0],
     832             (unsigned)pEndpointFBSD->acbData[1],
     833             (unsigned)pUrb->cbData,
     834             (unsigned)index, (unsigned)ep_num));
     835
     836    if (RT_FAILURE(rc))
     837    {
     838        if (rc == VERR_RESOURCE_BUSY)
     839        {
     840            index++;
     841            goto retry;
     842        }
    809843        return false;
    810844    }
     845    pUrb->Dev.pvPrivate = (void *)(long)(index + 1);
     846    pEndpointFBSD->pUrb = pUrb;
    811847
    812848    return true;
    813849}
    814 
    815850
    816851/**
     
    824859static PVUSBURB usbProxyFreeBSDUrbReap(PUSBPROXYDEV pProxyDev, RTMSINTERVAL cMillies)
    825860{
    826     PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv;
    827 
    828     LogFlow(("usbProxyFreeBSDUrbReap: cMillies=%u\n", cMillies));
    829 
    830     /* We will poll for finished urbs because the ioctl doesn't take a timeout parameter. */
     861    struct usb_fs_endpoint *pXferEndpoint;
     862    PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv;
     863    PUSBENDPOINTFBSD pEndpointFBSD;
     864    PVUSBURB pUrb;
     865    struct usb_fs_complete UsbFsComplete;
    831866    struct pollfd PollFd;
    832     PVUSBURB pUrb = NULL;
    833 
    834     PollFd.fd      = (int)pDevFBSD->File;
    835     PollFd.events  = POLLIN | POLLRDNORM | POLLOUT;
    836     PollFd.revents = 0;
    837 
    838     struct usb_fs_complete UsbFsComplete;
    839 
    840     UsbFsComplete.ep_index = 0;
    841 
    842     int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_COMPLETE, &UsbFsComplete, true, UINT32_MAX);
    843     if (!rc)
    844     {
    845         struct usb_fs_endpoint *pXferEndpoint = &pDevFBSD->paXferEndpoints[UsbFsComplete.ep_index];
    846         PVUSBURBFBSD pUrbFBSD = &pDevFBSD->paUrbs[UsbFsComplete.ep_index];
    847 
    848         LogFlow(("Reaped URB %#p\n", pUrbFBSD->pUrb));
    849 
    850         pUrb = pUrbFBSD->pUrb;
    851         AssertMsg(pUrb, ("No URB handle for the completed entry\n"));
    852         pUrbFBSD->pUrb = NULL;
     867    int rc;
     868
     869    LogFlow(("usbProxyFreeBSDUrbReap: pProxyDev=%p, cMillies=%u\n",
     870             pProxyDev, cMillies));
     871
     872repeat:
     873
     874    pUrb = NULL;
     875
     876    /* check for cancelled transfers */
     877    if (pDevFBSD->fCancelling)
     878    {
     879        for (unsigned n = 0; n < USBFBSD_MAXENDPOINTS; n++)
     880        {
     881            pEndpointFBSD = &pDevFBSD->aSwEndpoint[n];
     882            if (pEndpointFBSD->fCancelling)
     883            {
     884                pEndpointFBSD->fCancelling = false;
     885                pUrb = pEndpointFBSD->pUrb;
     886                pEndpointFBSD->pUrb = NULL;
     887
     888                if (pUrb != NULL)
     889                    break;
     890            }
     891        }
     892
     893        if (pUrb != NULL)
     894        {
     895            pUrb->enmStatus = VUSBSTATUS_INVALID;
     896            pUrb->Dev.pvPrivate = NULL;
     897
     898            switch (pUrb->enmType)
     899            {
     900                case VUSBXFERTYPE_MSG:
     901                    pUrb->cbData = 0;
     902                    break;
     903                case VUSBXFERTYPE_ISOC:
     904                    pUrb->cbData = 0;
     905                    for (int n = 0; n < (int)pUrb->cIsocPkts; n++)
     906                        pUrb->aIsocPkts[n].cb = 0;
     907                    break;
     908                default:
     909                    pUrb->cbData = 0;
     910                    break;
     911            }
     912            return pUrb;
     913        }
     914        pDevFBSD->fCancelling = false;
     915    }
     916    /* Zero default */
     917
     918    memset(&UsbFsComplete, 0, sizeof(UsbFsComplete));
     919
     920    /* Check if any endpoints are complete */
     921    rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_COMPLETE, &UsbFsComplete, true);
     922    if (RT_SUCCESS(rc))
     923    {
     924        pXferEndpoint = &pDevFBSD->aHwEndpoint[UsbFsComplete.ep_index];
     925        pEndpointFBSD = &pDevFBSD->aSwEndpoint[UsbFsComplete.ep_index];
     926
     927        LogFlow(("usbProxyFreeBSDUrbReap: Reaped "
     928                 "URB %#p\n", pEndpointFBSD->pUrb));
     929
     930        if (pXferEndpoint->status == USB_ERR_CANCELLED)
     931            goto repeat;
     932
     933        pUrb = pEndpointFBSD->pUrb;
     934        pEndpointFBSD->pUrb = NULL;
     935        if (pUrb == NULL)
     936            goto repeat;
    853937
    854938        switch (pXferEndpoint->status)
     
    861945                break;
    862946            default:
    863                 AssertMsgFailed(("Unexpected status code %d\n", pXferEndpoint->status));
    864         }
    865     }
    866     else
    867     {
    868 
    869         rc = poll(&PollFd, 1, cMillies == RT_INDEFINITE_WAIT ? INFTIM : cMillies);
    870         if (rc == 1)
    871         {
    872     //        do
     947                pUrb->enmStatus = VUSBSTATUS_INVALID;
     948                break;
     949        }
     950
     951        pUrb->Dev.pvPrivate = NULL;
     952
     953        switch (pUrb->enmType)
     954        {
     955            case VUSBXFERTYPE_MSG:
     956                pUrb->cbData = pEndpointFBSD->acbData[0] + pEndpointFBSD->acbData[1];
     957                break;
     958            case VUSBXFERTYPE_ISOC:
    873959            {
    874                 UsbFsComplete.ep_index = 0;
    875                 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_COMPLETE, &UsbFsComplete, true, UINT32_MAX);
    876                 if (!rc)
     960                int n;
     961
     962                if (pUrb->enmDir == VUSBDIRECTION_OUT)
     963                    break;
     964                pUrb->cbData = 0;
     965                for (n = 0; n < (int)pUrb->cIsocPkts; n++)
    877966                {
    878                     struct usb_fs_endpoint *pXferEndpoint = &pDevFBSD->paXferEndpoints[UsbFsComplete.ep_index];
    879                     PVUSBURBFBSD pUrbFBSD = &pDevFBSD->paUrbs[UsbFsComplete.ep_index];
    880 
    881                     LogFlow(("Reaped URB %#p\n", pUrbFBSD->pUrb));
    882 
    883                     pUrb = pUrbFBSD->pUrb;
    884                     AssertMsg(pUrb, ("No URB handle for the completed entry\n"));
    885                     pUrbFBSD->pUrb = NULL;
    886 
    887                     switch (pXferEndpoint->status)
    888                     {
    889                         case USB_ERR_NORMAL_COMPLETION:
    890                             pUrb->enmStatus = VUSBSTATUS_OK;
    891                             break;
    892                         case USB_ERR_STALLED:
    893                             pUrb->enmStatus = VUSBSTATUS_STALL;
    894                             break;
    895                         default:
    896                             AssertMsgFailed(("Unexpected status code %d\n", pXferEndpoint->status));
    897                     }
    898 
    899                     rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_COMPLETE, &UsbFsComplete, true, UINT32_MAX);
    900                     AssertMsg(((rc == -1) && (errno == EBUSY)), ("Expected return value rc=%d rc=%Rrc\n", rc, RTErrConvertFromErrno(errno)));
     967                    if (n >= (int)pEndpointFBSD->cMaxFrames)
     968                        break;
     969                    pUrb->cbData += pEndpointFBSD->acbData[n];
     970                    pUrb->aIsocPkts[n].cb = pEndpointFBSD->acbData[n];
    901971                }
    902                 else
    903                     LogFlow(("couldn't get completed URB rc=%Rrc\n", RTErrConvertFromErrno(errno)));
     972                for (; n < (int)pUrb->cIsocPkts; n++)
     973                    pUrb->aIsocPkts[n].cb = 0;
     974
     975                break;
    904976            }
    905     //        while (!rc);
     977            default:
     978                pUrb->cbData = pEndpointFBSD->acbData[0];
     979                break;
     980        }
     981
     982        LogFlow(("usbProxyFreeBSDUrbReap: Status=%d epindex=%u "
     983                 "len[0]=%d len[1]=%d\n",
     984                 (int)pXferEndpoint->status,
     985                 (unsigned)UsbFsComplete.ep_index,
     986                 (unsigned)pEndpointFBSD->acbData[0],
     987                 (unsigned)pEndpointFBSD->acbData[1]));
     988
     989    }
     990    else if (cMillies && rc == VERR_RESOURCE_BUSY)
     991    {
     992        /* Poll for finished transfers */
     993        PollFd.fd = (int)pDevFBSD->File;
     994        PollFd.events = POLLIN | POLLRDNORM;
     995        PollFd.revents = 0;
     996
     997        rc = poll(&PollFd, 1, (cMillies == RT_INDEFINITE_WAIT) ? INFTIM : cMillies);
     998        if (rc >= 1)
     999        {
     1000            goto repeat;
    9061001        }
    9071002        else
    908             LogFlow(("poll returned rc=%d rcRT=%Rrc\n", rc, rc < 0 ? RTErrConvertFromErrno(errno) : VERR_TIMEOUT));
    909     }
    910 
     1003        {
     1004            LogFlow(("usbProxyFreeBSDUrbReap: "
     1005                     "poll returned rc=%d\n", rc));
     1006        }
     1007    }
    9111008    return pUrb;
    9121009}
    913 
    9141010
    9151011/**
     
    9201016{
    9211017    PUSBPROXYDEV pProxyDev = PDMINS_2_DATA(pUrb->pUsbIns, PUSBPROXYDEV);
    922     PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv;
    923 
    924 
    925 }
    926 
     1018    int index;
     1019
     1020    index = (int)(long)pUrb->Dev.pvPrivate - 1;
     1021
     1022    if (index < 0 || index >= USBFBSD_MAXENDPOINTS)
     1023        return;
     1024
     1025    LogFlow(("usbProxyFreeBSDUrbCancel: epindex=%u\n", (unsigned)index));
     1026
     1027    usbProxyFreeBSDEndpointClose(pProxyDev, index);
     1028}
    9271029
    9281030/**
     
    9471049};
    9481050
    949 
    9501051/*
    9511052 * Local Variables:
Note: See TracChangeset for help on using the changeset viewer.

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