VirtualBox

Changeset 57262 in vbox for trunk/src/VBox/Devices/USB


Ignore:
Timestamp:
Aug 10, 2015 12:50:53 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
102017
Message:

USB/UsbIp: Updates, implement receiving response handling

File:
1 edited

Legend:

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

    r56292 r57262  
    340340    /** The device ID to use to identify the device. */
    341341    uint32_t          u32DevId;
     342    /** Temporary buffer for the next reply header */
     343    UsbIpRet          BufRet;
     344    /** Number of bytes received so far. */
     345    size_t            cbRecv;
     346    /** Number of bytes left to receive. */
     347    size_t            cbLeft;
     348    /** Flag whether we are currently receiving data for an URB. */
     349    bool              fRecvData;
     350    /** The URB we currently receive a response for. */
     351    PUSBPROXYURBUSBIP pUrbUsbIp;
    342352} USBPROXYDEVUSBIP, *PUSBPROXYDEVUSBIP;
    343353
     
    461471
    462472    return VERR_NOT_IMPLEMENTED;
     473}
     474
     475/**
     476 * Converts a USB/IP status code to a VUSB status code.
     477 *
     478 * @returns VUSB status code.
     479 * @param   u32Status    The USB/IP status code from the reply.
     480 */
     481DECLINLINE(VUSBSTATUS) usbProxyUsbIpVUsbStatusConvertFromStatus(uint32_t u32Status)
     482{
     483    if (RT_LIKELY(u32Status == 0))
     484        return VUSBSTATUS_OK;
     485
     486    return VUSBSTATUS_DNR;
    463487}
    464488
     
    716740}
    717741
     742/**
     743 * Returns the URB matching the given sequence number from the in flight list.
     744 *
     745 * @returns pointer to the URB matching the given sequence number or NULL
     746 * @param  pProxyDevUsbIp    The USB/IP proxy device data.
     747 * @param  u32SeqNum         The sequence number to search for.
     748 */
     749static PUSBPROXYURBUSBIP usbProxyUsbIpGetUrbFromSeqNum(PUSBPROXYDEVUSBIP pProxyDevUsbIp, uint32_t u32SeqNum)
     750{
     751    bool fFound = false;
     752    PUSBPROXYURBUSBIP pIt;
     753
     754    RTListForEach(&pProxyDevUsbIp->ListUrbsInFlight, pIt, USBPROXYURBUSBIP, NodeList)
     755    {
     756        if (pIt->u32SeqNumUrb == u32SeqNum)
     757        {
     758            fFound = true;
     759            break;
     760        }
     761    }
     762
     763    return fFound ? pIt : NULL;
     764}
     765
     766/**
     767 * Resets the receive state for a new reply.
     768 *
     769 * @returns nothing.
     770 * @param  pProxyDevUsbIp    The USB/IP proxy device data.
     771 */
     772static void usbProxyUsbIpResetRecvState(PUSBPROXYDEVUSBIP pProxyDevUsbIp)
     773{
     774    pProxyDevUsbIp->fRecvData = false;
     775    pProxyDevUsbIp->cbRecv    = 0;
     776    pProxyDevUsbIp->cbLeft    = sizeof(UsbIpReqRetHdr);
     777}
     778
    718779/*
    719780 * The USB proxy device functions.
     
    737798    pDevUsbIp->pszHost       = NULL;
    738799    pDevUsbIp->pszBusId      = NULL;
     800    pDevUsbIp->cbRecv        = 0;
     801    pDevUsbIp->cbLeft        = sizeof(UsbIpReqRetHdr);
     802    pDevUsbIp->fRecvData     = false;
    739803
    740804    /* Setup wakeup pipe and poll set first. */
     
    9931057    if (!pUrbUsbIp)
    9941058    {
    995         uint32_t uIdReady = 0;
    996         uint32_t fEventsRecv = 0;
    997 
    9981059        if (!ASMAtomicXchgBool(&pDev->fWokenUp, false))
    9991060        {
    1000             int rc = RTPoll(pDev->hPollSet, cMillies, &fEventsRecv, &uIdReady);
     1061            int rc = VINF_SUCCESS;
     1062            uint32_t uIdReady = 0;
     1063            uint32_t fEventsRecv = 0;
     1064
     1065            rc = RTPoll(pDev->hPollSet, cMillies, &fEventsRecv, &uIdReady);
    10011066            Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT);
     1067
     1068            if (RT_SUCCESS(rc))
     1069            {
     1070                if (uIdReady == USBIP_POLL_ID_SOCKET)
     1071                {
     1072                    size_t cbRead = 0;
     1073
     1074                    if (pDev->fRecvData)
     1075                    {
     1076                        /* Read data into the URB. */
     1077                        rc = RTTcpReadNB(pDev->hSocket, &pDev->pUrbUsbIp->pVUsbUrb->abData[pDev->cbRecv], pDev->cbLeft, &cbRead);
     1078                        if (RT_SUCCESS(rc))
     1079                        {
     1080                            if (!pDev->cbLeft)
     1081                            {
     1082                                pUrbUsbIp = pDev->pUrbUsbIp;
     1083                                usbProxyUsbIpResetRecvState(pDev);
     1084                            }
     1085                        }
     1086                        else
     1087                        {
     1088                            pUrbUsbIp = pDev->pUrbUsbIp;
     1089                            pUrbUsbIp->pVUsbUrb->enmStatus = VUSBSTATUS_DNR;
     1090                            usbProxyUsbIpResetRecvState(pDev);
     1091                        }
     1092                    }
     1093                    else
     1094                    {
     1095                        rc = RTTcpReadNB(pDev->hSocket, &pDev->BufRet.abReply[pDev->cbRecv], pDev->cbLeft, &cbRead);
     1096                        if (RT_SUCCESS(rc))
     1097                        {
     1098                            pDev->cbRecv += cbRead;
     1099                            pDev->cbLeft -= cbRead;
     1100                        }
     1101
     1102                        /* Check whether we received a complete header. */
     1103                        if (!pDev->cbLeft)
     1104                        {
     1105                            if (pDev->cbRecv == sizeof(UsbIpReqRetHdr))
     1106                            {
     1107                                /*
     1108                                 * Determine the residual amount of data to receive until
     1109                                 * the complete reply header was received.
     1110                                 */
     1111                                switch (pDev->BufRet.Hdr.u32ReqRet)
     1112                                {
     1113                                    case USBIP_RET_SUBMIT:
     1114                                        pDev->cbLeft = sizeof(UsbIpRetSubmit) - sizeof(UsbIpReqRetHdr);
     1115                                        break;
     1116                                    case USBIP_RET_UNLINK:
     1117                                        pDev->cbLeft = sizeof(UsbIpRetUnlink) - sizeof(UsbIpReqRetHdr);
     1118                                        break;
     1119                                    default:
     1120                                        AssertLogRelMsgFailed(("Invalid reply header received: %d",
     1121                                                               pDev->BufRet.Hdr.u32ReqRet));
     1122                                        usbProxyUsbIpResetRecvState(pDev);
     1123                                }
     1124                            }
     1125                            else
     1126                            {
     1127                                AssertMsg(pDev->cbRecv > sizeof(UsbIpReqRetHdr), ("Invalid state\n"));
     1128
     1129                                /* Get the URB from the in flight list. */
     1130                                pDev->pUrbUsbIp = usbProxyUsbIpGetUrbFromSeqNum(pDev, pDev->BufRet.Hdr.u32SeqNum);
     1131                                if (pDev->pUrbUsbIp)
     1132                                {
     1133                                    /** @todo: Verify that the directions match. */
     1134
     1135                                    switch (pDev->BufRet.Hdr.u32ReqRet)
     1136                                    {
     1137                                        case USBIP_RET_SUBMIT:
     1138                                            pDev->pUrbUsbIp->pVUsbUrb->enmStatus = usbProxyUsbIpVUsbStatusConvertFromStatus(pDev->BufRet.RetSubmit.u32Status);
     1139                                            if (pDev->BufRet.Hdr.u32Direction == USBIP_DIR_IN)
     1140                                            {
     1141                                                pDev->fRecvData = true;
     1142                                                pDev->cbRecv = 0;
     1143                                                pDev->cbLeft = pDev->BufRet.RetSubmit.u32ActualLength;
     1144                                            }
     1145                                            else
     1146                                            {
     1147                                                Assert(pDev->BufRet.Hdr.u32Direction == USBIP_DIR_OUT);
     1148                                                pUrbUsbIp = pDev->pUrbUsbIp;
     1149                                                usbProxyUsbIpResetRecvState(pDev);
     1150                                            }
     1151                                            break;
     1152                                        case USBIP_RET_UNLINK:
     1153                                            pUrbUsbIp = pDev->pUrbUsbIp;
     1154                                            pUrbUsbIp->pVUsbUrb->enmStatus = usbProxyUsbIpVUsbStatusConvertFromStatus(pDev->BufRet.RetUnlink.u32Status);
     1155                                            usbProxyUsbIpResetRecvState(pDev);
     1156                                            break;
     1157                                    }
     1158                                }
     1159                                else
     1160                                {
     1161                                    LogRel(("USB/IP: Received reply with sequence number doesn't match any local URB\n", pDev->BufRet.Hdr.u32SeqNum));
     1162                                    usbProxyUsbIpResetRecvState(pDev);
     1163                                }
     1164                            }
     1165                        }
     1166                    }
     1167                }
     1168                else
     1169                {
     1170                    uint8_t bRead = 0;
     1171
     1172                    AssertLogRelMsg(uIdReady == USBIP_POLL_ID_PIPE, ("Invalid pollset ID given\n"));
     1173                    AssertMsg(pDev->fWokenUp, ("Pipe is not empty but no one woke the reaper thread\n"));
     1174
     1175                    rc = RTPipeRead(pDev->hPipeR, &bRead, 1, NULL);
     1176                    AssertRC(rc);
     1177                    ASMAtomicXchgBool(&pDev->fWokenUp, false);
     1178                }
     1179            }
    10021180        }
    1003 
    1004         UsbIpRet Reply;
    10051181    }
    10061182
    10071183    if (pUrbUsbIp)
    10081184    {
    1009 
     1185        pUrb = pUrbUsbIp->pVUsbUrb;
     1186        usbProxyUsbIpUrbFree(pDev, pUrbUsbIp);
    10101187    }
    10111188
     
    10291206    ReqUnlink.u32SeqNum               = pUrbUsbIp->u32SeqNumUrb;
    10301207
    1031     int rc = RTTcpWrite(pProxyDevUsbIp->hSocket, &ReqUnlink, sizeof(ReqUnlink));
    1032     /* Wait for the reply. */
    1033     return rc;
     1208    return RTTcpWrite(pProxyDevUsbIp->hSocket, &ReqUnlink, sizeof(ReqUnlink));
    10341209}
    10351210
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