VirtualBox

Changeset 75582 in vbox


Ignore:
Timestamp:
Nov 19, 2018 5:02:46 PM (6 years ago)
Author:
vboxsync
Message:

USBProxyDevice-usbip.cpp: Convert the synchronous CTRL message exchange code to use the generic PDU receive path to ensure that the code does not try to receive a new PDU while being in the middle of another one. Hopefully fixes a few testcase failures (especially the Set/Clear halt tests which fail frequently)

File:
1 edited

Legend:

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

    r72054 r75582  
    349349    /** Flag whether the URB was cancelled. */
    350350    bool               fCancelled;
     351    /** USB xfer type. */
     352    VUSBXFERTYPE       enmType;
     353    /** USB xfer direction. */
     354    VUSBDIRECTION      enmDir;
     355    /** Completion status. */
     356    VUSBSTATUS         enmStatus;
    351357    /** Pointer to the VUSB URB. */
    352358    PVUSBURB           pVUsbUrb;
     
    623629DECLINLINE(uint32_t) usbProxyUsbIpSeqNumGet(PUSBPROXYDEVUSBIP pProxyDevUsbIp)
    624630{
    625     return ASMAtomicIncU32(&pProxyDevUsbIp->u32SeqNumNext);
     631    uint32_t u32SeqNum = ASMAtomicIncU32(&pProxyDevUsbIp->u32SeqNumNext);
     632    if (RT_UNLIKELY(!u32SeqNum))
     633        u32SeqNum = ASMAtomicIncU32(&pProxyDevUsbIp->u32SeqNumNext);
     634
     635    return u32SeqNum;
    626636}
    627637
     
    844854
    845855/**
    846  * Synchronously exchange a given control message with the remote device.
    847  *
    848  * @eturns VBox status code.
    849  * @param  pProxyDevUsbIp    The USB/IP proxy device data.
    850  * @param  pSetup            The setup message.
    851  *
    852  * @note This method is only used to implement the *SetConfig, *SetInterface and *ClearHaltedEp
    853  *       callbacks because the USB/IP protocol lacks dedicated requests for these.
    854  * @remark It is assumed that this method is never called while usbProxyUsbIpUrbReap is called
    855  *         on another thread.
    856  */
    857 static int usbProxyUsbIpCtrlUrbExchangeSync(PUSBPROXYDEVUSBIP pProxyDevUsbIp, PVUSBSETUP pSetup)
    858 {
    859     int rc = VINF_SUCCESS;
    860     unsigned iTry = 0;
    861 
    862     UsbIpReqSubmit ReqSubmit;
    863 
    864     RT_ZERO(ReqSubmit);
    865 
    866     uint32_t u32SeqNum = usbProxyUsbIpSeqNumGet(pProxyDevUsbIp);
    867     ReqSubmit.Hdr.u32ReqRet           = USBIP_CMD_SUBMIT;
    868     ReqSubmit.Hdr.u32SeqNum           = u32SeqNum;
    869     ReqSubmit.Hdr.u32DevId            = pProxyDevUsbIp->u32DevId;
    870     ReqSubmit.Hdr.u32Direction        = USBIP_DIR_OUT;
    871     ReqSubmit.Hdr.u32Endpoint         = 0; /* Only default control endpoint is allowed for these kind of messages. */
    872     ReqSubmit.u32XferFlags            = 0;
    873     ReqSubmit.u32TransferBufferLength = 0;
    874     ReqSubmit.u32StartFrame           = 0;
    875     ReqSubmit.u32NumIsocPkts          = 0;
    876     ReqSubmit.u32Interval             = 0;
    877     memcpy(&ReqSubmit.Setup, pSetup, sizeof(ReqSubmit.Setup));
    878     usbProxyUsbIpReqSubmitH2N(&ReqSubmit);
    879 
    880     do
    881     {
    882         /* Send the command. */
    883         rc = RTTcpWrite(pProxyDevUsbIp->hSocket, &ReqSubmit, sizeof(ReqSubmit));
    884         if (RT_SUCCESS(rc))
    885         {
    886             /* Wait for the response. */
    887             /** @todo Don't wait indefinitely long. */
    888             UsbIpRetSubmit RetSubmit;
    889             rc = RTTcpRead(pProxyDevUsbIp->hSocket, &RetSubmit, sizeof(RetSubmit), NULL);
    890             if (RT_SUCCESS(rc))
    891             {
    892                 usbProxyUsbIpRetSubmitN2H(&RetSubmit);
    893                 rc = usbProxyUsbIpStatusConvertFromStatus(RetSubmit.u32Status);
    894             }
    895         }
    896     } while (   rc == VERR_TRY_AGAIN
    897              && iTry++ < 10);
    898     return rc;
    899 }
    900 
    901 /**
    902856 * Returns the URB matching the given sequence number from the in flight list.
    903857 *
     
    910864    bool fFound = false;
    911865
     866    int rc = RTSemFastMutexRequest(pProxyDevUsbIp->hMtxLists);
     867    AssertRC(rc);
    912868    PUSBPROXYURBUSBIP pIt;
    913869    RTListForEach(&pProxyDevUsbIp->ListUrbsInFlight, pIt, USBPROXYURBUSBIP, NodeList)
     
    919875        }
    920876    }
     877    RTSemFastMutexRelease(pProxyDevUsbIp->hMtxLists);
    921878
    922879    return fFound ? pIt : NULL;
     
    934891    bool fFound = false;
    935892
     893    int rc = RTSemFastMutexRequest(pProxyDevUsbIp->hMtxLists);
     894    AssertRC(rc);
    936895    PUSBPROXYURBUSBIP pIt;
    937896    RTListForEach(&pProxyDevUsbIp->ListUrbsInFlight, pIt, USBPROXYURBUSBIP, NodeList)
     
    944903        }
    945904    }
     905    RTSemFastMutexRelease(pProxyDevUsbIp->hMtxLists);
    946906
    947907    return fFound ? pIt : NULL;
     
    10411001
    10421002                                /* We still have to receive the transfer buffer, even in case of an error. */
    1043                                 pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->enmStatus = usbProxyUsbIpVUsbStatusConvertFromStatus(pProxyDevUsbIp->BufRet.RetSubmit.u32Status);
    1044                                 if (pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->enmDir == VUSBDIRECTION_IN)
     1003                                pProxyDevUsbIp->pUrbUsbIp->enmStatus = usbProxyUsbIpVUsbStatusConvertFromStatus(pProxyDevUsbIp->BufRet.RetSubmit.u32Status);
     1004                                if (pProxyDevUsbIp->pUrbUsbIp->enmDir == VUSBDIRECTION_IN)
    10451005                                {
    10461006                                    uint8_t *pbData = NULL;
    10471007
    1048                                     if (pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->enmType == VUSBXFERTYPE_MSG)
     1008                                    AssertPtr(pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb);
     1009                                    if (pProxyDevUsbIp->pUrbUsbIp->enmType == VUSBXFERTYPE_MSG)
    10491010                                    {
    10501011                                        /* Preserve the setup request. */
     
    10691030                                else
    10701031                                {
    1071                                     Assert(pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->enmDir == VUSBDIRECTION_OUT);
     1032                                    Assert(pProxyDevUsbIp->pUrbUsbIp->enmDir == VUSBDIRECTION_OUT);
    10721033                                    pUrbUsbIp = pProxyDevUsbIp->pUrbUsbIp;
    10731034                                    usbProxyUsbIpResetRecvState(pProxyDevUsbIp);
     
    10761037                            else
    10771038                            {
    1078                                 LogRel(("USB/IP: Received reply with sequence number %u doesn't match any local URB\n", pProxyDevUsbIp->BufRet.Hdr.u32SeqNum));
     1039                                LogRel(("USB/IP: Received reply with sequence number %u doesn't match any local URB\n",
     1040                                        RT_N2H_U32(pProxyDevUsbIp->BufRet.Hdr.u32SeqNum)));
    10791041                                usbProxyUsbIpResetRecvState(pProxyDevUsbIp);
    10801042                            }
     
    11541116
    11551117    pUrbUsbIp->u32SeqNumUrb = usbProxyUsbIpSeqNumGet(pProxyDevUsbIp);
     1118    pUrbUsbIp->enmType      = pUrb->enmType;
     1119    pUrbUsbIp->enmStatus    = pUrb->enmStatus;
     1120    pUrbUsbIp->enmDir       = pUrb->enmDir;
    11561121
    11571122    UsbIpReqSubmit ReqSubmit;
     
    13181283}
    13191284
     1285/**
     1286 * Executes the poll/receive loop either until a URB is received (with an optional matching sequence number) or
     1287 * the given timeout has elapsed.
     1288 *
     1289 * @returns Pointer to the received USB/IP URB or NULL on timeout or error.
     1290 * @param   pProxyDevUsbIp    The USB/IP proxy device data.
     1291 * @param   u32SeqNumRet      The sequence number of a specific reply to return the URB for, 0 if
     1292 *                            any received URB is accepted.
     1293 * @param   fPollWakePipe     Flag whether to poll the wakeup pipe.
     1294 * @param   cMillies          Maximum number of milliseconds to wait for an URB to arrive.
     1295 */
     1296static PUSBPROXYURBUSBIP usbProxyUsbIpPollWorker(PUSBPROXYDEVUSBIP pProxyDevUsbIp, uint32_t u32SeqNumRet,
     1297                                                 bool fPollWakePipe, RTMSINTERVAL cMillies)
     1298{
     1299    int rc = VINF_SUCCESS;
     1300    PUSBPROXYURBUSBIP pUrbUsbIp = NULL;
     1301
     1302    if (!fPollWakePipe)
     1303    {
     1304        rc = RTPollSetRemove(pProxyDevUsbIp->hPollSet, USBIP_POLL_ID_PIPE);
     1305        AssertRC(rc);
     1306    }
     1307
     1308    while (!pUrbUsbIp && RT_SUCCESS(rc) && cMillies)
     1309    {
     1310        uint32_t uIdReady = 0;
     1311        uint32_t fEventsRecv = 0;
     1312        RTMSINTERVAL msStart = RTTimeMilliTS();
     1313        RTMSINTERVAL msNow;
     1314
     1315        rc = RTPoll(pProxyDevUsbIp->hPollSet, cMillies, &fEventsRecv, &uIdReady);
     1316        Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT);
     1317        if (RT_SUCCESS(rc))
     1318        {
     1319            msNow = RTTimeMilliTS();
     1320            cMillies = msNow - msStart >= cMillies ? 0 : cMillies - (msNow - msStart);
     1321
     1322            if (uIdReady == USBIP_POLL_ID_SOCKET)
     1323            {
     1324                rc = usbProxyUsbIpRecvPdu(pProxyDevUsbIp, &pUrbUsbIp);
     1325                if (   RT_SUCCESS(rc)
     1326                    && pUrbUsbIp)
     1327                {
     1328                    /* Link the URB into the landed list if a specifc reply is requested and the URB doesn't match. */
     1329                    if (   u32SeqNumRet != 0
     1330                        && pUrbUsbIp->u32SeqNumUrb != u32SeqNumRet)
     1331                    {
     1332                        usbProxyUsbIpUnlinkUrb(pProxyDevUsbIp, pUrbUsbIp);
     1333                        usbProxyUsbIpLinkUrb(pProxyDevUsbIp, &pProxyDevUsbIp->ListUrbsLanded, pUrbUsbIp);
     1334                        pUrbUsbIp = NULL;
     1335                    }
     1336                }
     1337            }
     1338            else
     1339            {
     1340                AssertLogRelMsg(uIdReady == USBIP_POLL_ID_PIPE, ("Invalid pollset ID given\n"));
     1341
     1342                char bReason = usbProxyUsbIpWakeupPipeDrain(pProxyDevUsbIp);
     1343                if (bReason == USBIP_REAPER_WAKEUP_REASON_QUEUE)
     1344                    usbProxyUsbIpUrbsQueuePending(pProxyDevUsbIp);
     1345                else
     1346                {
     1347                    Assert(bReason == USBIP_REAPER_WAKEUP_REASON_EXTERNAL);
     1348                    break;
     1349                }
     1350            }
     1351        }
     1352    }
     1353
     1354    if (!fPollWakePipe)
     1355    {
     1356        rc = RTPollSetAddPipe(pProxyDevUsbIp->hPollSet, pProxyDevUsbIp->hPipeR,
     1357                              RTPOLL_EVT_READ, USBIP_POLL_ID_PIPE);
     1358        AssertRC(rc);
     1359    }
     1360
     1361    return pUrbUsbIp;
     1362}
     1363
     1364/**
     1365 * Synchronously exchange a given control message with the remote device.
     1366 *
     1367 * @eturns VBox status code.
     1368 * @param  pProxyDevUsbIp    The USB/IP proxy device data.
     1369 * @param  pSetup            The setup message.
     1370 *
     1371 * @note This method is only used to implement the *SetConfig, *SetInterface and *ClearHaltedEp
     1372 *       callbacks because the USB/IP protocol lacks dedicated requests for these.
     1373 * @remark It is assumed that this method is never called while usbProxyUsbIpUrbReap is called
     1374 *         on another thread.
     1375 */
     1376static int usbProxyUsbIpCtrlUrbExchangeSync(PUSBPROXYDEVUSBIP pProxyDevUsbIp, PVUSBSETUP pSetup)
     1377{
     1378    int rc = VINF_SUCCESS;
     1379
     1380    UsbIpReqSubmit ReqSubmit;
     1381    USBPROXYURBUSBIP UsbIpUrb;
     1382
     1383    RT_ZERO(ReqSubmit);
     1384
     1385    uint32_t u32SeqNum = usbProxyUsbIpSeqNumGet(pProxyDevUsbIp);
     1386    ReqSubmit.Hdr.u32ReqRet           = USBIP_CMD_SUBMIT;
     1387    ReqSubmit.Hdr.u32SeqNum           = u32SeqNum;
     1388    ReqSubmit.Hdr.u32DevId            = pProxyDevUsbIp->u32DevId;
     1389    ReqSubmit.Hdr.u32Direction        = USBIP_DIR_OUT;
     1390    ReqSubmit.Hdr.u32Endpoint         = 0; /* Only default control endpoint is allowed for these kind of messages. */
     1391    ReqSubmit.u32XferFlags            = 0;
     1392    ReqSubmit.u32TransferBufferLength = 0;
     1393    ReqSubmit.u32StartFrame           = 0;
     1394    ReqSubmit.u32NumIsocPkts          = 0;
     1395    ReqSubmit.u32Interval             = 0;
     1396    memcpy(&ReqSubmit.Setup, pSetup, sizeof(ReqSubmit.Setup));
     1397    usbProxyUsbIpReqSubmitH2N(&ReqSubmit);
     1398
     1399    UsbIpUrb.u32SeqNumUrb       = u32SeqNum;
     1400    UsbIpUrb.u32SeqNumUrbUnlink = 0;
     1401    UsbIpUrb.fCancelled         = false;
     1402    UsbIpUrb.enmType            = VUSBXFERTYPE_MSG;
     1403    UsbIpUrb.enmDir             = VUSBDIRECTION_OUT;
     1404    UsbIpUrb.pVUsbUrb           = NULL;
     1405
     1406    /* Send the command. */
     1407    rc = RTTcpWrite(pProxyDevUsbIp->hSocket, &ReqSubmit, sizeof(ReqSubmit));
     1408    if (RT_SUCCESS(rc))
     1409    {
     1410        usbProxyUsbIpLinkUrb(pProxyDevUsbIp, &pProxyDevUsbIp->ListUrbsInFlight, &UsbIpUrb);
     1411        PUSBPROXYURBUSBIP pUrbUsbIp = usbProxyUsbIpPollWorker(pProxyDevUsbIp, u32SeqNum, false /*fPollWakePipe*/,
     1412                                                              30 * RT_MS_1SEC);
     1413        Assert(   !pUrbUsbIp
     1414               || pUrbUsbIp == &UsbIpUrb); /* The returned URB should point to the URB we submitted. */
     1415        usbProxyUsbIpUnlinkUrb(pProxyDevUsbIp, &UsbIpUrb);
     1416
     1417        if (!pUrbUsbIp)
     1418            rc = VERR_TIMEOUT;
     1419    }
     1420
     1421    return rc;
     1422}
     1423
     1424
    13201425/*
    13211426 * The USB proxy device functions.
     
    15971702    if (!RTListIsEmpty(&pProxyDevUsbIp->ListUrbsLanded))
    15981703        pUrbUsbIp = RTListGetFirst(&pProxyDevUsbIp->ListUrbsLanded, USBPROXYURBUSBIP, NodeList);
    1599 
    1600     while (!pUrbUsbIp && RT_SUCCESS(rc) && cMillies)
    1601     {
    1602         uint32_t uIdReady = 0;
    1603         uint32_t fEventsRecv = 0;
    1604         RTMSINTERVAL msStart = RTTimeMilliTS();
    1605         RTMSINTERVAL msNow;
    1606 
    1607         rc = RTPoll(pProxyDevUsbIp->hPollSet, cMillies, &fEventsRecv, &uIdReady);
    1608         Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT);
    1609         if (RT_SUCCESS(rc))
    1610         {
    1611             msNow = RTTimeMilliTS();
    1612             cMillies = msNow - msStart >= cMillies ? 0 : cMillies - (msNow - msStart);
    1613 
    1614             if (uIdReady == USBIP_POLL_ID_SOCKET)
    1615                 rc = usbProxyUsbIpRecvPdu(pProxyDevUsbIp, &pUrbUsbIp);
    1616             else
    1617             {
    1618                 AssertLogRelMsg(uIdReady == USBIP_POLL_ID_PIPE, ("Invalid pollset ID given\n"));
    1619 
    1620                 char bReason = usbProxyUsbIpWakeupPipeDrain(pProxyDevUsbIp);
    1621                 if (bReason == USBIP_REAPER_WAKEUP_REASON_QUEUE)
    1622                     usbProxyUsbIpUrbsQueuePending(pProxyDevUsbIp);
    1623                 else
    1624                 {
    1625                     Assert(bReason == USBIP_REAPER_WAKEUP_REASON_EXTERNAL);
    1626                     break;
    1627                 }
    1628             }
    1629         }
    1630     }
     1704    else
     1705        pUrbUsbIp = usbProxyUsbIpPollWorker(pProxyDevUsbIp, 0, true /*fPollWakePipe*/, cMillies);
    16311706
    16321707    if (pUrbUsbIp)
    16331708    {
    16341709        pUrb = pUrbUsbIp->pVUsbUrb;
     1710        pUrb->enmStatus = pUrbUsbIp->enmStatus;
    16351711
    16361712        /* unlink from the pending delivery list */
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