Changeset 93914 in vbox for trunk/src/VBox/Devices/USB/DrvVUSBRootHub.cpp
- Timestamp:
- Feb 24, 2022 12:20:43 PM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/USB/DrvVUSBRootHub.cpp
r93115 r93914 220 220 221 221 222 #define VUSB_ROOTHUB_SAVED_STATE_VERSION 1 223 224 225 /** 226 * Data used for reattaching devices on a state load. 227 */ 228 typedef struct VUSBROOTHUBLOAD 229 { 230 /** Timer used once after state load to inform the guest about new devices. 231 * We do this to be sure the guest get any disconnect / reconnect on the 232 * same port. */ 233 TMTIMERHANDLE hTimer; 234 /** Number of detached devices. */ 235 unsigned cDevs; 236 /** Array of devices which were detached. */ 237 PVUSBDEV apDevs[VUSB_DEVICES_MAX]; 238 } VUSBROOTHUBLOAD; 239 240 241 /** 242 * Returns the attached VUSB device for the given port or NULL if none is attached. 243 * 244 * @returns Pointer to the VUSB device or NULL if not found. 245 * @param pThis The VUSB roothub device instance. 246 * @param uPort The port to get the device for. 247 * 248 * @note The reference count of the VUSB device structure is retained to prevent it from going away. 249 */ 250 static PVUSBDEV vusbR3RhGetVUsbDevByPortRetain(PVUSBROOTHUB pThis, uint32_t uPort) 251 { 252 PVUSBDEV pDev = NULL; 253 254 AssertReturn(uPort < RT_ELEMENTS(pThis->apDevByPort), NULL); 255 256 RTCritSectEnter(&pThis->CritSectDevices); 257 258 pDev = pThis->apDevByPort[uPort]; 259 if (RT_LIKELY(pDev)) 260 ASMAtomicIncU32(&pDev->cRefs); 261 262 RTCritSectLeave(&pThis->CritSectDevices); 263 264 return pDev; 265 } 266 222 267 223 268 /** … … 375 420 * Worker routine for vusbRhConnNewUrb(). 376 421 */ 377 static PVUSBURB vusbRhNewUrb(PVUSBROOTHUB pRh, uint8_t DstAddress, PVUSBDEV pDev, VUSBXFERTYPE enmType,422 static PVUSBURB vusbRhNewUrb(PVUSBROOTHUB pRh, uint8_t DstAddress, uint32_t uPort, VUSBXFERTYPE enmType, 378 423 VUSBDIRECTION enmDir, uint32_t cbData, uint32_t cTds, const char *pszTag) 379 424 { … … 387 432 } 388 433 389 if (!pDev) 434 PVUSBDEV pDev; 435 if (uPort == VUSB_DEVICE_PORT_INVALID) 390 436 pDev = vusbRhFindDevByAddress(pRh, DstAddress); 391 437 else 392 vusbDevRetain(pDev);438 pDev = vusbR3RhGetVUsbDevByPortRetain(pRh, uPort); 393 439 394 440 if (pDev) … … 631 677 632 678 679 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnReset} */ 680 static DECLCALLBACK(int) vusbR3RhReset(PVUSBIROOTHUBCONNECTOR pInterface, bool fResetOnLinux) 681 { 682 PVUSBROOTHUB pRh = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 683 return pRh->pIRhPort->pfnReset(pRh->pIRhPort, fResetOnLinux); 684 } 685 686 687 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnPowerOn} */ 688 static DECLCALLBACK(int) vusbR3RhPowerOn(PVUSBIROOTHUBCONNECTOR pInterface) 689 { 690 PVUSBROOTHUB pRh = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 691 LogFlow(("vusR3bRhPowerOn: pRh=%p\n", pRh)); 692 693 Assert( pRh->Hub.Dev.enmState != VUSB_DEVICE_STATE_DETACHED 694 && pRh->Hub.Dev.enmState != VUSB_DEVICE_STATE_RESET); 695 696 if (pRh->Hub.Dev.enmState == VUSB_DEVICE_STATE_ATTACHED) 697 pRh->Hub.Dev.enmState = VUSB_DEVICE_STATE_POWERED; 698 699 return VINF_SUCCESS; 700 } 701 702 703 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnPowerOff} */ 704 static DECLCALLBACK(int) vusbR3RhPowerOff(PVUSBIROOTHUBCONNECTOR pInterface) 705 { 706 PVUSBROOTHUB pThis = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 707 LogFlow(("vusbR3RhDevPowerOff: pThis=%p\n", pThis)); 708 709 Assert( pThis->Hub.Dev.enmState != VUSB_DEVICE_STATE_DETACHED 710 && pThis->Hub.Dev.enmState != VUSB_DEVICE_STATE_RESET); 711 712 /* 713 * Cancel all URBs and reap them. 714 */ 715 VUSBIRhCancelAllUrbs(&pThis->IRhConnector); 716 for (uint32_t uPort = 0; uPort < RT_ELEMENTS(pThis->apDevByPort); uPort++) 717 VUSBIRhReapAsyncUrbs(&pThis->IRhConnector, uPort, 0); 718 719 pThis->Hub.Dev.enmState = VUSB_DEVICE_STATE_ATTACHED; 720 return VINF_SUCCESS; 721 } 722 723 633 724 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnNewUrb} */ 634 static DECLCALLBACK(PVUSBURB) vusbRhConnNewUrb(PVUSBIROOTHUBCONNECTOR pInterface, uint8_t DstAddress, PVUSBIDEVICE pDev, VUSBXFERTYPE enmType,725 static DECLCALLBACK(PVUSBURB) vusbRhConnNewUrb(PVUSBIROOTHUBCONNECTOR pInterface, uint8_t DstAddress, uint32_t uPort, VUSBXFERTYPE enmType, 635 726 VUSBDIRECTION enmDir, uint32_t cbData, uint32_t cTds, const char *pszTag) 636 727 { 637 728 PVUSBROOTHUB pRh = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 638 return vusbRhNewUrb(pRh, DstAddress, (PVUSBDEV)pDev, enmType, enmDir, cbData, cTds, pszTag);729 return vusbRhNewUrb(pRh, DstAddress, uPort, enmType, enmDir, cbData, cTds, pszTag); 639 730 } 640 731 … … 760 851 761 852 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnReapAsyncUrbs} */ 762 static DECLCALLBACK(void) vusbRhReapAsyncUrbs(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice, RTMSINTERVAL cMillies)853 static DECLCALLBACK(void) vusbRhReapAsyncUrbs(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, RTMSINTERVAL cMillies) 763 854 { 764 855 PVUSBROOTHUB pRh = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); NOREF(pRh); 765 PVUSBDEV pDev = (PVUSBDEV)pDevice; 766 767 if (RTListIsEmpty(&pDev->LstAsyncUrbs)) 856 PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pRh, uPort); 857 858 if ( !pDev 859 || RTListIsEmpty(&pDev->LstAsyncUrbs)) 768 860 return; 769 861 … … 772 864 AssertRC(rc); 773 865 STAM_PROFILE_STOP(&pRh->StatReapAsyncUrbs, a); 866 867 vusbDevRelease(pDev); 774 868 } 775 869 … … 871 965 872 966 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnAbortEp} */ 873 static DECLCALLBACK(int) vusbRhAbortEp(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice, int EndPt, VUSBDIRECTION enmDir)967 static DECLCALLBACK(int) vusbRhAbortEp(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, int EndPt, VUSBDIRECTION enmDir) 874 968 { 875 969 PVUSBROOTHUB pRh = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 876 if (&pRh->Hub != ((PVUSBDEV)pDevice)->pHub) 970 PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pRh, uPort); 971 972 if (&pRh->Hub != pDev->pHub) 877 973 AssertFailedReturn(VERR_INVALID_PARAMETER); 878 974 879 RTCritSectEnter(&pRh->CritSectDevices);880 PVUSBDEV pDev = (PVUSBDEV)pDevice;881 975 vusbDevIoThreadExecSync(pDev, (PFNRT)vusbRhAbortEpWorker, 3, pDev, EndPt, enmDir); 882 RTCritSectLeave(&pRh->CritSectDevices);976 vusbDevRelease(pDev); 883 977 884 978 /* The reaper thread will take care of completing the URB. */ 885 979 886 980 return VINF_SUCCESS; 887 }888 889 890 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnAttachDevice} */891 static DECLCALLBACK(int) vusbRhAttachDevice(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice)892 {893 PVUSBROOTHUB pRh = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface);894 return vusbHubAttach(&pRh->Hub, (PVUSBDEV)pDevice);895 }896 897 898 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnDetachDevice} */899 static DECLCALLBACK(int) vusbRhDetachDevice(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice)900 {901 PVUSBROOTHUB pRh = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface);902 if (&pRh->Hub != ((PVUSBDEV)pDevice)->pHub)903 AssertFailedReturn(VERR_INVALID_PARAMETER);904 return vusbDevDetach((PVUSBDEV)pDevice);905 981 } 906 982 … … 980 1056 981 1057 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnUpdateIsocFrameDelta} */ 982 static DECLCALLBACK(uint32_t) vusbRhUpdateIsocFrameDelta(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice,1058 static DECLCALLBACK(uint32_t) vusbRhUpdateIsocFrameDelta(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, 983 1059 int EndPt, VUSBDIRECTION enmDir, uint16_t uNewFrameID, uint8_t uBits) 984 1060 { 985 1061 PVUSBROOTHUB pRh = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 986 1062 AssertReturn(pRh, 0); 987 PVUSBDEV pDev = (PVUSBDEV)pDevice;1063 PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pRh, uPort); AssertPtr(pDev); 988 1064 PVUSBPIPE pPipe = &pDev->aPipes[EndPt]; 989 1065 uint32_t *puLastFrame; … … 998 1074 uFrameDelta += uMaxVal; 999 1075 1076 vusbDevRelease(pDev); 1000 1077 return (uint16_t)uFrameDelta; 1001 1078 } 1002 1079 1003 /* -=-=-=-=-=- VUSB Device methods (for the root hub) -=-=-=-=-=- */ 1004 1005 1006 /** 1007 * @interface_method_impl{VUSBIDEVICE,pfnReset} 1008 */ 1009 static DECLCALLBACK(int) vusbRhDevReset(PVUSBIDEVICE pInterface, bool fResetOnLinux, 1010 PFNVUSBRESETDONE pfnDone, void *pvUser, PVM pVM) 1011 { 1012 RT_NOREF(pfnDone, pvUser, pVM); 1013 PVUSBROOTHUB pRh = RT_FROM_MEMBER(pInterface, VUSBROOTHUB, Hub.Dev.IDevice); 1014 Assert(!pfnDone); 1015 return pRh->pIRhPort->pfnReset(pRh->pIRhPort, fResetOnLinux); /** @todo change rc from bool to vbox status everywhere! */ 1016 } 1017 1018 1019 /** 1020 * @interface_method_impl{VUSBIDEVICE,pfnPowerOn} 1021 */ 1022 static DECLCALLBACK(int) vusbRhDevPowerOn(PVUSBIDEVICE pInterface) 1023 { 1024 PVUSBROOTHUB pRh = RT_FROM_MEMBER(pInterface, VUSBROOTHUB, Hub.Dev.IDevice); 1025 LogFlow(("vusbRhDevPowerOn: pRh=%p\n", pRh)); 1026 1027 Assert( pRh->Hub.Dev.enmState != VUSB_DEVICE_STATE_DETACHED 1028 && pRh->Hub.Dev.enmState != VUSB_DEVICE_STATE_RESET); 1029 1030 if (pRh->Hub.Dev.enmState == VUSB_DEVICE_STATE_ATTACHED) 1031 pRh->Hub.Dev.enmState = VUSB_DEVICE_STATE_POWERED; 1032 1033 return VINF_SUCCESS; 1034 } 1035 1036 1037 /** 1038 * @interface_method_impl{VUSBIDEVICE,pfnPowerOff} 1039 */ 1040 static DECLCALLBACK(int) vusbRhDevPowerOff(PVUSBIDEVICE pInterface) 1041 { 1042 PVUSBROOTHUB pRh = RT_FROM_MEMBER(pInterface, VUSBROOTHUB, Hub.Dev.IDevice); 1043 LogFlow(("vusbRhDevPowerOff: pRh=%p\n", pRh)); 1044 1045 Assert( pRh->Hub.Dev.enmState != VUSB_DEVICE_STATE_DETACHED 1046 && pRh->Hub.Dev.enmState != VUSB_DEVICE_STATE_RESET); 1047 1048 /* 1049 * Cancel all URBs and reap them. 1050 */ 1051 VUSBIRhCancelAllUrbs(&pRh->IRhConnector); 1052 RTCritSectEnter(&pRh->CritSectDevices); 1053 PVUSBDEV pDev = pRh->pDevices; 1054 while (pDev) 1055 { 1056 VUSBIRhReapAsyncUrbs(&pRh->IRhConnector, (PVUSBIDEVICE)pDev, 0); 1057 pDev = pDev->pNext; 1058 } 1059 RTCritSectLeave(&pRh->CritSectDevices); 1060 1061 pRh->Hub.Dev.enmState = VUSB_DEVICE_STATE_ATTACHED; 1062 return VINF_SUCCESS; 1063 } 1064 1065 /** 1066 * @interface_method_impl{VUSBIDEVICE,pfnGetState} 1067 */ 1068 static DECLCALLBACK(VUSBDEVICESTATE) vusbRhDevGetState(PVUSBIDEVICE pInterface) 1069 { 1070 PVUSBROOTHUB pRh = RT_FROM_MEMBER(pInterface, VUSBROOTHUB, Hub.Dev.IDevice); 1071 return pRh->Hub.Dev.enmState; 1080 1081 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnDevReset} */ 1082 static DECLCALLBACK(int) vusbR3RhDevReset(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, bool fResetOnLinux, 1083 PFNVUSBRESETDONE pfnDone, void *pvUser, PVM pVM) 1084 { 1085 PVUSBROOTHUB pThis = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 1086 PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pThis, uPort); 1087 AssertPtr(pDev); 1088 1089 int rc = VUSBIDevReset(&pDev->IDevice, fResetOnLinux, pfnDone, pvUser, pVM); 1090 vusbDevRelease(pDev); 1091 return rc; 1092 } 1093 1094 1095 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnDevPowerOn} */ 1096 static DECLCALLBACK(int) vusbR3RhDevPowerOn(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort) 1097 { 1098 PVUSBROOTHUB pThis = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 1099 PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pThis, uPort); 1100 AssertPtr(pDev); 1101 1102 int rc = VUSBIDevPowerOn(&pDev->IDevice); 1103 vusbDevRelease(pDev); 1104 return rc; 1105 } 1106 1107 1108 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnDevPowerOff} */ 1109 static DECLCALLBACK(int) vusbR3RhDevPowerOff(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort) 1110 { 1111 PVUSBROOTHUB pThis = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 1112 PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pThis, uPort); 1113 AssertPtr(pDev); 1114 1115 int rc = VUSBIDevPowerOff(&pDev->IDevice); 1116 vusbDevRelease(pDev); 1117 return rc; 1118 } 1119 1120 1121 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnDevGetState} */ 1122 static DECLCALLBACK(VUSBDEVICESTATE) vusbR3RhDevGetState(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort) 1123 { 1124 PVUSBROOTHUB pThis = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 1125 PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pThis, uPort); 1126 AssertPtr(pDev); 1127 1128 VUSBDEVICESTATE enmState = VUSBIDevGetState(&pDev->IDevice); 1129 vusbDevRelease(pDev); 1130 return enmState; 1131 } 1132 1133 1134 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnIsSavedStateSupported} */ 1135 static DECLCALLBACK(bool) vusbR3RhDevIsSavedStateSupported(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort) 1136 { 1137 PVUSBROOTHUB pThis = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 1138 PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pThis, uPort); 1139 AssertPtr(pDev); 1140 1141 bool fSavedStateSupported = VUSBIDevIsSavedStateSupported(&pDev->IDevice); 1142 vusbDevRelease(pDev); 1143 return fSavedStateSupported; 1144 } 1145 1146 1147 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnDevGetSpeed} */ 1148 static DECLCALLBACK(VUSBSPEED) vusbR3RhDevGetSpeed(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort) 1149 { 1150 PVUSBROOTHUB pThis = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 1151 PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pThis, uPort); 1152 AssertPtr(pDev); 1153 1154 VUSBSPEED enmSpeed = pDev->IDevice.pfnGetSpeed(&pDev->IDevice); 1155 vusbDevRelease(pDev); 1156 return enmSpeed; 1072 1157 } 1073 1158 … … 1104 1189 } 1105 1190 1191 1192 /** 1193 * @callback_method_impl{FNSSMDEVSAVEPREP, All URBs needs to be canceled.} 1194 */ 1195 static DECLCALLBACK(int) vusbR3RhSavePrep(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM) 1196 { 1197 PVUSBROOTHUB pThis = PDMINS_2_DATA(pDrvIns, PVUSBROOTHUB); 1198 LogFlow(("vusbR3RhSavePrep:\n")); 1199 RT_NOREF(pSSM); 1200 1201 /* 1202 * Detach all proxied devices. 1203 */ 1204 RTCritSectEnter(&pThis->CritSectDevices); 1205 1206 /** @todo we a) can't tell which are proxied, and b) this won't work well when continuing after saving! */ 1207 for (unsigned i = 0; i < RT_ELEMENTS(pThis->apDevByPort); i++) 1208 { 1209 PVUSBDEV pDev = pThis->apDevByPort[i]; 1210 if (pDev) 1211 { 1212 if (!VUSBIDevIsSavedStateSupported(&pDev->IDevice)) 1213 { 1214 int rc = vusbDevDetach(pDev); 1215 AssertRC(rc); 1216 1217 /* 1218 * Save the device pointers here so we can reattach them afterwards. 1219 * This will work fine even if the save fails since the Done handler is 1220 * called unconditionally if the Prep handler was called. 1221 */ 1222 pThis->apDevByPort[i] = pDev; 1223 } 1224 } 1225 } 1226 1227 RTCritSectLeave(&pThis->CritSectDevices); 1228 1229 /* 1230 * Kill old load data which might be hanging around. 1231 */ 1232 if (pThis->pLoad) 1233 { 1234 PDMDrvHlpTimerDestroy(pDrvIns, pThis->pLoad->hTimer); 1235 pThis->pLoad->hTimer = NIL_TMTIMERHANDLE; 1236 PDMDrvHlpMMHeapFree(pDrvIns, pThis->pLoad); 1237 pThis->pLoad = NULL; 1238 } 1239 1240 return VINF_SUCCESS; 1241 } 1242 1243 1244 /** 1245 * @callback_method_impl{FNSSMDEVSAVEDONE} 1246 */ 1247 static DECLCALLBACK(int) vusbR3RhSaveDone(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM) 1248 { 1249 PVUSBROOTHUB pThis = PDMINS_2_DATA(pDrvIns, PVUSBROOTHUB); 1250 PVUSBDEV aPortsOld[VUSB_DEVICES_MAX]; 1251 unsigned i; 1252 LogFlow(("vusbR3RhSaveDone:\n")); 1253 RT_NOREF(pSSM); 1254 1255 /* Save the current data. */ 1256 memcpy(aPortsOld, pThis->apDevByPort, sizeof(aPortsOld)); 1257 AssertCompile(sizeof(aPortsOld) == sizeof(pThis->apDevByPort)); 1258 1259 /* 1260 * NULL the dev pointers. 1261 */ 1262 for (i = 0; i < RT_ELEMENTS(pThis->apDevByPort); i++) 1263 if (pThis->apDevByPort[i] && !VUSBIDevIsSavedStateSupported(&pThis->apDevByPort[i]->IDevice)) 1264 pThis->apDevByPort[i] = NULL; 1265 1266 /* 1267 * Attach the devices. 1268 */ 1269 for (i = 0; i < RT_ELEMENTS(pThis->apDevByPort); i++) 1270 { 1271 PVUSBDEV pDev = aPortsOld[i]; 1272 if (pDev && !VUSBIDevIsSavedStateSupported(&pDev->IDevice)) 1273 vusbHubAttach(&pThis->Hub, pDev); 1274 } 1275 1276 return VINF_SUCCESS; 1277 } 1278 1279 1280 /** 1281 * @callback_method_impl{FNSSMDEVLOADPREP, This must detach the devices 1282 * currently attached and save them for reconnect after the state load has been 1283 * completed.} 1284 */ 1285 static DECLCALLBACK(int) vusbR3RhLoadPrep(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM) 1286 { 1287 PVUSBROOTHUB pThis = PDMINS_2_DATA(pDrvIns, PVUSBROOTHUB); 1288 int rc = VINF_SUCCESS; 1289 LogFlow(("vusbR3RhLoadPrep:\n")); 1290 RT_NOREF(pSSM); 1291 1292 if (!pThis->pLoad) 1293 { 1294 VUSBROOTHUBLOAD Load; 1295 unsigned i; 1296 1297 /// @todo This is all bogus. 1298 /* 1299 * Detach all devices which are present in this session. Save them in the load 1300 * structure so we can reattach them after restoring the guest. 1301 */ 1302 Load.hTimer = NIL_TMTIMERHANDLE; 1303 Load.cDevs = 0; 1304 for (i = 0; i < RT_ELEMENTS(pThis->apDevByPort); i++) 1305 { 1306 PVUSBDEV pDev = pThis->apDevByPort[i]; 1307 if (pDev && !VUSBIDevIsSavedStateSupported(&pDev->IDevice)) 1308 { 1309 Load.apDevs[Load.cDevs++] = pDev; 1310 vusbDevDetach(pDev); 1311 Assert(!pThis->apDevByPort[i]); 1312 } 1313 } 1314 1315 /* 1316 * Any devices to reattach? If so, duplicate the Load struct. 1317 */ 1318 if (Load.cDevs) 1319 { 1320 pThis->pLoad = (PVUSBROOTHUBLOAD)RTMemAllocZ(sizeof(Load)); 1321 if (!pThis->pLoad) 1322 return VERR_NO_MEMORY; 1323 *pThis->pLoad = Load; 1324 } 1325 } 1326 /* else: we ASSUME no device can be attached or detached in the time 1327 * between a state load and the pLoad stuff processing. */ 1328 return rc; 1329 } 1330 1331 1332 /** 1333 * Reattaches devices after a saved state load. 1334 */ 1335 static DECLCALLBACK(void) vusbR3RhLoadReattachDevices(PPDMDRVINS pDrvIns, TMTIMERHANDLE hTimer, void *pvUser) 1336 { 1337 PVUSBROOTHUB pThis = PDMINS_2_DATA(pDrvIns, PVUSBROOTHUB); 1338 PVUSBROOTHUBLOAD pLoad = pThis->pLoad; 1339 LogFlow(("vusbR3RhLoadReattachDevices:\n")); 1340 Assert(hTimer == pLoad->hTimer); RT_NOREF(pvUser); 1341 1342 /* 1343 * Reattach devices. 1344 */ 1345 for (unsigned i = 0; i < pLoad->cDevs; i++) 1346 vusbHubAttach(&pThis->Hub, pLoad->apDevs[i]); 1347 1348 /* 1349 * Cleanup. 1350 */ 1351 PDMDrvHlpTimerDestroy(pDrvIns, hTimer); 1352 pLoad->hTimer = NIL_TMTIMERHANDLE; 1353 RTMemFree(pLoad); 1354 pThis->pLoad = NULL; 1355 } 1356 1357 1358 /** 1359 * @callback_method_impl{FNSSMDEVLOADDONE} 1360 */ 1361 static DECLCALLBACK(int) vusbR3RhLoadDone(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM) 1362 { 1363 PVUSBROOTHUB pThis = PDMINS_2_DATA(pDrvIns, PVUSBROOTHUB); 1364 LogFlow(("vusbR3RhLoadDone:\n")); 1365 RT_NOREF(pSSM); 1366 1367 /* 1368 * Start a timer if we've got devices to reattach 1369 */ 1370 if (pThis->pLoad) 1371 { 1372 int rc = PDMDrvHlpTMTimerCreate(pDrvIns, TMCLOCK_VIRTUAL, vusbR3RhLoadReattachDevices, NULL, 1373 TMTIMER_FLAGS_NO_CRIT_SECT | TMTIMER_FLAGS_NO_RING0, 1374 "VUSB reattach on load", &pThis->pLoad->hTimer); 1375 if (RT_SUCCESS(rc)) 1376 rc = PDMDrvHlpTimerSetMillies(pDrvIns, pThis->pLoad->hTimer, 250); 1377 return rc; 1378 } 1379 1380 return VINF_SUCCESS; 1381 } 1382 1383 1106 1384 /* -=-=-=-=-=- VUSB Hub methods -=-=-=-=-=- */ 1107 1385 … … 1136 1414 * linked into the device list of this hub. 1137 1415 */ 1138 int rc = pRh->pIRhPort->pfnAttach(pRh->pIRhPort, &pDev->IDevice, iPort); 1416 VUSBSPEED enmSpeed = pDev->IDevice.pfnGetSpeed(&pDev->IDevice); 1417 int rc = pRh->pIRhPort->pfnAttach(pRh->pIRhPort, iPort, enmSpeed); 1139 1418 if (RT_SUCCESS(rc)) 1140 1419 { … … 1142 1421 pDev->pNext = pRh->pDevices; 1143 1422 pRh->pDevices = pDev; 1423 1424 Assert(!pRh->apDevByPort[iPort]); 1425 pRh->apDevByPort[iPort] = pDev; 1426 1144 1427 RTCritSectLeave(&pRh->CritSectDevices); 1145 1428 LogRel(("VUSB: Attached '%s' to port %d on %s (%sSpeed)\n", pDev->pUsbIns->pszName, … … 1184 1467 pRh->pDevices = pDev->pNext; 1185 1468 pDev->pNext = NULL; 1469 1470 pRh->apDevByPort[pDev->i16Port] = NULL; 1186 1471 RTCritSectLeave(&pRh->CritSectDevices); 1187 1472 … … 1190 1475 */ 1191 1476 unsigned uPort = pDev->i16Port; 1192 pRh->pIRhPort->pfnDetach(pRh->pIRhPort, &pDev->IDevice,uPort);1477 pRh->pIRhPort->pfnDetach(pRh->pIRhPort, uPort); 1193 1478 LogRel(("VUSB: Detached '%s' from port %u on %s\n", pDev->pUsbIns->pszName, uPort, pHub->pszName)); 1194 1479 ASMBitSet(&pRh->Bitmap, uPort); … … 1307 1592 /* the usb device */ 1308 1593 pThis->Hub.Dev.enmState = VUSB_DEVICE_STATE_ATTACHED; 1309 pThis->Hub.Dev.u8Address = VUSB_INVALID_ADDRESS;1310 pThis->Hub.Dev.u8NewAddress = VUSB_INVALID_ADDRESS;1311 pThis->Hub.Dev.i16Port = -1;1312 1594 pThis->Hub.Dev.cRefs = 1; 1313 pThis->Hub.Dev.IDevice.pfnReset = vusbRhDevReset;1314 pThis->Hub.Dev.IDevice.pfnPowerOn = vusbRhDevPowerOn;1315 pThis->Hub.Dev.IDevice.pfnPowerOff = vusbRhDevPowerOff;1316 pThis->Hub.Dev.IDevice.pfnGetState = vusbRhDevGetState;1317 1595 /* the hub */ 1318 1596 pThis->Hub.pOps = &s_VUsbRhHubOps; … … 1326 1604 /* the connector */ 1327 1605 pThis->IRhConnector.pfnSetUrbParams = vusbRhSetUrbParams; 1606 pThis->IRhConnector.pfnReset = vusbR3RhReset; 1607 pThis->IRhConnector.pfnPowerOn = vusbR3RhPowerOn; 1608 pThis->IRhConnector.pfnPowerOff = vusbR3RhPowerOff; 1328 1609 pThis->IRhConnector.pfnNewUrb = vusbRhConnNewUrb; 1329 1610 pThis->IRhConnector.pfnFreeUrb = vusbRhConnFreeUrb; … … 1333 1614 pThis->IRhConnector.pfnCancelAllUrbs = vusbRhCancelAllUrbs; 1334 1615 pThis->IRhConnector.pfnAbortEp = vusbRhAbortEp; 1335 pThis->IRhConnector.pfnAttachDevice = vusbRhAttachDevice;1336 pThis->IRhConnector.pfnDetachDevice = vusbRhDetachDevice;1337 1616 pThis->IRhConnector.pfnSetPeriodicFrameProcessing = vusbRhSetFrameProcessing; 1338 1617 pThis->IRhConnector.pfnGetPeriodicFrameRate = vusbRhGetPeriodicFrameRate; 1339 1618 pThis->IRhConnector.pfnUpdateIsocFrameDelta = vusbRhUpdateIsocFrameDelta; 1619 pThis->IRhConnector.pfnDevReset = vusbR3RhDevReset; 1620 pThis->IRhConnector.pfnDevPowerOn = vusbR3RhDevPowerOn; 1621 pThis->IRhConnector.pfnDevPowerOff = vusbR3RhDevPowerOff; 1622 pThis->IRhConnector.pfnDevGetState = vusbR3RhDevGetState; 1623 pThis->IRhConnector.pfnDevIsSavedStateSupported = vusbR3RhDevIsSavedStateSupported; 1624 pThis->IRhConnector.pfnDevGetSpeed = vusbR3RhDevGetSpeed; 1340 1625 pThis->hSniffer = VUSBSNIFFER_NIL; 1341 1626 pThis->cbHci = 0; … … 1388 1673 if (RT_FAILURE(rc)) 1389 1674 return rc; 1675 1676 /* 1677 * Register the saved state data unit for attaching devices. 1678 */ 1679 rc = PDMDrvHlpSSMRegisterEx(pDrvIns, VUSB_ROOTHUB_SAVED_STATE_VERSION, 0, 1680 NULL, NULL, NULL, 1681 vusbR3RhSavePrep, NULL, vusbR3RhSaveDone, 1682 vusbR3RhLoadPrep, NULL, vusbR3RhLoadDone); 1683 AssertRCReturn(rc, rc); 1390 1684 1391 1685 /*
Note:
See TracChangeset
for help on using the changeset viewer.