Changeset 80685 in vbox for trunk/src/VBox/HostDrivers/VBoxUSB
- Timestamp:
- Sep 10, 2019 6:56:06 AM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 133222
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/VBoxUSB/win/lib/VBoxUsbLib-win.cpp
r80631 r80685 386 386 } 387 387 388 #ifndef VBOX_WITH_NEW_USB_ENUM 388 389 static int usbLibDevStrDriverKeyGet(HANDLE hHub, ULONG iPort, LPSTR* plpszName) 389 390 { … … 431 432 return rc; 432 433 } 434 #endif 433 435 434 436 static int usbLibDevStrHubNameGet(HANDLE hHub, ULONG iPort, LPSTR* plpszName) … … 756 758 } 757 759 760 #ifndef VBOX_WITH_NEW_USB_ENUM 758 761 static int usbLibDevGetHubDevices(LPCSTR lpszName, PUSBDEVICE *ppDevs, uint32_t *pcDevs); 759 762 … … 902 905 return rc; 903 906 } 907 #endif 904 908 905 909 #ifdef VBOX_WITH_NEW_USB_ENUM … … 918 922 { 919 923 LogRelFunc(("Failed to query buffer size, error %ld\n", GetLastError())); 920 AssertFailed();921 924 return NULL; 922 925 } … … 970 973 971 974 /* Given a hub's PnP device instance, find its device path (file name). */ 972 static LPCSTR usbLibGetHubPathFrom DevInst(LPCSTR DevInst)975 static LPCSTR usbLibGetHubPathFromInstanceID(LPCSTR InstanceID) 973 976 { 974 977 HDEVINFO InfoSet; 975 SP_DEVINFO_DATA DeviceData;976 978 SP_DEVICE_INTERFACE_DATA InterfaceData; 977 979 PSP_DEVICE_INTERFACE_DETAIL_DATA DetailData; … … 980 982 981 983 /* Enumerate the DevInst's USB hub interface. */ 982 InfoSet = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_HUB, DevInst, NULL,984 InfoSet = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_HUB, InstanceID, NULL, 983 985 DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); 984 986 if (InfoSet == INVALID_HANDLE_VALUE) 985 987 { 986 LogRelFunc(("Failed to get interface , error %ld\n", GetLastError()));988 LogRelFunc(("Failed to get interface for InstID %se, error %ld\n", InstanceID, GetLastError())); 987 989 return NULL; 988 990 } 989 991 990 memset(& DeviceData, 0, sizeof(DeviceData));991 DeviceData.cbSize = sizeof(DeviceData);992 memset(&InterfaceData, 0, sizeof(InterfaceData)); 993 InterfaceData.cbSize = sizeof(InterfaceData); 992 994 rc = SetupDiEnumDeviceInterfaces(InfoSet, 0, &GUID_DEVINTERFACE_USB_HUB, 0, &InterfaceData); 993 995 if (!rc) 994 996 { 995 LogRelFunc(("Failed to get interface data, error %ld\n", GetLastError())); 997 DWORD dwErr = GetLastError(); 998 999 /* The parent device might not be a hub; that is valid, ignore such errors. */ 1000 if (dwErr != ERROR_NO_MORE_ITEMS) 1001 LogRelFunc(("Failed to get interface data for InstID %s, error %ld\n", InstanceID, dwErr)); 996 1002 SetupDiDestroyDeviceInfoList(InfoSet); 997 1003 return NULL; … … 1026 1032 1027 1033 /* First get the parent DEVINST. */ 1028 cr = CM_Get_Parent( 1034 cr = CM_Get_Parent(&ParentInst, DevInst, 0); 1029 1035 if (cr != CR_SUCCESS) 1030 1036 { … … 1058 1064 } 1059 1065 1066 /* Process a single USB device that's being enumerated and grab its hub-specific data. */ 1067 static int usbLibDevGetDevice(LPCSTR lpcszHubFile, ULONG iPort, LPCSTR Location, PUSBDEVICE *ppDevs, uint32_t *pcDevs) 1068 { 1069 HANDLE HubDevice; 1070 BYTE abConBuf[sizeof(USB_NODE_CONNECTION_INFORMATION_EX)]; 1071 PUSB_NODE_CONNECTION_INFORMATION_EX pConInfo = PUSB_NODE_CONNECTION_INFORMATION_EX(abConBuf); 1072 int rc = VINF_SUCCESS; 1073 DWORD cbReturned = 0; 1074 1075 /* Validate inputs. */ 1076 if ((iPort < 1) || (iPort > 255)) 1077 { 1078 LogRelFunc(("Port index out of range (%u)\n", iPort)); 1079 return VERR_INVALID_PARAMETER; 1080 } 1081 if (!lpcszHubFile) 1082 { 1083 LogRelFunc(("Hub path is NULL!\n")); 1084 return VERR_INVALID_PARAMETER; 1085 } 1086 1087 /* Try opening the hub file so we can send IOCTLs to it. */ 1088 HubDevice = CreateFile(lpcszHubFile, GENERIC_WRITE, FILE_SHARE_WRITE, 1089 NULL, OPEN_EXISTING, 0, NULL); 1090 if (HubDevice == INVALID_HANDLE_VALUE) 1091 { 1092 LogRelFunc(("Failed to open hub `%s', dwErr(%d)\n", lpcszHubFile, GetLastError())); 1093 return VERR_FILE_NOT_FOUND; 1094 } 1095 1096 /* The shenanigans with abConBuf are due to USB_NODE_CONNECTION_INFORMATION_EX 1097 * containing a zero-sized array, triggering compiler warnings. 1098 */ 1099 memset(pConInfo, 0, sizeof(abConBuf)); 1100 pConInfo->ConnectionIndex = iPort; 1101 1102 /* We expect that IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX is always available 1103 * on any supported Windows version and hardware. 1104 * NB: IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 is Win8 and later only. 1105 */ 1106 if (!DeviceIoControl(HubDevice, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, 1107 pConInfo, sizeof(abConBuf), pConInfo, sizeof(abConBuf), 1108 &cbReturned, NULL)) 1109 { 1110 DWORD dwErr = GetLastError(); NOREF(dwErr); 1111 LogRel(("IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX failed with error %ld on hub %s, port %d\n", dwErr, lpcszHubFile, iPort)); 1112 AssertMsg(dwErr == ERROR_DEVICE_NOT_CONNECTED, (__FUNCTION__": DeviceIoControl failed dwErr (%d)\n", dwErr)); 1113 CloseHandle(HubDevice); 1114 return VERR_GENERAL_FAILURE; 1115 } 1116 1117 if (pConInfo->ConnectionStatus != DeviceConnected) 1118 { 1119 /* Ignore this, can't do anything with it. */ 1120 LogFunc(("Device is not connected, skipping.\n")); 1121 CloseHandle(HubDevice); 1122 return VINF_SUCCESS; 1123 } 1124 1125 if (pConInfo->DeviceIsHub) 1126 { 1127 /* We're ignoring hubs, just skip this. */ 1128 LogFunc(("Device is a hub, skipping.\n")); 1129 CloseHandle(HubDevice); 1130 return VINF_SUCCESS; 1131 } 1132 1133 PUSB_CONFIGURATION_DESCRIPTOR pCfgDr = NULL; 1134 PVBOXUSB_STRING_DR_ENTRY pList = NULL; 1135 rc = usbLibDevCfgDrGet(HubDevice, lpcszHubFile, iPort, 0, &pCfgDr); 1136 if (pCfgDr) 1137 { 1138 rc = usbLibDevStrDrEntryGetAll(HubDevice, lpcszHubFile, iPort, &pConInfo->DeviceDescriptor, pCfgDr, &pList); 1139 #ifdef VBOX_WITH_ANNOYING_USB_ASSERTIONS 1140 AssertRC(rc); // this can fail if device suspended 1141 #endif 1142 } 1143 1144 /* At this point we're done with the hub device. */ 1145 CloseHandle(HubDevice); 1146 1147 PUSBDEVICE pDev = (PUSBDEVICE)RTMemAllocZ(sizeof (*pDev)); 1148 if (RT_LIKELY(pDev)) 1149 { 1150 rc = usbLibDevPopulate(pDev, pConInfo, iPort, Location, lpcszHubFile, pList); 1151 if (RT_SUCCESS(rc)) 1152 { 1153 pDev->pNext = *ppDevs; 1154 *ppDevs = pDev; 1155 ++*pcDevs; 1156 } 1157 else 1158 RTMemFree(pDev); 1159 } 1160 else 1161 rc = VERR_NO_MEMORY; 1162 1163 if (pCfgDr) 1164 usbLibDevCfgDrFree(pCfgDr); 1165 if (pList) 1166 usbLibDevStrDrEntryFreeList(pList); 1167 1168 return rc; 1169 } 1170 1171 1060 1172 /* 1061 1173 * Enumerate the USB devices in the host system. Since we do not care about the hierarchical 1062 * structure of root hubs, other hubs, and devices, we just use ask the USB PnP enumerator to 1063 * give us all it has. This includes hubs (though not root hubs) which we filter out. It also 1064 * includes USB devices with no driver, which is notably something we cannot get by enumerating 1065 * via GUID_DEVINTERFACE_USB_DEVICE. 1174 * structure of root hubs, other hubs, and devices, we just ask the USB PnP enumerator to 1175 * give us all it has. This includes hubs (though not root hubs), as well as multiple child 1176 * interfaces of multi-interface USB devices, which we filter out. It also includes USB 1177 * devices with no driver, which is notably something we cannot get by enumerating via 1178 * GUID_DEVINTERFACE_USB_DEVICE. 1066 1179 * 1067 * This approach also saves us some trouble relative to enumerating via hub IOCTLs and then 1068 * hunting through the PnP manager to find them. Instead, we look up the device's parent which 1069 * is inevitably a hub, and that allows us to obtain USB-specific data (descriptors, speeds, 1070 * etc.) when combined with the devices PnP "address" (USB port on parent hub). 1180 * This approach also saves us some trouble relative to enumerating devices via hub IOCTLs and 1181 * then hunting through the PnP manager to find them. Instead, we look up the device's parent 1182 * which (for devices we're interested in) is always a hub, and that allows us to obtain 1183 * USB-specific data (descriptors, speeds, etc.) when combined with the devices PnP "address" 1184 * (USB port on parent hub). 1071 1185 * 1072 1186 * NB: Every USB device known to the Windows PnP Manager will have a device instance ID. Typically … … 1077 1191 * 1078 1192 * The location information should be a reliable way of identifying a device and does not change 1079 * with driver installs, capturing, etc. It is only available on Windows Vista and later; earlier 1080 * Windows version had no reliable way of cross-referencing the USB IOCTL and PnP Manager data. 1193 * with driver installs, capturing, etc. USB device location information is only available on 1194 * Windows Vista and later; earlier Windows version had no reliable way of cross-referencing the 1195 * USB IOCTL and PnP Manager data. 1081 1196 */ 1082 1197 static int usbLibDevGetDevices(PUSBDEVICE *ppDevs, uint32_t *pcDevs) … … 1084 1199 HDEVINFO InfoSet; 1085 1200 DWORD DeviceIndex; 1201 LPDWORD Address; 1086 1202 SP_DEVINFO_DATA DeviceData; 1087 LPSTR ClassGUID; 1203 LPCSTR ParentInstID; 1204 LPCSTR HubPath = NULL; 1205 LPCSTR Location; 1088 1206 1089 1207 /* Ask for the USB PnP enumerator for all it has. */ … … 1097 1215 while (SetupDiEnumDeviceInfo(InfoSet, DeviceIndex, &DeviceData)) 1098 1216 { 1099 /* Grab the class GUID. If it's a USB hub, we aren't interested. */ 1100 ClassGUID = (LPSTR)usbLibGetRegistryProperty(InfoSet, &DeviceData, SPDRP_CLASSGUID); 1101 if (ClassGUID && strcmp(ClassGUID, "{36fc9e60-c465-11cf-8056-444553540000}")) 1102 { 1103 /* There is a class GUID and it's not a hub. Should be a USB device then. */ 1104 RTMemFree(ClassGUID); 1105 } 1217 /* Use the CM API to get the parent instance ID. */ 1218 ParentInstID = usbLibGetParentInstanceID(DeviceData.DevInst); 1219 1220 /* Now figure out the hub's file path fron the instance ID, if there is one. */ 1221 if (ParentInstID) 1222 HubPath = usbLibGetHubPathFromInstanceID(ParentInstID); 1223 1224 /* If there's no hub interface on the parent, then this might be a child 1225 * device of a multi-interface device. Either way, we're not interested. 1226 */ 1227 if (HubPath) 1228 { 1229 /* The location information uniquely identifies the USB device, (hub/port). */ 1230 Location = (LPCSTR)usbLibGetRegistryProperty(InfoSet, &DeviceData, SPDRP_LOCATION_INFORMATION); 1231 1232 /* The device's PnP Manager "address" is the port number on the parent hub. */ 1233 Address = (LPDWORD)usbLibGetRegistryProperty(InfoSet, &DeviceData, SPDRP_ADDRESS); 1234 if (Address && Location) 1235 { 1236 usbLibDevGetDevice(HubPath, *Address, Location, ppDevs, pcDevs); 1237 } 1238 RTMemFree((void *)HubPath); 1239 1240 if (Location) 1241 RTMemFree((void *)Location); 1242 if (Address) 1243 RTMemFree((void *)Address); 1244 } 1245 1246 /* Clean up after this device. */ 1247 if (ParentInstID) 1248 RTMemFree((void *)ParentInstID); 1106 1249 1107 1250 ++DeviceIndex;
Note:
See TracChangeset
for help on using the changeset viewer.