Changeset 57301 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Aug 12, 2015 9:49:22 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/USB/usbip/USBProxyDevice-usbip.cpp
r57273 r57301 72 72 73 73 /** URB direction - input. */ 74 #define USBIP_DIR_IN UINT32_C( 0)74 #define USBIP_DIR_IN UINT32_C(1) 75 75 /** URB direction - output. */ 76 #define USBIP_DIR_OUT UINT32_C( 1)76 #define USBIP_DIR_OUT UINT32_C(0) 77 77 78 78 /** @name USB/IP error codes. … … 333 333 /** Pipe endpoint - write. */ 334 334 RTPIPE hPipeW; 335 /** Flag whether the reaper thread was woken up. */336 volatile bool fWokenUp;337 335 /** Next sequence number to use for identifying submitted URBs. */ 338 336 volatile uint32_t u32SeqNumNext; … … 343 341 /** List of landed URBs. */ 344 342 RTLISTANCHOR ListUrbsLanded; 343 /** List of URBs to submit. */ 344 RTLISTANCHOR ListUrbsToQueue; 345 345 /** Port of the USB/IP host to connect to. */ 346 346 uint32_t uPort; … … 372 372 /** USB/IP address prefix length. */ 373 373 #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' 374 379 375 380 /** … … 810 815 } 811 816 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 */ 826 static 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 */ 957 static 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 */ 1053 static 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 */ 1086 static 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 */ 1103 static 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 812 1114 /* 813 1115 * The USB proxy device functions. … … 823 1125 RTListInit(&pDevUsbIp->ListUrbsInFlight); 824 1126 RTListInit(&pDevUsbIp->ListUrbsLanded); 1127 RTListInit(&pDevUsbIp->ListUrbsToQueue); 825 1128 pDevUsbIp->hSocket = NIL_RTSOCKET; 826 1129 pDevUsbIp->hPollSet = NIL_RTPOLLSET; 827 1130 pDevUsbIp->hPipeW = NIL_RTPIPE; 828 1131 pDevUsbIp->hPipeR = NIL_RTPIPE; 829 pDevUsbIp->fWokenUp = false;830 1132 pDevUsbIp->u32SeqNumNext = 0; 831 1133 pDevUsbIp->pszHost = NULL; … … 929 1231 LogFlowFunc(("pProxyDev = %p\n", pProxyDev)); 930 1232 931 PUSBPROXYDEVUSBIP p Dev= USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);1233 PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP); 932 1234 return VINF_SUCCESS; /* No way to reset the device with the current protocol. */ 933 1235 } … … 937 1239 LogFlowFunc(("pProxyDev=%s cfg=%#x\n", pProxyDev->pUsbIns->pszName, iCfg)); 938 1240 939 PUSBPROXYDEVUSBIP p Dev= USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);1241 PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP); 940 1242 VUSBSETUP Setup; 941 1243 … … 945 1247 Setup.wIndex = 0; 946 1248 Setup.wLength = 0; 947 return usbProxyUsbIpCtrlUrbExchangeSync(p Dev, &Setup);1249 return usbProxyUsbIpCtrlUrbExchangeSync(pProxyDevUsbIp, &Setup); 948 1250 } 949 1251 … … 964 1266 LogFlowFunc(("pProxyDev=%p ifnum=%#x setting=%#x\n", pProxyDev, ifnum, setting)); 965 1267 966 PUSBPROXYDEVUSBIP p Dev= USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);1268 PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP); 967 1269 VUSBSETUP Setup; 968 1270 … … 972 1274 Setup.wIndex = ifnum; 973 1275 Setup.wLength = 0; 974 return usbProxyUsbIpCtrlUrbExchangeSync(p Dev, &Setup);1276 return usbProxyUsbIpCtrlUrbExchangeSync(pProxyDevUsbIp, &Setup); 975 1277 } 976 1278 … … 979 1281 LogFlowFunc(("pProxyDev=%s ep=%u\n", pProxyDev->pUsbIns->pszName, iEp)); 980 1282 981 PUSBPROXYDEVUSBIP p Dev= USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);1283 PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP); 982 1284 VUSBSETUP Setup; 983 1285 … … 987 1289 Setup.wIndex = iEp; 988 1290 Setup.wLength = 0; 989 return usbProxyUsbIpCtrlUrbExchangeSync(p Dev, &Setup);1291 return usbProxyUsbIpCtrlUrbExchangeSync(pProxyDevUsbIp, &Setup); 990 1292 } 991 1293 … … 1001 1303 return VERR_NO_MEMORY; 1002 1304 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); 1071 1314 } 1072 1315 … … 1075 1318 LogFlowFunc(("pProxyDev=%s\n", pProxyDev->pUsbIns->pszName)); 1076 1319 1077 PUSBPROXYDEVUSBIP p Dev= USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);1320 PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP); 1078 1321 PUSBPROXYURBUSBIP pUrbUsbIp = NULL; 1079 1322 PVUSBURB pUrb = NULL; 1080 1323 int rc = VINF_SUCCESS; 1081 1324 1325 /* Queue new URBs first. */ 1326 rc = usbProxyUsbIpUrbsQueuePending(pProxyDevUsbIp); 1327 AssertRC(rc); 1328 1082 1329 /* Any URBs pending delivery? */ 1083 if (!RTListIsEmpty(&p Dev->ListUrbsLanded))1084 pUrbUsbIp = RTListGetFirst(&p Dev->ListUrbsLanded, USBPROXYURBUSBIP, NodeList);1330 if (!RTListIsEmpty(&pProxyDevUsbIp->ListUrbsLanded)) 1331 pUrbUsbIp = RTListGetFirst(&pProxyDevUsbIp->ListUrbsLanded, USBPROXYURBUSBIP, NodeList); 1085 1332 1086 1333 while (!pUrbUsbIp && RT_SUCCESS(rc) && cMillies) 1087 1334 { 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)) 1089 1343 { 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 1098 1344 msNow = RTTimeMilliTS(); 1099 1345 cMillies = msNow - msStart >= cMillies ? 0 : cMillies - (msNow - msStart); 1100 1346 1101 if (RT_SUCCESS(rc)) 1347 if (uIdReady == USBIP_POLL_ID_SOCKET) 1348 rc = usbProxyUsbIpRecvPdu(pProxyDevUsbIp, &pUrbUsbIp); 1349 else 1102 1350 { 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); 1205 1356 else 1206 1357 { 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; 1215 1360 } 1216 1361 } … … 1223 1368 1224 1369 /* unlink from the pending delivery list */ 1225 usbProxyUsbIpUnlinkUrb(p Dev, pUrbUsbIp);1226 usbProxyUsbIpUrbFree(p Dev, pUrbUsbIp);1370 usbProxyUsbIpUnlinkUrb(pProxyDevUsbIp, pUrbUsbIp); 1371 usbProxyUsbIpUrbFree(pProxyDevUsbIp, pUrbUsbIp); 1227 1372 } 1228 1373 … … 1246 1391 ReqUnlink.u32SeqNum = pUrbUsbIp->u32SeqNumUrb; 1247 1392 1393 usbProxyUsbIpReqUnlinkH2N(&ReqUnlink); 1248 1394 return RTTcpWrite(pProxyDevUsbIp->hSocket, &ReqUnlink, sizeof(ReqUnlink)); 1249 1395 } … … 1253 1399 LogFlowFunc(("pProxyDev=%s\n", pProxyDev->pUsbIns->pszName)); 1254 1400 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); 1267 1403 } 1268 1404
Note:
See TracChangeset
for help on using the changeset viewer.