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