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 }