Mercurial > hg > ucis.core
diff USBLib/Windows/USB/UsbHub.cs @ 63:309c705d7460
Updates and cleanup in Windows USB enumeration code
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Sun, 13 Oct 2013 18:43:45 +0200 |
parents | edc41c861d96 |
children | e811297f5aa4 |
line wrap: on
line diff
--- a/USBLib/Windows/USB/UsbHub.cs Sun Oct 13 02:47:08 2013 +0200 +++ b/USBLib/Windows/USB/UsbHub.cs Sun Oct 13 18:43:45 2013 +0200 @@ -3,69 +3,108 @@ using System.ComponentModel; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; +using UCIS.HWLib.Windows.Devices; using UCIS.USBLib.Internal.Windows; namespace UCIS.HWLib.Windows.USB { public class UsbHub : UsbDevice { - public bool IsRootHub { get; private set; } - internal USB_NODE_INFORMATION NodeInformation { get; private set; } - - public int PortCount { get { return NodeInformation.HubInformation.HubDescriptor.bNumberOfPorts; } } - public bool IsBusPowered { get { return NodeInformation.HubInformation.HubIsBusPowered; } } - public override string DeviceDescription { get { return IsRootHub ? "RootHub" : "Standard-USB-Hub"; } } + internal static SafeFileHandle OpenHandle(String path) { + SafeFileHandle handle = Kernel32.CreateFile(path, Kernel32.GENERIC_WRITE, Kernel32.FILE_SHARE_WRITE, IntPtr.Zero, Kernel32.OPEN_EXISTING, 0, IntPtr.Zero); + if (handle.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error()); + return handle; + } - public override string DriverKey { - get { - if (Parent == null) return null; - using (SafeFileHandle handle = OpenHandle(Parent.DevicePath)) return GetNodeConnectionDriverKey(handle, AdapterNumber); - } - } - - internal UsbHub(UsbDevice parent, USB_NODE_CONNECTION_INFORMATION_EX nci, string devicePath, uint port, Boolean roothub) - : base(parent, nci, port, devicePath) { - this.IsRootHub = roothub; - using (SafeFileHandle handle = OpenHandle(DevicePath)) { - USB_NODE_INFORMATION NodeInfo; - GetNodeInformation(handle, out NodeInfo); - this.NodeInformation = NodeInfo; - } + private Boolean HasNodeInformation = false; + private USB_NODE_INFORMATION NodeInformation; + + private void GetNodeInformation() { + if (HasNodeInformation) return; + NodeInformation = new USB_NODE_INFORMATION(); + int nBytes = Marshal.SizeOf(typeof(USB_NODE_INFORMATION)); + using (SafeFileHandle handle = OpenHandle()) + if (!Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_NODE_INFORMATION, ref NodeInformation, nBytes, out NodeInformation, nBytes, out nBytes, IntPtr.Zero)) + throw new Win32Exception(Marshal.GetLastWin32Error()); } - public override int GetDescriptor(byte descriptorType, byte index, short langId, byte[] buffer, int offset, int length) { - if (Parent == null) return 0; - using (SafeFileHandle handle = UsbHub.OpenHandle(Parent.DevicePath)) return GetDescriptor(handle, AdapterNumber, descriptorType, index, langId, buffer, offset, length); + public bool IsRootHub { get; private set; } + public int PortCount { get { GetNodeInformation(); return NodeInformation.HubInformation.HubDescriptor.bNumberOfPorts; } } + public bool IsBusPowered { get { GetNodeInformation(); return NodeInformation.HubInformation.HubIsBusPowered; } } + public override string DeviceDescription { get { return IsRootHub ? "Root hub" : base.DeviceDescription; } } + + public String DevicePath { get; private set; } + + internal UsbHub(UsbHub parent, string devicePath, uint port) + : base(null, parent, port) { + this.DevicePath = devicePath; + this.IsRootHub = (parent == null); + if (IsRootHub) SetNodeConnectionInfo(new USB_NODE_CONNECTION_INFORMATION_EX()); } + private UsbHub(DeviceNode devnode, string devicePath) + : base(devnode, null, 0) { + this.DevicePath = devicePath; + this.IsRootHub = false; + } + + internal SafeFileHandle OpenHandle() { + return OpenHandle(DevicePath); + } public IList<UsbDevice> Devices { get { - List<UsbDevice> devices = new List<UsbDevice>(); - using (SafeFileHandle handle = OpenHandle(DevicePath)) { + UsbDevice[] devices = new UsbDevice[PortCount]; + using (SafeFileHandle handle = OpenHandle()) { for (uint index = 1; index <= PortCount; index++) { - devices.Add(BuildDevice(this, index, this.DevicePath, handle)); + USB_NODE_CONNECTION_INFORMATION_EX nodeConnection = GetNodeConnectionInformation(handle, index); + UsbDevice device; + if (nodeConnection.ConnectionStatus != USB_CONNECTION_STATUS.DeviceConnected) { + device = new UsbDevice(null, this, index); + } else if (nodeConnection.DeviceDescriptor.DeviceClass == (Byte)UsbDeviceClass.HubDevice) { + int nBytes = Marshal.SizeOf(typeof(USB_NODE_CONNECTION_NAME)); + USB_NODE_CONNECTION_NAME nameConnection = new USB_NODE_CONNECTION_NAME(); + nameConnection.ConnectionIndex = index; + if (!Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_NODE_CONNECTION_NAME, ref nameConnection, nBytes, out nameConnection, nBytes, out nBytes, IntPtr.Zero)) + throw new Win32Exception(Marshal.GetLastWin32Error()); + device = new UsbHub(this, @"\\?\" + nameConnection.NodeName, index); + } else { + device = new UsbDevice(null, this, index); + } + device.SetNodeConnectionInfo(nodeConnection); + devices[index - 1] = device; } } return devices; } } - internal static UsbDevice BuildDevice(UsbDevice parent, uint portCount, string devicePath) { - using (SafeFileHandle handle = OpenHandle(devicePath)) return BuildDevice(parent, portCount, devicePath, handle); + static readonly Guid IID_DEVINTERFACE_USB_HUB = new Guid(UsbApi.GUID_DEVINTERFACE_USB_HUB); + public static UsbHub GetHubForDeviceNode(DeviceNode node) { + if (node == null) return null; + String[] interfaces = node.GetInterfaces(IID_DEVINTERFACE_USB_HUB); + if (interfaces == null || interfaces.Length == 0) return null; + return new UsbHub(node, interfaces[0]); } - internal static UsbDevice BuildDevice(UsbDevice parent, uint portCount, string devicePath, SafeFileHandle handle) { - USB_NODE_CONNECTION_INFORMATION_EX nodeConnection; - if (!GetNodeConnectionInformation(handle, portCount, out nodeConnection)) throw new Win32Exception(Marshal.GetLastWin32Error()); - UsbDevice device = null; - if (nodeConnection.ConnectionStatus != USB_CONNECTION_STATUS.DeviceConnected) { - device = new UsbDevice(parent, nodeConnection, portCount, devicePath); - } else if (nodeConnection.DeviceDescriptor.DeviceClass == (Byte)UsbDeviceClass.HubDevice) { - String nodeName = GetNodeConnectionName(handle, portCount); - device = new UsbHub(parent, nodeConnection, @"\\?\" + nodeName, portCount, false); + + public static IList<UsbHub> GetHubs() { + IList<UsbHub> devices = new List<UsbHub>(); + foreach (DeviceNode dev in DeviceNode.GetDevices(IID_DEVINTERFACE_USB_HUB)) { + UsbHub hub = GetHubForDeviceNode(dev); + if (hub != null) devices.Add(hub); + } + return devices; + } + + public UsbDevice FindChildForDeviceNode(DeviceNode node) { + String driverkey = node.DriverKey; + if (driverkey != null) { + foreach (UsbDevice child in Devices) if (driverkey.Equals(child.DriverKey, StringComparison.InvariantCultureIgnoreCase)) return child; } else { - device = new UsbDevice(parent, nodeConnection, portCount, devicePath); + int? address = node.Address; + if (address == null || address.Value == 0) return null; + int port = address.Value; + foreach (UsbDevice child in Devices) if (port == child.AdapterNumber) return child; } - device.NodeConnectionInfo = nodeConnection; - return device; + return null; } } }