Mercurial > hg > ucis.core
comparison 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 |
comparison
equal
deleted
inserted
replaced
62:edc41c861d96 | 63:309c705d7460 |
---|---|
1 using System; | 1 using System; |
2 using System.Collections.Generic; | 2 using System.Collections.Generic; |
3 using System.ComponentModel; | 3 using System.ComponentModel; |
4 using System.Runtime.InteropServices; | 4 using System.Runtime.InteropServices; |
5 using Microsoft.Win32.SafeHandles; | 5 using Microsoft.Win32.SafeHandles; |
6 using UCIS.HWLib.Windows.Devices; | |
6 using UCIS.USBLib.Internal.Windows; | 7 using UCIS.USBLib.Internal.Windows; |
7 | 8 |
8 namespace UCIS.HWLib.Windows.USB { | 9 namespace UCIS.HWLib.Windows.USB { |
9 public class UsbHub : UsbDevice { | 10 public class UsbHub : UsbDevice { |
10 public bool IsRootHub { get; private set; } | 11 internal static SafeFileHandle OpenHandle(String path) { |
11 internal USB_NODE_INFORMATION NodeInformation { get; private set; } | 12 SafeFileHandle handle = Kernel32.CreateFile(path, Kernel32.GENERIC_WRITE, Kernel32.FILE_SHARE_WRITE, IntPtr.Zero, Kernel32.OPEN_EXISTING, 0, IntPtr.Zero); |
12 | 13 if (handle.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error()); |
13 public int PortCount { get { return NodeInformation.HubInformation.HubDescriptor.bNumberOfPorts; } } | 14 return handle; |
14 public bool IsBusPowered { get { return NodeInformation.HubInformation.HubIsBusPowered; } } | |
15 public override string DeviceDescription { get { return IsRootHub ? "RootHub" : "Standard-USB-Hub"; } } | |
16 | |
17 public override string DriverKey { | |
18 get { | |
19 if (Parent == null) return null; | |
20 using (SafeFileHandle handle = OpenHandle(Parent.DevicePath)) return GetNodeConnectionDriverKey(handle, AdapterNumber); | |
21 } | |
22 } | |
23 | |
24 internal UsbHub(UsbDevice parent, USB_NODE_CONNECTION_INFORMATION_EX nci, string devicePath, uint port, Boolean roothub) | |
25 : base(parent, nci, port, devicePath) { | |
26 this.IsRootHub = roothub; | |
27 using (SafeFileHandle handle = OpenHandle(DevicePath)) { | |
28 USB_NODE_INFORMATION NodeInfo; | |
29 GetNodeInformation(handle, out NodeInfo); | |
30 this.NodeInformation = NodeInfo; | |
31 } | |
32 } | 15 } |
33 | 16 |
34 public override int GetDescriptor(byte descriptorType, byte index, short langId, byte[] buffer, int offset, int length) { | 17 private Boolean HasNodeInformation = false; |
35 if (Parent == null) return 0; | 18 private USB_NODE_INFORMATION NodeInformation; |
36 using (SafeFileHandle handle = UsbHub.OpenHandle(Parent.DevicePath)) return GetDescriptor(handle, AdapterNumber, descriptorType, index, langId, buffer, offset, length); | 19 |
20 private void GetNodeInformation() { | |
21 if (HasNodeInformation) return; | |
22 NodeInformation = new USB_NODE_INFORMATION(); | |
23 int nBytes = Marshal.SizeOf(typeof(USB_NODE_INFORMATION)); | |
24 using (SafeFileHandle handle = OpenHandle()) | |
25 if (!Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_NODE_INFORMATION, ref NodeInformation, nBytes, out NodeInformation, nBytes, out nBytes, IntPtr.Zero)) | |
26 throw new Win32Exception(Marshal.GetLastWin32Error()); | |
37 } | 27 } |
38 | 28 |
29 public bool IsRootHub { get; private set; } | |
30 public int PortCount { get { GetNodeInformation(); return NodeInformation.HubInformation.HubDescriptor.bNumberOfPorts; } } | |
31 public bool IsBusPowered { get { GetNodeInformation(); return NodeInformation.HubInformation.HubIsBusPowered; } } | |
32 public override string DeviceDescription { get { return IsRootHub ? "Root hub" : base.DeviceDescription; } } | |
33 | |
34 public String DevicePath { get; private set; } | |
35 | |
36 internal UsbHub(UsbHub parent, string devicePath, uint port) | |
37 : base(null, parent, port) { | |
38 this.DevicePath = devicePath; | |
39 this.IsRootHub = (parent == null); | |
40 if (IsRootHub) SetNodeConnectionInfo(new USB_NODE_CONNECTION_INFORMATION_EX()); | |
41 } | |
42 | |
43 private UsbHub(DeviceNode devnode, string devicePath) | |
44 : base(devnode, null, 0) { | |
45 this.DevicePath = devicePath; | |
46 this.IsRootHub = false; | |
47 } | |
48 | |
49 internal SafeFileHandle OpenHandle() { | |
50 return OpenHandle(DevicePath); | |
51 } | |
39 | 52 |
40 public IList<UsbDevice> Devices { | 53 public IList<UsbDevice> Devices { |
41 get { | 54 get { |
42 List<UsbDevice> devices = new List<UsbDevice>(); | 55 UsbDevice[] devices = new UsbDevice[PortCount]; |
43 using (SafeFileHandle handle = OpenHandle(DevicePath)) { | 56 using (SafeFileHandle handle = OpenHandle()) { |
44 for (uint index = 1; index <= PortCount; index++) { | 57 for (uint index = 1; index <= PortCount; index++) { |
45 devices.Add(BuildDevice(this, index, this.DevicePath, handle)); | 58 USB_NODE_CONNECTION_INFORMATION_EX nodeConnection = GetNodeConnectionInformation(handle, index); |
59 UsbDevice device; | |
60 if (nodeConnection.ConnectionStatus != USB_CONNECTION_STATUS.DeviceConnected) { | |
61 device = new UsbDevice(null, this, index); | |
62 } else if (nodeConnection.DeviceDescriptor.DeviceClass == (Byte)UsbDeviceClass.HubDevice) { | |
63 int nBytes = Marshal.SizeOf(typeof(USB_NODE_CONNECTION_NAME)); | |
64 USB_NODE_CONNECTION_NAME nameConnection = new USB_NODE_CONNECTION_NAME(); | |
65 nameConnection.ConnectionIndex = index; | |
66 if (!Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_NODE_CONNECTION_NAME, ref nameConnection, nBytes, out nameConnection, nBytes, out nBytes, IntPtr.Zero)) | |
67 throw new Win32Exception(Marshal.GetLastWin32Error()); | |
68 device = new UsbHub(this, @"\\?\" + nameConnection.NodeName, index); | |
69 } else { | |
70 device = new UsbDevice(null, this, index); | |
71 } | |
72 device.SetNodeConnectionInfo(nodeConnection); | |
73 devices[index - 1] = device; | |
46 } | 74 } |
47 } | 75 } |
48 return devices; | 76 return devices; |
49 } | 77 } |
50 } | 78 } |
51 | 79 |
52 internal static UsbDevice BuildDevice(UsbDevice parent, uint portCount, string devicePath) { | 80 static readonly Guid IID_DEVINTERFACE_USB_HUB = new Guid(UsbApi.GUID_DEVINTERFACE_USB_HUB); |
53 using (SafeFileHandle handle = OpenHandle(devicePath)) return BuildDevice(parent, portCount, devicePath, handle); | 81 public static UsbHub GetHubForDeviceNode(DeviceNode node) { |
82 if (node == null) return null; | |
83 String[] interfaces = node.GetInterfaces(IID_DEVINTERFACE_USB_HUB); | |
84 if (interfaces == null || interfaces.Length == 0) return null; | |
85 return new UsbHub(node, interfaces[0]); | |
54 } | 86 } |
55 internal static UsbDevice BuildDevice(UsbDevice parent, uint portCount, string devicePath, SafeFileHandle handle) { | 87 |
56 USB_NODE_CONNECTION_INFORMATION_EX nodeConnection; | 88 public static IList<UsbHub> GetHubs() { |
57 if (!GetNodeConnectionInformation(handle, portCount, out nodeConnection)) throw new Win32Exception(Marshal.GetLastWin32Error()); | 89 IList<UsbHub> devices = new List<UsbHub>(); |
58 UsbDevice device = null; | 90 foreach (DeviceNode dev in DeviceNode.GetDevices(IID_DEVINTERFACE_USB_HUB)) { |
59 if (nodeConnection.ConnectionStatus != USB_CONNECTION_STATUS.DeviceConnected) { | 91 UsbHub hub = GetHubForDeviceNode(dev); |
60 device = new UsbDevice(parent, nodeConnection, portCount, devicePath); | 92 if (hub != null) devices.Add(hub); |
61 } else if (nodeConnection.DeviceDescriptor.DeviceClass == (Byte)UsbDeviceClass.HubDevice) { | 93 } |
62 String nodeName = GetNodeConnectionName(handle, portCount); | 94 return devices; |
63 device = new UsbHub(parent, nodeConnection, @"\\?\" + nodeName, portCount, false); | 95 } |
96 | |
97 public UsbDevice FindChildForDeviceNode(DeviceNode node) { | |
98 String driverkey = node.DriverKey; | |
99 if (driverkey != null) { | |
100 foreach (UsbDevice child in Devices) if (driverkey.Equals(child.DriverKey, StringComparison.InvariantCultureIgnoreCase)) return child; | |
64 } else { | 101 } else { |
65 device = new UsbDevice(parent, nodeConnection, portCount, devicePath); | 102 int? address = node.Address; |
103 if (address == null || address.Value == 0) return null; | |
104 int port = address.Value; | |
105 foreach (UsbDevice child in Devices) if (port == child.AdapterNumber) return child; | |
66 } | 106 } |
67 device.NodeConnectionInfo = nodeConnection; | 107 return null; |
68 return device; | |
69 } | 108 } |
70 } | 109 } |
71 } | 110 } |