/// <summary>return a list of the down stream ports</summary> /// <returns>List of downstream ports</returns> internal IEnumerable <UsbPort> GetPorts() { List <UsbPort> portList = new List <UsbPort>(); // Open a handle to the Hub device IntPtr h = CreateFile(HubDevicePath, GENERIC_WRITE, FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); if (h == INVALID_HANDLE_VALUE) { return(new ReadOnlyCollection <UsbPort>(portList)); } int nBytes = Marshal.SizeOf(typeof(UsbNodeConnectionInformationEx)); IntPtr ptrNodeConnection = Marshal.AllocHGlobal(nBytes); // loop thru all of the ports on the hub // BTW: Ports are numbered starting at 1 for (int i = 1; i <= HubPortCount; i++) { var nodeConnection = new UsbNodeConnectionInformationEx { ConnectionIndex = i }; Marshal.StructureToPtr(nodeConnection, ptrNodeConnection, true); if (!DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, ptrNodeConnection, nBytes, ptrNodeConnection, nBytes, out _, IntPtr.Zero)) { continue; } nodeConnection = (UsbNodeConnectionInformationEx)Marshal.PtrToStructure(ptrNodeConnection, typeof(UsbNodeConnectionInformationEx)); // load up the USBPort class var port = new UsbPort { PortPortNumber = i, PortHubDevicePath = HubDevicePath, PortStatus = ((UsbConnectionStatus)nodeConnection.ConnectionStatus).ToString(), PortSpeed = ((UsbDeviceSpeed)nodeConnection.Speed).ToString(), PortIsDeviceConnected = nodeConnection.ConnectionStatus == (int)UsbConnectionStatus.DeviceConnected, PortIsHub = Convert.ToBoolean(nodeConnection.DeviceIsHub), PortDeviceDescriptor = nodeConnection.DeviceDescriptor }; // add it to the list portList.Add(port); } Marshal.FreeHGlobal(ptrNodeConnection); CloseHandle(h); // convert it into a Collection return(new ReadOnlyCollection <UsbPort>(portList)); }
public IEnumerable <UsbPort> GetPorts() { var h = Kernel32.CreateFile(this.HubDevicePath, UsbConstants.GENERIC_WRITE, UsbConstants.FILE_SHARE_WRITE, IntPtr.Zero, UsbConstants.OPEN_EXISTING, default(int), IntPtr.Zero); if (h.ToInt32() != UsbConstants.INVALID_HANDLE_VALUE) { var nBytes = Marshal.SizeOf(typeof(UsbNodeConnectionInformationEx)); var ptrNodeConnection = Marshal.AllocHGlobal(nBytes); for (var i = 1; i <= this.HubPortCount; i++) { var nodeConnection = new UsbNodeConnectionInformationEx { ConnectionIndex = i, }; Marshal.StructureToPtr(nodeConnection, ptrNodeConnection, true); if (Kernel32.DeviceIoControl(h, UsbConstants.IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, ptrNodeConnection, nBytes, ptrNodeConnection, nBytes, out int nBytesReturned, IntPtr.Zero)) { nodeConnection = (UsbNodeConnectionInformationEx)Marshal.PtrToStructure(ptrNodeConnection, typeof(UsbNodeConnectionInformationEx)); var status = (UsbConnectionStatus)nodeConnection.ConnectionStatus; var speed = (UsbDeviceSpeed)nodeConnection.Speed; var port = new UsbPort(this) { PortNumber = i, Status = status.ToString(), HubDevicePath = this.HubDevicePath, Speed = speed.ToString(), IsHub = Convert.ToBoolean(nodeConnection.DeviceIsHub), IsDeviceConnected = nodeConnection.ConnectionStatus == (int)UsbConnectionStatus.DeviceConnected, DeviceDescriptor = nodeConnection.DeviceDescriptor, }; yield return(port); } } Marshal.FreeHGlobal(ptrNodeConnection); Kernel32.CloseHandle(h); } }
public static async Task <ExportedDevice[]> GetAll(CancellationToken cancellationToken) { var exportedDevices = new SortedDictionary <string, ExportedDevice>(); using var deviceInfoSet = NativeMethods.SetupDiGetClassDevs(IntPtr.Zero, "USB", IntPtr.Zero, DiGetClassFlags.DIGCF_ALLCLASSES | DiGetClassFlags.DIGCF_PRESENT); foreach (var devInfoData in EnumDeviceInfo(deviceInfoSet)) { cancellationToken.ThrowIfCancellationRequested(); var instanceId = GetDevicePropertyString(deviceInfoSet, devInfoData, DEVPKEY_Device_InstanceId); if (IsUsbHub(instanceId)) { // device is itself a USB hub, which is not supported continue; } var parentId = GetDevicePropertyString(deviceInfoSet, devInfoData, DEVPKEY_Device_Parent); if (!IsUsbHub(parentId)) { // parent is not a USB hub (which it must be for this device to be supported) continue; } // OK, so the device is directly connected to a hub, but is not a hub itself ... this looks promising GetBusId(deviceInfoSet, devInfoData, out var hubNum, out var connectionIndex); var address = GetDevicePropertyUInt32(deviceInfoSet, devInfoData, DEVPKEY_Device_Address); if (connectionIndex != address) { throw new NotSupportedException($"DEVPKEY_Device_Address ({address}) does not match DEVPKEY_Device_LocationInfo ({connectionIndex})"); } // now query the parent USB hub for device details { cancellationToken.ThrowIfCancellationRequested(); using var hubs = NativeMethods.SetupDiGetClassDevs(GUID_DEVINTERFACE_USB_HUB, parentId, IntPtr.Zero, DiGetClassFlags.DIGCF_DEVICEINTERFACE | DiGetClassFlags.DIGCF_PRESENT); var(_, interfaceData) = EnumDeviceInterfaces(hubs, GUID_DEVINTERFACE_USB_HUB).Single(); var hubPath = GetDeviceInterfaceDetail(hubs, interfaceData); cancellationToken.ThrowIfCancellationRequested(); using var hubFile = new DeviceFile(hubPath); using var cancellationTokenRegistration = cancellationToken.Register(() => hubFile.Dispose()); var data = new UsbNodeConnectionInformationEx() { ConnectionIndex = connectionIndex }; var buf = StructToBytes(data); await hubFile.IoControlAsync(IoControl.IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, buf, buf); BytesToStruct(buf, 0, out data); var speed = MapWindowsSpeedToLinuxSpeed(data.Speed); var data2 = new UsbNodeConnectionInformationExV2() { ConnectionIndex = connectionIndex, Length = (uint)Marshal.SizeOf <UsbNodeConnectionInformationExV2>(), SupportedUsbProtocols = UsbProtocols.Usb110 | UsbProtocols.Usb200 | UsbProtocols.Usb300, }; var buf2 = StructToBytes(data2); await hubFile.IoControlAsync(IoControl.IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, buf2, buf2); BytesToStruct(buf2, 0, out data2); if ((data2.SupportedUsbProtocols & UsbProtocols.Usb300) != 0) { if ((data2.Flags & UsbNodeConnectionInformationExV2Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher) != 0) { speed = Linux.UsbDeviceSpeed.USB_SPEED_SUPER_PLUS; } else if ((data2.Flags & UsbNodeConnectionInformationExV2Flags.DeviceIsOperatingAtSuperSpeedOrHigher) != 0) { speed = Linux.UsbDeviceSpeed.USB_SPEED_SUPER; } } var exportedDevice = new ExportedDevice() { Path = instanceId, BusNum = hubNum, DevNum = connectionIndex, Speed = speed, VendorId = data.DeviceDescriptor.idVendor, ProductId = data.DeviceDescriptor.idProduct, BcdDevice = data.DeviceDescriptor.bcdDevice, DeviceClass = data.DeviceDescriptor.bDeviceClass, DeviceSubClass = data.DeviceDescriptor.bDeviceSubClass, DeviceProtocol = data.DeviceDescriptor.bDeviceProtocol, ConfigurationValue = data.CurrentConfigurationValue, NumConfigurations = data.DeviceDescriptor.bNumConfigurations, ConfigurationDescriptors = await GetConfigurationDescriptor(hubFile, connectionIndex, data.DeviceDescriptor.bNumConfigurations), }; exportedDevices.Add(exportedDevice.BusId, exportedDevice); } } return(exportedDevices.Values.ToArray()); }