VirtualBox

Changeset 57301 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Aug 12, 2015 9:49:22 PM (9 years ago)
Author:
vboxsync
Message:

USB/IP: Updates, works with bulk devices now

File:
1 edited

Legend:

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

    r57273 r57301  
    7272
    7373/** URB direction - input. */
    74 #define USBIP_DIR_IN                         UINT32_C(0)
     74#define USBIP_DIR_IN                         UINT32_C(1)
    7575/** URB direction - output. */
    76 #define USBIP_DIR_OUT                        UINT32_C(1)
     76#define USBIP_DIR_OUT                        UINT32_C(0)
    7777
    7878/** @name USB/IP error codes.
     
    333333    /** Pipe endpoint - write. */
    334334    RTPIPE            hPipeW;
    335     /** Flag whether the reaper thread was woken up. */
    336     volatile bool     fWokenUp;
    337335    /** Next sequence number to use for identifying submitted URBs. */
    338336    volatile uint32_t u32SeqNumNext;
     
    343341    /** List of landed URBs. */
    344342    RTLISTANCHOR      ListUrbsLanded;
     343    /** List of URBs to submit. */
     344    RTLISTANCHOR      ListUrbsToQueue;
    345345    /** Port of the USB/IP host to connect to. */
    346346    uint32_t          uPort;
     
    372372/** USB/IP address prefix length. */
    373373#define USBIP_URI_PREFIX_LEN (sizeof(USBIP_URI_PREFIX) - 1)
     374
     375/** Waking reason for the USB I/P reaper: New URBs to queue. */
     376#define USBIP_REAPER_WAKEUP_REASON_QUEUE 'Q'
     377/** Waking reason for the USB I/P reaper: External wakeup. */
     378#define USBIP_REAPER_WAKEUP_REASON_EXTERNAL 'E'
    374379
    375380/**
     
    810815}
    811816
     817/**
     818 * Handles reception of a USB/IP PDU.
     819 *
     820 * @returns VBox status code.
     821 * @param  pProxyDevUsbIp    The USB/IP proxy device data.
     822 * @param  ppUrbUsbIp        Where to store the pointer to the USB/IP URB which completed.
     823 *                           Will be NULL if the received PDU is not complete and we have
     824 *                           have to wait for more data or on failure.
     825 */
     826static int usbProxyUsbIpRecvPdu(PUSBPROXYDEVUSBIP pProxyDevUsbIp, PUSBPROXYURBUSBIP *ppUrbUsbIp)
     827{
     828    int rc = VINF_SUCCESS;
     829    size_t cbRead = 0;
     830    PUSBPROXYURBUSBIP pUrbUsbIp = NULL;
     831
     832    if (pProxyDevUsbIp->fRecvData)
     833    {
     834        /* Read data into the URB. */
     835        rc = RTTcpReadNB(pProxyDevUsbIp->hSocket, &pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->abData[pProxyDevUsbIp->cbRecv], pProxyDevUsbIp->cbLeft, &cbRead);
     836        if (RT_SUCCESS(rc))
     837        {
     838            pProxyDevUsbIp->cbRecv += cbRead;
     839            pProxyDevUsbIp->cbLeft -= cbRead;
     840
     841            if (!pProxyDevUsbIp->cbLeft)
     842            {
     843                pUrbUsbIp = pProxyDevUsbIp->pUrbUsbIp;
     844                usbProxyUsbIpResetRecvState(pProxyDevUsbIp);
     845            }
     846        }
     847        else
     848        {
     849            pUrbUsbIp = pProxyDevUsbIp->pUrbUsbIp;
     850            pUrbUsbIp->pVUsbUrb->enmStatus = VUSBSTATUS_DNR;
     851            usbProxyUsbIpResetRecvState(pProxyDevUsbIp);
     852        }
     853    }
     854    else
     855    {
     856        rc = RTTcpReadNB(pProxyDevUsbIp->hSocket, &pProxyDevUsbIp->BufRet.abReply[pProxyDevUsbIp->cbRecv], pProxyDevUsbIp->cbLeft, &cbRead);
     857        if (RT_SUCCESS(rc))
     858        {
     859            pProxyDevUsbIp->cbRecv += cbRead;
     860            pProxyDevUsbIp->cbLeft -= cbRead;
     861        }
     862
     863        /* Check whether we received a complete header. */
     864        if (!pProxyDevUsbIp->cbLeft)
     865        {
     866            if (pProxyDevUsbIp->cbRecv == sizeof(UsbIpReqRetHdr))
     867            {
     868                /*
     869                 * Determine the residual amount of data to receive until
     870                 * the complete reply header was received.
     871                 */
     872                switch (RT_N2H_U32(pProxyDevUsbIp->BufRet.Hdr.u32ReqRet))
     873                {
     874                    case USBIP_RET_SUBMIT:
     875                        pProxyDevUsbIp->cbLeft = sizeof(UsbIpRetSubmit) - sizeof(UsbIpReqRetHdr);
     876                        break;
     877                    case USBIP_RET_UNLINK:
     878                        pProxyDevUsbIp->cbLeft = sizeof(UsbIpRetUnlink) - sizeof(UsbIpReqRetHdr);
     879                        break;
     880                    default:
     881                        AssertLogRelMsgFailed(("Invalid reply header received: %d\n",
     882                                               pProxyDevUsbIp->BufRet.Hdr.u32ReqRet));
     883                        usbProxyUsbIpResetRecvState(pProxyDevUsbIp);
     884                }
     885            }
     886            else
     887            {
     888                AssertMsg(pProxyDevUsbIp->cbRecv > sizeof(UsbIpReqRetHdr), ("Invalid state\n"));
     889
     890                /* Get the URB from the in flight list. */
     891                pProxyDevUsbIp->pUrbUsbIp = usbProxyUsbIpGetUrbFromSeqNum(pProxyDevUsbIp, RT_N2H_U32(pProxyDevUsbIp->BufRet.Hdr.u32SeqNum));
     892                if (pProxyDevUsbIp->pUrbUsbIp)
     893                {
     894                    /** @todo: Verify that the directions match, verify that the length doesn't exceed the buffer. */
     895
     896                    switch (RT_N2H_U32(pProxyDevUsbIp->BufRet.Hdr.u32ReqRet))
     897                    {
     898                        case USBIP_RET_SUBMIT:
     899                            usbProxyUsbIpRetSubmitN2H(&pProxyDevUsbIp->BufRet.RetSubmit);
     900                            pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->enmStatus = usbProxyUsbIpVUsbStatusConvertFromStatus(pProxyDevUsbIp->BufRet.RetSubmit.u32Status);
     901                            if (   pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->enmDir == VUSBDIRECTION_IN
     902                                && pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->enmStatus == VUSBSTATUS_OK)
     903                            {
     904                                pProxyDevUsbIp->fRecvData = true;
     905                                if (pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->enmType == VUSBXFERTYPE_MSG)
     906                                {
     907                                    /* Preserve the setup request. */
     908                                    pProxyDevUsbIp->cbRecv = sizeof(VUSBSETUP);
     909                                    pProxyDevUsbIp->cbLeft = pProxyDevUsbIp->BufRet.RetSubmit.u32ActualLength;
     910                                    pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->cbData = pProxyDevUsbIp->BufRet.RetSubmit.u32ActualLength + sizeof(VUSBSETUP);
     911                                }
     912                                else
     913                                {
     914                                    pProxyDevUsbIp->cbRecv = 0;
     915                                    pProxyDevUsbIp->cbLeft = pProxyDevUsbIp->BufRet.RetSubmit.u32ActualLength;
     916                                    pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->cbData = pProxyDevUsbIp->BufRet.RetSubmit.u32ActualLength;
     917                                }
     918                            }
     919                            else
     920                            {
     921                                Assert(   pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->enmDir == VUSBDIRECTION_OUT
     922                                       || pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->enmStatus != VUSBSTATUS_OK);
     923                                pUrbUsbIp = pProxyDevUsbIp->pUrbUsbIp;
     924                                usbProxyUsbIpResetRecvState(pProxyDevUsbIp);
     925                            }
     926                            break;
     927                        case USBIP_RET_UNLINK:
     928                            usbProxyUsbIpRetUnlinkN2H(&pProxyDevUsbIp->BufRet.RetUnlink);
     929                            pUrbUsbIp = pProxyDevUsbIp->pUrbUsbIp;
     930                            pUrbUsbIp->pVUsbUrb->enmStatus = usbProxyUsbIpVUsbStatusConvertFromStatus(pProxyDevUsbIp->BufRet.RetUnlink.u32Status);
     931                            usbProxyUsbIpResetRecvState(pProxyDevUsbIp);
     932                            break;
     933                    }
     934                }
     935                else
     936                {
     937                    LogRel(("USB/IP: Received reply with sequence number doesn't match any local URB\n", pProxyDevUsbIp->BufRet.Hdr.u32SeqNum));
     938                    usbProxyUsbIpResetRecvState(pProxyDevUsbIp);
     939                }
     940            }
     941        }
     942    }
     943
     944    if (RT_SUCCESS(rc))
     945        *ppUrbUsbIp = pUrbUsbIp;
     946
     947    return rc;
     948}
     949
     950/**
     951 * Worker for queueing an URB on the main I/O thread.
     952 *
     953 * @returns VBox status code.
     954 * @param   pProxyDevUsbIp    The USB/IP proxy device data.
     955 * @param   pUrbUsbIp         The USB/IP URB to queue.
     956 */
     957static int usbProxyUsbIpUrbQueueWorker(PUSBPROXYDEVUSBIP pProxyDevUsbIp, PUSBPROXYURBUSBIP pUrbUsbIp)
     958{
     959    size_t cbData = 0;
     960    void  *pvData = NULL;
     961    PVUSBURB pUrb = pUrbUsbIp->pVUsbUrb;
     962
     963    pUrbUsbIp->u32SeqNumUrb = usbProxyUsbIpSeqNumGet(pProxyDevUsbIp);
     964
     965    UsbIpReqSubmit ReqSubmit;
     966    ReqSubmit.Hdr.u32ReqRet           = USBIP_CMD_SUBMIT;
     967    ReqSubmit.Hdr.u32SeqNum           = pUrbUsbIp->u32SeqNumUrb;
     968    ReqSubmit.Hdr.u32DevId            = pProxyDevUsbIp->u32DevId;
     969    ReqSubmit.Hdr.u32Endpoint         = pUrb->EndPt;
     970    ReqSubmit.Hdr.u32Direction        = pUrb->enmDir == VUSBDIRECTION_IN ? USBIP_DIR_IN : USBIP_DIR_OUT;
     971    ReqSubmit.u32XferFlags            = 0;
     972    if (pUrb->enmDir == VUSBDIRECTION_IN && pUrb->fShortNotOk)
     973        ReqSubmit.u32XferFlags |= USBIP_XFER_FLAGS_SHORT_NOT_OK;
     974
     975    ReqSubmit.u32TransferBufferLength = pUrb->cbData;
     976    ReqSubmit.u32StartFrame           = 0;
     977    ReqSubmit.u32NumIsocPkts          = 0;
     978    ReqSubmit.u32Interval             = 0;
     979
     980    switch (pUrb->enmType)
     981    {
     982        case VUSBXFERTYPE_MSG:
     983            memcpy(&ReqSubmit.Setup, &pUrb->abData, sizeof(ReqSubmit.Setup));
     984            if (pUrb->enmDir == VUSBDIRECTION_OUT)
     985            {
     986                cbData = pUrb->cbData - sizeof(VUSBSETUP);
     987                pvData = pUrb->abData + sizeof(VUSBSETUP);
     988            }
     989            else
     990                cbData = 0;
     991            LogFlowFunc(("Message (Control) URB\n"));
     992            break;
     993        case VUSBXFERTYPE_ISOC:
     994            cbData = pUrb->cbData;
     995            pvData = pUrb->abData;
     996
     997            ReqSubmit.u32XferFlags |= USBIP_XFER_FLAGS_ISO_ASAP;
     998            ReqSubmit.u32NumIsocPkts = pUrb->cIsocPkts;
     999#if 0
     1000            for (unsigned i = 0; i < pUrb->cIsocPkts; i++)
     1001            {
     1002                pUrbLnx->KUrb.iso_frame_desc[i].length = pUrb->aIsocPkts[i].cb;
     1003                pUrbLnx->KUrb.iso_frame_desc[i].actual_length = 0;
     1004                pUrbLnx->KUrb.iso_frame_desc[i].status = 0x7fff;
     1005            }
     1006#else /** @todo: Implement isochronous support */
     1007            usbProxyUsbIpUrbFree(pProxyDevUsbIp, pUrbUsbIp);
     1008            return VERR_NOT_SUPPORTED;
     1009#endif
     1010            break;
     1011        case VUSBXFERTYPE_BULK:
     1012        case VUSBXFERTYPE_INTR:
     1013            if (pUrb->enmDir == VUSBDIRECTION_OUT)
     1014            {
     1015                cbData = pUrb->cbData;
     1016                pvData = pUrb->abData;
     1017            }
     1018            else
     1019                cbData = 0;
     1020            break;
     1021        default:
     1022            usbProxyUsbIpUrbFree(pProxyDevUsbIp, pUrbUsbIp);
     1023            return VERR_INVALID_PARAMETER; /** @todo: better status code. */
     1024    }
     1025
     1026    usbProxyUsbIpReqSubmitH2N(&ReqSubmit);
     1027
     1028    /* Send the command. */
     1029    RTSGBUF SgBufReq;
     1030    RTSGSEG aSegReq[2];
     1031    aSegReq[0].pvSeg = &ReqSubmit;
     1032    aSegReq[0].cbSeg = sizeof(ReqSubmit);
     1033    aSegReq[1].pvSeg = pvData;
     1034    aSegReq[1].cbSeg = cbData;
     1035    RTSgBufInit(&SgBufReq, &aSegReq[0], RT_ELEMENTS(aSegReq));
     1036
     1037    int rc = RTTcpSgWrite(pProxyDevUsbIp->hSocket, &SgBufReq);
     1038    if (RT_SUCCESS(rc))
     1039    {
     1040        /* Link the URB into the list of in flight URBs. */
     1041        usbProxyUsbIpLinkUrb(pProxyDevUsbIp, &pProxyDevUsbIp->ListUrbsInFlight, pUrbUsbIp);
     1042    }
     1043
     1044    return rc;
     1045}
     1046
     1047/**
     1048 * Queues all pending URBs from the list.
     1049 *
     1050 * @returns VBox status code.
     1051 * @param   pProxyDevUsbIp    The USB/IP proxy device data.
     1052 */
     1053static int usbProxyUsbIpUrbsQueuePending(PUSBPROXYDEVUSBIP pProxyDevUsbIp)
     1054{
     1055    RTLISTANCHOR ListUrbsPending;
     1056
     1057    RTListInit(&ListUrbsPending);
     1058    int rc = RTSemFastMutexRequest(pProxyDevUsbIp->hMtxLists);
     1059    AssertRC(rc);
     1060    RTListMove(&ListUrbsPending, &pProxyDevUsbIp->ListUrbsToQueue);
     1061    RTSemFastMutexRelease(pProxyDevUsbIp->hMtxLists);
     1062
     1063    PUSBPROXYURBUSBIP pIter = NULL;
     1064    PUSBPROXYURBUSBIP pIterNext = NULL;
     1065    RTListForEachSafe(&ListUrbsPending, pIter, pIterNext, USBPROXYURBUSBIP, NodeList)
     1066    {
     1067        RTListNodeRemove(&pIter->NodeList);
     1068        rc = usbProxyUsbIpUrbQueueWorker(pProxyDevUsbIp, pIter);
     1069        if (RT_FAILURE(rc))
     1070        {
     1071            /** @todo:  Complete the URB with an error. */
     1072            usbProxyUsbIpUrbFree(pProxyDevUsbIp, pIter);
     1073        }
     1074    }
     1075
     1076    return VINF_SUCCESS;
     1077}
     1078
     1079/**
     1080 * Kick the reaper thread.
     1081 *
     1082 * @returns VBox status code.
     1083 * @param   pProxyDevUsbIp    The USB/IP proxy device data.
     1084 * @param   bReason           The wakeup reason.
     1085 */
     1086static char usbProxyReaperKick(PUSBPROXYDEVUSBIP pProxyDevUsbIp, char bReason)
     1087{
     1088    int rc = VINF_SUCCESS;
     1089    size_t cbWritten = 0;
     1090
     1091    rc = RTPipeWrite(pProxyDevUsbIp->hPipeW, &bReason, 1, &cbWritten);
     1092    Assert(RT_SUCCESS(rc) || cbWritten == 0);
     1093
     1094    return rc;
     1095}
     1096
     1097/**
     1098 * Drain the wakeup pipe.
     1099 *
     1100 * @returns Wakeup reason.
     1101 * @param   pProxyDevUsbIp    The USB/IP proxy device data.
     1102 */
     1103static char usbProxyUsbIpWakeupPipeDrain(PUSBPROXYDEVUSBIP pProxyDevUsbIp)
     1104{
     1105    char bRead = 0;
     1106    size_t cbRead = 0;
     1107
     1108    int rc = RTPipeRead(pProxyDevUsbIp->hPipeR, &bRead, 1, &cbRead);
     1109    Assert(RT_SUCCESS(rc) && cbRead == 1);
     1110
     1111    return bRead;
     1112}
     1113
    8121114/*
    8131115 * The USB proxy device functions.
     
    8231125    RTListInit(&pDevUsbIp->ListUrbsInFlight);
    8241126    RTListInit(&pDevUsbIp->ListUrbsLanded);
     1127    RTListInit(&pDevUsbIp->ListUrbsToQueue);
    8251128    pDevUsbIp->hSocket       = NIL_RTSOCKET;
    8261129    pDevUsbIp->hPollSet      = NIL_RTPOLLSET;
    8271130    pDevUsbIp->hPipeW        = NIL_RTPIPE;
    8281131    pDevUsbIp->hPipeR        = NIL_RTPIPE;
    829     pDevUsbIp->fWokenUp      = false;
    8301132    pDevUsbIp->u32SeqNumNext = 0;
    8311133    pDevUsbIp->pszHost       = NULL;
     
    9291231    LogFlowFunc(("pProxyDev = %p\n", pProxyDev));
    9301232
    931     PUSBPROXYDEVUSBIP pDev = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
     1233    PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
    9321234    return VINF_SUCCESS; /* No way to reset the device with the current protocol. */
    9331235}
     
    9371239    LogFlowFunc(("pProxyDev=%s cfg=%#x\n", pProxyDev->pUsbIns->pszName, iCfg));
    9381240
    939     PUSBPROXYDEVUSBIP pDev = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
     1241    PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
    9401242    VUSBSETUP Setup;
    9411243
     
    9451247    Setup.wIndex        = 0;
    9461248    Setup.wLength       = 0;
    947     return usbProxyUsbIpCtrlUrbExchangeSync(pDev, &Setup);
     1249    return usbProxyUsbIpCtrlUrbExchangeSync(pProxyDevUsbIp, &Setup);
    9481250}
    9491251
     
    9641266    LogFlowFunc(("pProxyDev=%p ifnum=%#x setting=%#x\n", pProxyDev, ifnum, setting));
    9651267
    966     PUSBPROXYDEVUSBIP pDev = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
     1268    PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
    9671269    VUSBSETUP Setup;
    9681270
     
    9721274    Setup.wIndex        = ifnum;
    9731275    Setup.wLength       = 0;
    974     return usbProxyUsbIpCtrlUrbExchangeSync(pDev, &Setup);
     1276    return usbProxyUsbIpCtrlUrbExchangeSync(pProxyDevUsbIp, &Setup);
    9751277}
    9761278
     
    9791281    LogFlowFunc(("pProxyDev=%s ep=%u\n", pProxyDev->pUsbIns->pszName, iEp));
    9801282
    981     PUSBPROXYDEVUSBIP pDev = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
     1283    PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
    9821284    VUSBSETUP Setup;
    9831285
     
    9871289    Setup.wIndex        = iEp;
    9881290    Setup.wLength       = 0;
    989     return usbProxyUsbIpCtrlUrbExchangeSync(pDev, &Setup);
     1291    return usbProxyUsbIpCtrlUrbExchangeSync(pProxyDevUsbIp, &Setup);
    9901292}
    9911293
     
    10011303        return VERR_NO_MEMORY;
    10021304
    1003     pUrbUsbIp->u32SeqNumUrb = usbProxyUsbIpSeqNumGet(pProxyDevUsbIp);
    1004 
    1005     UsbIpReqSubmit ReqSubmit;
    1006     ReqSubmit.Hdr.u32ReqRet           = USBIP_CMD_SUBMIT;
    1007     ReqSubmit.Hdr.u32SeqNum           = pUrbUsbIp->u32SeqNumUrb;
    1008     ReqSubmit.Hdr.u32DevId            = pProxyDevUsbIp->u32DevId;
    1009     ReqSubmit.Hdr.u32Endpoint         = pUrb->EndPt;
    1010     ReqSubmit.Hdr.u32Direction        = pUrb->enmDir == VUSBDIRECTION_IN ? USBIP_DIR_IN : USBIP_DIR_OUT;
    1011     ReqSubmit.u32XferFlags            = 0;
    1012     if (pUrb->enmDir == VUSBDIRECTION_IN && pUrb->fShortNotOk)
    1013         ReqSubmit.u32XferFlags |= USBIP_XFER_FLAGS_SHORT_NOT_OK;
    1014 
    1015     ReqSubmit.u32TransferBufferLength = pUrb->cbData;
    1016     ReqSubmit.u32StartFrame           = 0;
    1017     ReqSubmit.u32NumIsocPkts          = 0;
    1018     ReqSubmit.u32Interval             = 0;
    1019 
    1020     switch (pUrb->enmType)
    1021     {
    1022         case VUSBXFERTYPE_MSG:
    1023             memcpy(&ReqSubmit.Setup, &pUrb->abData, sizeof(ReqSubmit.Setup));
    1024             LogFlowFunc(("Message (Control) URB\n"));
    1025             break;
    1026         case VUSBXFERTYPE_ISOC:
    1027             ReqSubmit.u32XferFlags |= USBIP_XFER_FLAGS_ISO_ASAP;
    1028             ReqSubmit.u32NumIsocPkts = pUrb->cIsocPkts;
    1029 #if 0
    1030             for (unsigned i = 0; i < pUrb->cIsocPkts; i++)
    1031             {
    1032                 pUrbLnx->KUrb.iso_frame_desc[i].length = pUrb->aIsocPkts[i].cb;
    1033                 pUrbLnx->KUrb.iso_frame_desc[i].actual_length = 0;
    1034                 pUrbLnx->KUrb.iso_frame_desc[i].status = 0x7fff;
    1035             }
    1036 #else /** @todo: Implement isochronous support */
    1037             usbProxyUsbIpUrbFree(pProxyDevUsbIp, pUrbUsbIp);
    1038             return VERR_NOT_SUPPORTED;
    1039 #endif
    1040             break;
    1041         case VUSBXFERTYPE_BULK:
    1042         case VUSBXFERTYPE_INTR:
    1043             break;
    1044         default:
    1045             usbProxyUsbIpUrbFree(pProxyDevUsbIp, pUrbUsbIp);
    1046             return VERR_INVALID_PARAMETER; /** @todo: better status code. */
    1047     }
    1048     usbProxyUsbIpReqSubmitH2N(&ReqSubmit);
    1049 
    1050     /* Send the command. */
    1051     RTSGBUF SgBufReq;
    1052     RTSGSEG aSegReq[2];
    1053     aSegReq[0].pvSeg = &ReqSubmit;
    1054     aSegReq[0].cbSeg = sizeof(ReqSubmit);
    1055     aSegReq[1].pvSeg = &pUrb->abData[0];
    1056     aSegReq[1].cbSeg = pUrb->cbData;
    1057     RTSgBufInit(&SgBufReq, &aSegReq[0], RT_ELEMENTS(aSegReq));
    1058 
    1059     int rc = RTTcpSgWrite(pProxyDevUsbIp->hSocket, &SgBufReq);
    1060     if (RT_SUCCESS(rc))
    1061     {
    1062         /* Link the URB into the list of in flight URBs. */
    1063         pUrb->Dev.pvPrivate = pUrbUsbIp;
    1064         pUrbUsbIp->pVUsbUrb = pUrb;
    1065         usbProxyUsbIpLinkUrb(pProxyDevUsbIp, &pProxyDevUsbIp->ListUrbsInFlight, pUrbUsbIp);
    1066     }
    1067     else
    1068         usbProxyUsbIpUrbFree(pProxyDevUsbIp, pUrbUsbIp);
    1069 
    1070     return rc;
     1305    pUrbUsbIp->pVUsbUrb = pUrb;
     1306    pUrb->Dev.pvPrivate = pUrbUsbIp;
     1307
     1308    int rc = RTSemFastMutexRequest(pProxyDevUsbIp->hMtxLists);
     1309    AssertRC(rc);
     1310    RTListAppend(&pProxyDevUsbIp->ListUrbsToQueue, &pUrbUsbIp->NodeList);
     1311    RTSemFastMutexRelease(pProxyDevUsbIp->hMtxLists);
     1312
     1313    return usbProxyReaperKick(pProxyDevUsbIp, USBIP_REAPER_WAKEUP_REASON_QUEUE);
    10711314}
    10721315
     
    10751318    LogFlowFunc(("pProxyDev=%s\n", pProxyDev->pUsbIns->pszName));
    10761319
    1077     PUSBPROXYDEVUSBIP pDev = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
     1320    PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
    10781321    PUSBPROXYURBUSBIP pUrbUsbIp = NULL;
    10791322    PVUSBURB pUrb = NULL;
    10801323    int rc = VINF_SUCCESS;
    10811324
     1325    /* Queue new URBs first. */
     1326    rc = usbProxyUsbIpUrbsQueuePending(pProxyDevUsbIp);
     1327    AssertRC(rc);
     1328
    10821329    /* Any URBs pending delivery? */
    1083     if (!RTListIsEmpty(&pDev->ListUrbsLanded))
    1084         pUrbUsbIp = RTListGetFirst(&pDev->ListUrbsLanded, USBPROXYURBUSBIP, NodeList);
     1330    if (!RTListIsEmpty(&pProxyDevUsbIp->ListUrbsLanded))
     1331        pUrbUsbIp = RTListGetFirst(&pProxyDevUsbIp->ListUrbsLanded, USBPROXYURBUSBIP, NodeList);
    10851332
    10861333    while (!pUrbUsbIp && RT_SUCCESS(rc) && cMillies)
    10871334    {
    1088         if (!ASMAtomicXchgBool(&pDev->fWokenUp, false))
     1335        uint32_t uIdReady = 0;
     1336        uint32_t fEventsRecv = 0;
     1337        RTMSINTERVAL msStart = RTTimeMilliTS();
     1338        RTMSINTERVAL msNow;
     1339
     1340        rc = RTPoll(pProxyDevUsbIp->hPollSet, cMillies, &fEventsRecv, &uIdReady);
     1341        Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT);
     1342        if (RT_SUCCESS(rc))
    10891343        {
    1090             uint32_t uIdReady = 0;
    1091             uint32_t fEventsRecv = 0;
    1092             RTMSINTERVAL msStart = RTTimeMilliTS();
    1093             RTMSINTERVAL msNow;
    1094 
    1095             rc = RTPoll(pDev->hPollSet, cMillies, &fEventsRecv, &uIdReady);
    1096             Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT);
    1097 
    10981344            msNow = RTTimeMilliTS();
    10991345            cMillies = msNow - msStart >= cMillies ? 0 : cMillies - (msNow - msStart);
    11001346
    1101             if (RT_SUCCESS(rc))
     1347            if (uIdReady == USBIP_POLL_ID_SOCKET)
     1348                rc = usbProxyUsbIpRecvPdu(pProxyDevUsbIp, &pUrbUsbIp);
     1349            else
    11021350            {
    1103                 if (uIdReady == USBIP_POLL_ID_SOCKET)
    1104                 {
    1105                     size_t cbRead = 0;
    1106 
    1107                     if (pDev->fRecvData)
    1108                     {
    1109                         /* Read data into the URB. */
    1110                         rc = RTTcpReadNB(pDev->hSocket, &pDev->pUrbUsbIp->pVUsbUrb->abData[pDev->cbRecv], pDev->cbLeft, &cbRead);
    1111                         if (RT_SUCCESS(rc))
    1112                         {
    1113                             if (!pDev->cbLeft)
    1114                             {
    1115                                 pUrbUsbIp = pDev->pUrbUsbIp;
    1116                                 usbProxyUsbIpResetRecvState(pDev);
    1117                             }
    1118                         }
    1119                         else
    1120                         {
    1121                             pUrbUsbIp = pDev->pUrbUsbIp;
    1122                             pUrbUsbIp->pVUsbUrb->enmStatus = VUSBSTATUS_DNR;
    1123                             usbProxyUsbIpResetRecvState(pDev);
    1124                         }
    1125                     }
    1126                     else
    1127                     {
    1128                         rc = RTTcpReadNB(pDev->hSocket, &pDev->BufRet.abReply[pDev->cbRecv], pDev->cbLeft, &cbRead);
    1129                         if (RT_SUCCESS(rc))
    1130                         {
    1131                             pDev->cbRecv += cbRead;
    1132                             pDev->cbLeft -= cbRead;
    1133                         }
    1134 
    1135                         /* Check whether we received a complete header. */
    1136                         if (!pDev->cbLeft)
    1137                         {
    1138                             if (pDev->cbRecv == sizeof(UsbIpReqRetHdr))
    1139                             {
    1140                                 /*
    1141                                  * Determine the residual amount of data to receive until
    1142                                  * the complete reply header was received.
    1143                                  */
    1144                                 switch (RT_N2H_U32(pDev->BufRet.Hdr.u32ReqRet))
    1145                                 {
    1146                                     case USBIP_RET_SUBMIT:
    1147                                         pDev->cbLeft = sizeof(UsbIpRetSubmit) - sizeof(UsbIpReqRetHdr);
    1148                                         break;
    1149                                     case USBIP_RET_UNLINK:
    1150                                         pDev->cbLeft = sizeof(UsbIpRetUnlink) - sizeof(UsbIpReqRetHdr);
    1151                                         break;
    1152                                     default:
    1153                                         AssertLogRelMsgFailed(("Invalid reply header received: %d\n",
    1154                                                                pDev->BufRet.Hdr.u32ReqRet));
    1155                                         usbProxyUsbIpResetRecvState(pDev);
    1156                                 }
    1157                             }
    1158                             else
    1159                             {
    1160                                 AssertMsg(pDev->cbRecv > sizeof(UsbIpReqRetHdr), ("Invalid state\n"));
    1161 
    1162                                 /* Get the URB from the in flight list. */
    1163                                 pDev->pUrbUsbIp = usbProxyUsbIpGetUrbFromSeqNum(pDev, RT_N2H_U32(pDev->BufRet.Hdr.u32SeqNum));
    1164                                 if (pDev->pUrbUsbIp)
    1165                                 {
    1166                                     /** @todo: Verify that the directions match. */
    1167 
    1168                                     switch (RT_N2H_U32(pDev->BufRet.Hdr.u32ReqRet))
    1169                                     {
    1170                                         case USBIP_RET_SUBMIT:
    1171                                             usbProxyUsbIpRetSubmitN2H(&pDev->BufRet.RetSubmit);
    1172                                             pDev->pUrbUsbIp->pVUsbUrb->enmStatus = usbProxyUsbIpVUsbStatusConvertFromStatus(pDev->BufRet.RetSubmit.u32Status);
    1173                                             if (   pDev->BufRet.Hdr.u32Direction == USBIP_DIR_IN
    1174                                                 && pDev->pUrbUsbIp->pVUsbUrb->enmStatus == VUSBSTATUS_OK)
    1175                                             {
    1176                                                 pDev->fRecvData = true;
    1177                                                 pDev->cbRecv = 0;
    1178                                                 pDev->cbLeft = pDev->BufRet.RetSubmit.u32ActualLength;
    1179                                             }
    1180                                             else
    1181                                             {
    1182                                                 Assert(   pDev->BufRet.Hdr.u32Direction == USBIP_DIR_OUT
    1183                                                        || pDev->pUrbUsbIp->pVUsbUrb->enmStatus != VUSBSTATUS_OK);
    1184                                                 pUrbUsbIp = pDev->pUrbUsbIp;
    1185                                                 usbProxyUsbIpResetRecvState(pDev);
    1186                                             }
    1187                                             break;
    1188                                         case USBIP_RET_UNLINK:
    1189                                             usbProxyUsbIpRetUnlinkN2H(&pDev->BufRet.RetUnlink);
    1190                                             pUrbUsbIp = pDev->pUrbUsbIp;
    1191                                             pUrbUsbIp->pVUsbUrb->enmStatus = usbProxyUsbIpVUsbStatusConvertFromStatus(pDev->BufRet.RetUnlink.u32Status);
    1192                                             usbProxyUsbIpResetRecvState(pDev);
    1193                                             break;
    1194                                     }
    1195                                 }
    1196                                 else
    1197                                 {
    1198                                     LogRel(("USB/IP: Received reply with sequence number doesn't match any local URB\n", pDev->BufRet.Hdr.u32SeqNum));
    1199                                     usbProxyUsbIpResetRecvState(pDev);
    1200                                 }
    1201                             }
    1202                         }
    1203                     }
    1204                 }
     1351                AssertLogRelMsg(uIdReady == USBIP_POLL_ID_PIPE, ("Invalid pollset ID given\n"));
     1352
     1353                char bReason = usbProxyUsbIpWakeupPipeDrain(pProxyDevUsbIp);
     1354                if (bReason == USBIP_REAPER_WAKEUP_REASON_QUEUE)
     1355                    usbProxyUsbIpUrbsQueuePending(pProxyDevUsbIp);
    12051356                else
    12061357                {
    1207                     uint8_t bRead = 0;
    1208 
    1209                     AssertLogRelMsg(uIdReady == USBIP_POLL_ID_PIPE, ("Invalid pollset ID given\n"));
    1210                     AssertMsg(pDev->fWokenUp, ("Pipe is not empty but no one woke the reaper thread\n"));
    1211 
    1212                     rc = RTPipeRead(pDev->hPipeR, &bRead, 1, NULL);
    1213                     AssertRC(rc);
    1214                     ASMAtomicXchgBool(&pDev->fWokenUp, false);
     1358                    Assert(bReason == USBIP_REAPER_WAKEUP_REASON_EXTERNAL);
     1359                    break;
    12151360                }
    12161361            }
     
    12231368
    12241369        /* unlink from the pending delivery list */
    1225         usbProxyUsbIpUnlinkUrb(pDev, pUrbUsbIp);
    1226         usbProxyUsbIpUrbFree(pDev, pUrbUsbIp);
     1370        usbProxyUsbIpUnlinkUrb(pProxyDevUsbIp, pUrbUsbIp);
     1371        usbProxyUsbIpUrbFree(pProxyDevUsbIp, pUrbUsbIp);
    12271372    }
    12281373
     
    12461391    ReqUnlink.u32SeqNum               = pUrbUsbIp->u32SeqNumUrb;
    12471392
     1393    usbProxyUsbIpReqUnlinkH2N(&ReqUnlink);
    12481394    return RTTcpWrite(pProxyDevUsbIp->hSocket, &ReqUnlink, sizeof(ReqUnlink));
    12491395}
     
    12531399    LogFlowFunc(("pProxyDev=%s\n", pProxyDev->pUsbIns->pszName));
    12541400
    1255     PUSBPROXYDEVUSBIP pDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
    1256     int rc = VINF_SUCCESS;
    1257 
    1258     if (!ASMAtomicXchgBool(&pDevUsbIp->fWokenUp, true))
    1259     {
    1260         size_t cbWritten = 0;
    1261 
    1262         rc = RTPipeWrite(pDevUsbIp->hPipeW, "", 1, &cbWritten);
    1263         Assert(RT_SUCCESS(rc) || cbWritten == 0);
    1264     }
    1265 
    1266     return rc;
     1401    PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
     1402    return usbProxyReaperKick(pProxyDevUsbIp, USBIP_REAPER_WAKEUP_REASON_EXTERNAL);
    12671403}
    12681404
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