# HG changeset patch # User Ivo Smits # Date 1381682625 -7200 # Node ID 309c705d7460564666ffc9a3ea62db651105036f # Parent edc41c861d96f5fdc49d7de0e6184566558c707f Updates and cleanup in Windows USB enumeration code diff -r edc41c861d96 -r 309c705d7460 USBLib/Internal/Windows/SetupApi.cs --- a/USBLib/Internal/Windows/SetupApi.cs Sun Oct 13 02:47:08 2013 +0200 +++ b/USBLib/Internal/Windows/SetupApi.cs Sun Oct 13 18:43:45 2013 +0200 @@ -412,5 +412,6 @@ LEGACYBUSTYPE = 0x00000015, BUSNUMBER = 0x00000016, ENUMERATOR_NAME = 0x00000017, + ADDRESS = 0x0000001D, } -} \ No newline at end of file +} diff -r edc41c861d96 -r 309c705d7460 USBLib/Internal/Windows/UsbApi.cs --- a/USBLib/Internal/Windows/UsbApi.cs Sun Oct 13 02:47:08 2013 +0200 +++ b/USBLib/Internal/Windows/UsbApi.cs Sun Oct 13 18:43:45 2013 +0200 @@ -27,8 +27,6 @@ public const int DICS_DISABLE = 0x00000002; } - #region enumerations - enum UsbDeviceClass : byte { UnspecifiedDevice = 0x00, AudioInterface = 0x01, @@ -54,12 +52,6 @@ enum HubCharacteristics : byte { GangedPowerSwitching = 0x00, IndividualPotPowerSwitching = 0x01, - // to do - } - - enum USB_HUB_NODE { - UsbHub, - UsbMIParent } enum USB_CONNECTION_STATUS : int { @@ -100,8 +92,6 @@ HighSpeed = 0x0400, TestMode = 0x0800, Indicator = 0x1000, - // these are the bits which cause the hub port state machine to keep moving - //kHubPortStateChangeMask = kHubPortConnection | kHubPortEnabled | kHubPortSuspend | kHubPortOverCurrent | kHubPortBeingReset } enum HubStatus : byte { @@ -125,10 +115,6 @@ SetPowerOn = 1 } - #endregion - - #region structures - [StructLayout(LayoutKind.Sequential)] struct SP_CLASSINSTALL_HEADER { public int cbSize; @@ -143,18 +129,18 @@ public int HwProfile; } - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] struct USB_HCD_DRIVERKEY_NAME { - public uint ActualLength; + public UInt32 ActualLength; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = UsbApi.MAX_BUFFER_SIZE)] - public string DriverKeyName; //WCHAR DriverKeyName[1]; + public String DriverKeyName; } - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] struct USB_ROOT_HUB_NAME { - public uint ActualLength; + public UInt32 ActualLength; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = UsbApi.MAX_BUFFER_SIZE)] - public string RootHubName; //WCHAR RootHubName[1]; + public String RootHubName; } [StructLayout(LayoutKind.Sequential, Pack = 1)] @@ -177,9 +163,8 @@ [StructLayout(LayoutKind.Sequential)] struct USB_NODE_INFORMATION { - //public int NodeType; - public USB_HUB_NODE NodeType; - public USB_HUB_INFORMATION HubInformation; // union { USB_HUB_INFORMATION HubInformation; USB_MI_PARENT_INFORMATION MiParentInformation; } + public int NodeType; + public USB_HUB_INFORMATION HubInformation; } [StructLayout(LayoutKind.Sequential, Pack = 1)] @@ -225,7 +210,7 @@ public uint ConnectionIndex; public uint ActualLength; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = UsbApi.MAX_BUFFER_SIZE)] - public string NodeName; //WCHAR NodeName[1]; + public string NodeName; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] @@ -233,7 +218,7 @@ public uint ConnectionIndex; public uint ActualLength; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = UsbApi.MAX_BUFFER_SIZE)] - public string DriverKeyName; //WCHAR DriverKeyName[1]; + public string DriverKeyName; } [StructLayout(LayoutKind.Sequential)] @@ -242,5 +227,4 @@ public uint DeviceNumber; public uint PartitionNumber; } - #endregion } diff -r edc41c861d96 -r 309c705d7460 USBLib/Windows/Devices/DeviceNode.cs --- a/USBLib/Windows/Devices/DeviceNode.cs Sun Oct 13 02:47:08 2013 +0200 +++ b/USBLib/Windows/Devices/DeviceNode.cs Sun Oct 13 18:43:45 2013 +0200 @@ -244,6 +244,7 @@ public String PhysicalDeviceObjectName { get { return GetPropertyString(CMRDP.PHYSICAL_DEVICE_OBJECT_NAME); } } public Guid? BusTypeGuid { get { return SetupApi.GetAsGuid(GetProperty(CMRDP.BUSTYPEGUID)); } } public Int32? BusNumber { get { return SetupApi.GetAsInt32(GetProperty(CMRDP.BUSNUMBER)); } } + public Int32? Address { get { return SetupApi.GetAsInt32(GetProperty(CMRDP.ADDRESS)); } } public String EnumeratorName { get { return GetPropertyString(CMRDP.ENUMERATOR_NAME); } } public String[] GetInterfaces(String classGuid) { diff -r edc41c861d96 -r 309c705d7460 USBLib/Windows/USB/UsbController.cs --- a/USBLib/Windows/USB/UsbController.cs Sun Oct 13 02:47:08 2013 +0200 +++ b/USBLib/Windows/USB/UsbController.cs Sun Oct 13 18:43:45 2013 +0200 @@ -1,21 +1,26 @@ using System; using System.Collections.Generic; +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 UsbController { - static readonly Guid IID_DEVINTERFACE_USB_HOST_CONTROLLER = new Guid(UsbApi.GUID_DEVINTERFACE_USB_HOST_CONTROLLER); public String DevicePath { get; private set; } public DeviceNode DeviceNode { get; private set; } public String DeviceDescription { get { return DeviceNode.DeviceDescription; } } public String DriverKey { get { return DeviceNode.DriverKey; } } public UsbHub RootHub { get { - String rootHubName; - using (SafeFileHandle handle = UsbHub.OpenHandle(DevicePath)) rootHubName = UsbHub.GetRootHubName(handle); - return new UsbHub(null, new USB_NODE_CONNECTION_INFORMATION_EX(), @"\\?\" + rootHubName, 0, true); + USB_ROOT_HUB_NAME rootHubName = new USB_ROOT_HUB_NAME(); + int nBytesReturned; + using (SafeFileHandle handle = UsbHub.OpenHandle(DevicePath)) + if (!Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_ROOT_HUB_NAME, IntPtr.Zero, 0, out rootHubName, Marshal.SizeOf(rootHubName), out nBytesReturned, IntPtr.Zero)) + throw new Win32Exception(Marshal.GetLastWin32Error()); + if (rootHubName.ActualLength <= 0) return null; + return new UsbHub(null, @"\\?\" + rootHubName.RootHubName, 0); } } private UsbController(DeviceNode di, String devicePath) { @@ -23,7 +28,9 @@ this.DevicePath = devicePath; } + static readonly Guid IID_DEVINTERFACE_USB_HOST_CONTROLLER = new Guid(UsbApi.GUID_DEVINTERFACE_USB_HOST_CONTROLLER); public static UsbController GetControllerForDeviceNode(DeviceNode node) { + if (node == null) return null; String[] interfaces = node.GetInterfaces(IID_DEVINTERFACE_USB_HOST_CONTROLLER); if (interfaces == null || interfaces.Length == 0) return null; return new UsbController(node, interfaces[0]); diff -r edc41c861d96 -r 309c705d7460 USBLib/Windows/USB/UsbDevice.cs --- a/USBLib/Windows/USB/UsbDevice.cs Sun Oct 13 02:47:08 2013 +0200 +++ b/USBLib/Windows/USB/UsbDevice.cs Sun Oct 13 18:43:45 2013 +0200 @@ -9,86 +9,41 @@ namespace UCIS.HWLib.Windows.USB { public class UsbDevice : IUsbDevice, IUsbInterface { - protected 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; - } - internal static Boolean GetNodeInformation(SafeFileHandle handle, out USB_NODE_INFORMATION nodeInfo) { - nodeInfo = new USB_NODE_INFORMATION(); - int nBytes = Marshal.SizeOf(typeof(USB_NODE_INFORMATION)); - return Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_NODE_INFORMATION, ref nodeInfo, nBytes, out nodeInfo, nBytes, out nBytes, IntPtr.Zero); - } - internal static Boolean GetNodeConnectionInformation(SafeFileHandle handle, UInt32 port, out USB_NODE_CONNECTION_INFORMATION_EX nodeConnection) { + internal static USB_NODE_CONNECTION_INFORMATION_EX GetNodeConnectionInformation(SafeFileHandle handle, UInt32 port) { int nBytes = Marshal.SizeOf(typeof(USB_NODE_CONNECTION_INFORMATION_EX)); - nodeConnection = new USB_NODE_CONNECTION_INFORMATION_EX(); + USB_NODE_CONNECTION_INFORMATION_EX nodeConnection = new USB_NODE_CONNECTION_INFORMATION_EX(); nodeConnection.ConnectionIndex = port; if (!Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, ref nodeConnection, nBytes, out nodeConnection, nBytes, out nBytes, IntPtr.Zero)) throw new Win32Exception(Marshal.GetLastWin32Error()); - return true; - } - protected static String GetNodeConnectionName(SafeFileHandle handle, UInt32 port) { - int nBytes = Marshal.SizeOf(typeof(USB_NODE_CONNECTION_NAME)); - USB_NODE_CONNECTION_NAME nameConnection = new USB_NODE_CONNECTION_NAME(); - nameConnection.ConnectionIndex = port; - 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()); - return nameConnection.NodeName; - } - protected unsafe static int GetDescriptor(SafeFileHandle handle, UInt32 port, byte descriptorType, byte index, short langId, byte[] buffer, int offset, int length) { - int szRequest = Marshal.SizeOf(typeof(USB_DESCRIPTOR_REQUEST)); - USB_DESCRIPTOR_REQUEST request = new USB_DESCRIPTOR_REQUEST(); - request.ConnectionIndex = port; - request.SetupPacket.Value = (short)((descriptorType << 8) + index); - request.SetupPacket.Index = (short)langId; - request.SetupPacket.Length = (short)length; - int nBytes = length + szRequest; - Byte[] bigbuffer = new Byte[nBytes]; - if (!Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ref request, Marshal.SizeOf(typeof(USB_DESCRIPTOR_REQUEST)), bigbuffer, nBytes, out nBytes, IntPtr.Zero)) { - int err = Marshal.GetLastWin32Error(); - if (err != 2 && err != 31 && err != 87) throw new Win32Exception(err); - return 0; - } - nBytes -= szRequest; - if (nBytes > length) nBytes = length; - if (nBytes < 0) return 0; - if (nBytes > 0) Buffer.BlockCopy(bigbuffer, szRequest, buffer, offset, nBytes); - return nBytes; - } - protected internal unsafe static String GetRootHubName(SafeFileHandle handle) { - USB_ROOT_HUB_NAME rootHubName = new USB_ROOT_HUB_NAME(); - int nBytesReturned; - if (!Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_ROOT_HUB_NAME, IntPtr.Zero, 0, out rootHubName, Marshal.SizeOf(rootHubName), out nBytesReturned, IntPtr.Zero)) - throw new Win32Exception(Marshal.GetLastWin32Error()); - if (rootHubName.ActualLength <= 0) return null; - return rootHubName.RootHubName; - } - protected unsafe static String GetNodeConnectionDriverKey(SafeFileHandle handle, UInt32 port) { - USB_NODE_CONNECTION_DRIVERKEY_NAME DriverKeyStruct = new USB_NODE_CONNECTION_DRIVERKEY_NAME(); - int nBytes = Marshal.SizeOf(DriverKeyStruct); - DriverKeyStruct.ConnectionIndex = port; - if (!Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, ref DriverKeyStruct, nBytes, out DriverKeyStruct, nBytes, out nBytes, IntPtr.Zero)) - return null; - return DriverKeyStruct.DriverKeyName; + return nodeConnection; } - public UsbDevice Parent { get; protected set; } - public String DevicePath { get; private set; } - public UInt32 AdapterNumber { get; private set; } - internal USB_NODE_CONNECTION_INFORMATION_EX NodeConnectionInfo { get; set; } - public UsbDeviceDescriptor DeviceDescriptor { get { return NodeConnectionInfo.DeviceDescriptor; } } + private Boolean HasNodeConnectionInfo = false; + private USB_NODE_CONNECTION_INFORMATION_EX NodeConnectionInfo; - public bool IsHub { get { return NodeConnectionInfo.DeviceIsHub != 0; } } - public bool IsConnected { get { return NodeConnectionInfo.ConnectionStatus == USB_CONNECTION_STATUS.DeviceConnected; } } - public string Status { get { return NodeConnectionInfo.ConnectionStatus.ToString(); } } - public string Speed { get { return NodeConnectionInfo.Speed.ToString(); } } - public Byte CurrentConfigurationValue { get { return NodeConnectionInfo.CurrentConfigurationValue; } } - public UInt16 DeviceAddress { get { return NodeConnectionInfo.DeviceAddress; } } - public UInt32 NumberOfOpenPipes { get { return NodeConnectionInfo.NumberOfOpenPipes; } } + private void GetNodeConnectionInfo() { + if (HasNodeConnectionInfo) return; + if (Parent == null) { + HasNodeConnectionInfo = true; + return; + } + using (SafeFileHandle handle = Parent.OpenHandle()) NodeConnectionInfo = GetNodeConnectionInformation(handle, AdapterNumber); + HasNodeConnectionInfo = true; + } + internal void SetNodeConnectionInfo(USB_NODE_CONNECTION_INFORMATION_EX nci) { + NodeConnectionInfo = nci; + HasNodeConnectionInfo = true; + } - SafeFileHandle OpenHandle() { - return OpenHandle(DevicePath); - } + public UsbDeviceDescriptor DeviceDescriptor { get { GetNodeConnectionInfo(); return NodeConnectionInfo.DeviceDescriptor; } } + + public bool IsHub { get { GetNodeConnectionInfo(); return NodeConnectionInfo.DeviceIsHub != 0; } } + public bool IsConnected { get { GetNodeConnectionInfo(); return NodeConnectionInfo.ConnectionStatus == USB_CONNECTION_STATUS.DeviceConnected; } } + public string Status { get { GetNodeConnectionInfo(); return NodeConnectionInfo.ConnectionStatus.ToString(); } } + public string Speed { get { GetNodeConnectionInfo(); return NodeConnectionInfo.Speed.ToString(); } } + public Byte CurrentConfigurationValue { get { GetNodeConnectionInfo(); return NodeConnectionInfo.CurrentConfigurationValue; } } + public UInt16 DeviceAddress { get { GetNodeConnectionInfo(); return NodeConnectionInfo.DeviceAddress; } } + public UInt32 NumberOfOpenPipes { get { GetNodeConnectionInfo(); return NodeConnectionInfo.NumberOfOpenPipes; } } public int NumConfigurations { get { return DeviceDescriptor.NumConfigurations; } } public int VendorID { get { return DeviceDescriptor.VendorID; } } @@ -96,7 +51,7 @@ private String GetStringSafe(Byte id) { if (id == 0) return null; - String s = GetStringDescriptor(id); + String s = GetString(id, 0); if (s == null) return s; return s.Trim(' ', '\0'); } @@ -104,12 +59,27 @@ public string Manufacturer { get { return GetStringSafe(DeviceDescriptor.ManufacturerStringID); } } public string Product { get { return GetStringSafe(DeviceDescriptor.ProductStringID); } } public string SerialNumber { get { return GetStringSafe(DeviceDescriptor.SerialNumberStringID); } } - public virtual string DriverKey { get { using (SafeFileHandle handle = OpenHandle(DevicePath)) return UsbHub.GetNodeConnectionDriverKey(handle, AdapterNumber); } } + public String DriverKey { + get { + if (mParent != null) { + using (SafeFileHandle handle = mParent.OpenHandle()) { + USB_NODE_CONNECTION_DRIVERKEY_NAME DriverKeyStruct = new USB_NODE_CONNECTION_DRIVERKEY_NAME(); + int nBytes = Marshal.SizeOf(DriverKeyStruct); + DriverKeyStruct.ConnectionIndex = AdapterNumber; + if (!Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, ref DriverKeyStruct, nBytes, out DriverKeyStruct, nBytes, out nBytes, IntPtr.Zero)) + return null; + return DriverKeyStruct.DriverKeyName; + } + } + if (mDeviceNode != null) return mDeviceNode.DriverKey; + return null; + } + } public virtual string DeviceDescription { get { return DeviceNode == null ? null : DeviceNode.DeviceDescription; } } public string DeviceID { get { return DeviceNode == null ? null : DeviceNode.DeviceID; } } - private DeviceNode mDeviceNode; + protected DeviceNode mDeviceNode = null; public DeviceNode DeviceNode { get { String dk = DriverKey; @@ -124,57 +94,69 @@ return mDeviceNode; } } + protected UsbHub mParent = null; + private UInt32 mAdapterNumber = 0; + private UsbHub GetParent() { + if (mParent == null && mDeviceNode != null) { + mParent = UsbHub.GetHubForDeviceNode(mDeviceNode.GetParent()); + if (mParent != null) { + UsbDevice self = mParent.FindChildForDeviceNode(mDeviceNode); + if (self != null) mAdapterNumber = self.AdapterNumber; + } + } + return mParent; + } + public UsbHub Parent { get { return GetParent(); } } + public UInt32 AdapterNumber { get { GetParent(); return mAdapterNumber; } } - internal UsbDevice(UsbDevice parent, USB_NODE_CONNECTION_INFORMATION_EX nci, uint port, string devicePath) { - this.Parent = parent; - this.NodeConnectionInfo = nci; - this.DevicePath = devicePath; - this.AdapterNumber = port; - if (devicePath == null) return; + internal UsbDevice(DeviceNode devnode, UsbHub parent, uint port) { + this.mDeviceNode = devnode; + this.mParent = parent; + this.mAdapterNumber = port; } - private String GetStringDescriptor(Byte index) { - return UsbStringDescriptor.GetStringFromDevice(this, index, 0); //0x409 - } - - static UsbDevice GetUsbDevice(DeviceNode node, out Boolean isHostController) { - UsbController controller = UsbController.GetControllerForDeviceNode(node); - if (controller != null) { - isHostController = true; - return controller.RootHub; - } - isHostController = false; + public static UsbDevice GetUsbDevice(DeviceNode node) { + if (node == null) return null; + //UsbController controller = UsbController.GetControllerForDeviceNode(node); + //if (controller != null) return controller; + UsbHub hub = UsbHub.GetHubForDeviceNode(node); + if (hub != null) return hub; DeviceNode parent = node.GetParent(); if (parent == null) return null; - Boolean isHostControllerA; - UsbDevice usbdev = GetUsbDevice(parent, out isHostControllerA); - if (isHostControllerA) return usbdev; - UsbHub usbhub = usbdev as UsbHub; - if (usbhub == null) { - if (parent.Service == "usbccgp") return usbdev; - return null; - } - String driverkey = node.DriverKey; - if (driverkey == null) return null; - foreach (UsbDevice child in usbhub.Devices) { - if (driverkey.Equals(child.DriverKey, StringComparison.InvariantCultureIgnoreCase)) return child; - } - return null; - } - public static UsbDevice GetUsbDevice(DeviceNode node) { - Boolean isHostController; - return GetUsbDevice(node, out isHostController); + if (parent.Service == "usbccgp") return GetUsbDevice(parent); + hub = UsbHub.GetHubForDeviceNode(parent); + if (hub == null) return null; + return hub.FindChildForDeviceNode(node); } - #region IUsbInterface Members + #region IUsbInterface and IUsbDevice Members + public int GetDescriptor(byte descriptorType, byte index, short langId, byte[] buffer, int offset, int length) { + using (SafeFileHandle handle = Parent.OpenHandle()) { + int szRequest = Marshal.SizeOf(typeof(USB_DESCRIPTOR_REQUEST)); + USB_DESCRIPTOR_REQUEST request = new USB_DESCRIPTOR_REQUEST(); + request.ConnectionIndex = AdapterNumber; + request.SetupPacket.Value = (short)((descriptorType << 8) + index); + request.SetupPacket.Index = (short)langId; + request.SetupPacket.Length = (short)length; + int nBytes = length + szRequest; + Byte[] bigbuffer = new Byte[nBytes]; + if (!Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ref request, Marshal.SizeOf(typeof(USB_DESCRIPTOR_REQUEST)), bigbuffer, nBytes, out nBytes, IntPtr.Zero)) { + int err = Marshal.GetLastWin32Error(); + if (err != 2 && err != 31 && err != 87) throw new Win32Exception(err); + return 0; + } + nBytes -= szRequest; + if (nBytes > length) nBytes = length; + if (nBytes < 0) return 0; + if (nBytes > 0) Buffer.BlockCopy(bigbuffer, szRequest, buffer, offset, nBytes); + return nBytes; + } + } + public String GetString(short langId, byte stringIndex) { + return UsbStringDescriptor.GetStringFromDevice(this, stringIndex, langId); + } byte IUsbInterface.Configuration { get { throw new NotImplementedException(); } } void IUsbInterface.Close() { } - public virtual int GetDescriptor(byte descriptorType, byte index, short langId, byte[] buffer, int offset, int length) { - using (SafeFileHandle handle = UsbHub.OpenHandle(DevicePath)) return UsbHub.GetDescriptor(handle, AdapterNumber, descriptorType, index, langId, buffer, offset, length); - } - string IUsbInterface.GetString(short langId, byte stringIndex) { - return UsbStringDescriptor.GetStringFromDevice(this, stringIndex, langId); - } int IUsbInterface.BulkWrite(byte endpoint, byte[] buffer, int offset, int length) { throw new NotImplementedException(); } int IUsbInterface.BulkRead(byte endpoint, byte[] buffer, int offset, int length) { throw new NotImplementedException(); } void IUsbInterface.BulkReset(byte endpoint) { throw new NotImplementedException(); } @@ -186,8 +168,6 @@ UsbPipeStream IUsbInterface.GetBulkStream(byte endpoint) { throw new NotImplementedException(); } UsbPipeStream IUsbInterface.GetInterruptStream(byte endpoint) { throw new NotImplementedException(); } void IDisposable.Dispose() { } - #endregion - #region IUsbDevice Members byte IUsbDevice.Configuration { get { throw new NotSupportedException(); } set { throw new NotSupportedException(); } } void IUsbDevice.ClaimInterface(int interfaceID) { } void IUsbDevice.ReleaseInterface(int interfaceID) { } diff -r edc41c861d96 -r 309c705d7460 USBLib/Windows/USB/UsbHub.cs --- 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 Devices { get { - List devices = new List(); - 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 GetHubs() { + IList devices = new List(); + 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; } } }