Changeset 75582 in vbox
- Timestamp:
- Nov 19, 2018 5:02:46 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/USB/usbip/USBProxyDevice-usbip.cpp
r72054 r75582 349 349 /** Flag whether the URB was cancelled. */ 350 350 bool fCancelled; 351 /** USB xfer type. */ 352 VUSBXFERTYPE enmType; 353 /** USB xfer direction. */ 354 VUSBDIRECTION enmDir; 355 /** Completion status. */ 356 VUSBSTATUS enmStatus; 351 357 /** Pointer to the VUSB URB. */ 352 358 PVUSBURB pVUsbUrb; … … 623 629 DECLINLINE(uint32_t) usbProxyUsbIpSeqNumGet(PUSBPROXYDEVUSBIP pProxyDevUsbIp) 624 630 { 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; 626 636 } 627 637 … … 844 854 845 855 /** 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 *ClearHaltedEp853 * 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 called855 * 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 do881 {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_AGAIN897 && iTry++ < 10);898 return rc;899 }900 901 /**902 856 * Returns the URB matching the given sequence number from the in flight list. 903 857 * … … 910 864 bool fFound = false; 911 865 866 int rc = RTSemFastMutexRequest(pProxyDevUsbIp->hMtxLists); 867 AssertRC(rc); 912 868 PUSBPROXYURBUSBIP pIt; 913 869 RTListForEach(&pProxyDevUsbIp->ListUrbsInFlight, pIt, USBPROXYURBUSBIP, NodeList) … … 919 875 } 920 876 } 877 RTSemFastMutexRelease(pProxyDevUsbIp->hMtxLists); 921 878 922 879 return fFound ? pIt : NULL; … … 934 891 bool fFound = false; 935 892 893 int rc = RTSemFastMutexRequest(pProxyDevUsbIp->hMtxLists); 894 AssertRC(rc); 936 895 PUSBPROXYURBUSBIP pIt; 937 896 RTListForEach(&pProxyDevUsbIp->ListUrbsInFlight, pIt, USBPROXYURBUSBIP, NodeList) … … 944 903 } 945 904 } 905 RTSemFastMutexRelease(pProxyDevUsbIp->hMtxLists); 946 906 947 907 return fFound ? pIt : NULL; … … 1041 1001 1042 1002 /* 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) 1045 1005 { 1046 1006 uint8_t *pbData = NULL; 1047 1007 1048 if (pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->enmType == VUSBXFERTYPE_MSG) 1008 AssertPtr(pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb); 1009 if (pProxyDevUsbIp->pUrbUsbIp->enmType == VUSBXFERTYPE_MSG) 1049 1010 { 1050 1011 /* Preserve the setup request. */ … … 1069 1030 else 1070 1031 { 1071 Assert(pProxyDevUsbIp->pUrbUsbIp-> pVUsbUrb->enmDir == VUSBDIRECTION_OUT);1032 Assert(pProxyDevUsbIp->pUrbUsbIp->enmDir == VUSBDIRECTION_OUT); 1072 1033 pUrbUsbIp = pProxyDevUsbIp->pUrbUsbIp; 1073 1034 usbProxyUsbIpResetRecvState(pProxyDevUsbIp); … … 1076 1037 else 1077 1038 { 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))); 1079 1041 usbProxyUsbIpResetRecvState(pProxyDevUsbIp); 1080 1042 } … … 1154 1116 1155 1117 pUrbUsbIp->u32SeqNumUrb = usbProxyUsbIpSeqNumGet(pProxyDevUsbIp); 1118 pUrbUsbIp->enmType = pUrb->enmType; 1119 pUrbUsbIp->enmStatus = pUrb->enmStatus; 1120 pUrbUsbIp->enmDir = pUrb->enmDir; 1156 1121 1157 1122 UsbIpReqSubmit ReqSubmit; … … 1318 1283 } 1319 1284 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 */ 1296 static 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 */ 1376 static 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 1320 1425 /* 1321 1426 * The USB proxy device functions. … … 1597 1702 if (!RTListIsEmpty(&pProxyDevUsbIp->ListUrbsLanded)) 1598 1703 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); 1631 1706 1632 1707 if (pUrbUsbIp) 1633 1708 { 1634 1709 pUrb = pUrbUsbIp->pVUsbUrb; 1710 pUrb->enmStatus = pUrbUsbIp->enmStatus; 1635 1711 1636 1712 /* unlink from the pending delivery list */
Note:
See TracChangeset
for help on using the changeset viewer.