comparison USBLib/Windows/USB/UsbHub.cs @ 58:fd63c453ff65

Improved Windows USB enumeration classes
author Ivo Smits <Ivo@UCIS.nl>
date Wed, 09 Oct 2013 20:54:15 +0200
parents 5b14fed54a89
children 3424fa5a12c9
comparison
equal deleted inserted replaced
57:b1efeada517e 58:fd63c453ff65
1 using System; 1 using System;
2 using System.Collections.Generic; 2 using System.Collections.Generic;
3 using System.Runtime.InteropServices; 3 using System.Runtime.InteropServices;
4 using Microsoft.Win32.SafeHandles; 4 using Microsoft.Win32.SafeHandles;
5 using UCIS.USBLib.Internal.Windows; 5 using UCIS.USBLib.Internal.Windows;
6 using System.ComponentModel;
7 using UCIS.USBLib.Communication;
6 8
7 namespace UCIS.HWLib.Windows.USB { 9 namespace UCIS.HWLib.Windows.USB {
8 public class UsbHub : UsbDevice { 10 public class UsbHub : UsbDevice {
9 public int PortCount { get; private set; }
10 public bool IsBusPowered { get; private set; }
11 public bool IsRootHub { get; private set; } 11 public bool IsRootHub { get; private set; }
12 internal USB_NODE_INFORMATION NodeInformation { get; private set; } 12 internal USB_NODE_INFORMATION NodeInformation { get; private set; }
13 private List<UsbDevice> devices = new List<UsbDevice>(); 13
14 public IList<UsbDevice> Devices { get { return devices.AsReadOnly(); } } 14 public int PortCount { get { return NodeInformation.HubInformation.HubDescriptor.bNumberOfPorts; } }
15 public bool IsBusPowered { get { return NodeInformation.HubInformation.HubIsBusPowered; } }
15 public override string DeviceDescription { get { return IsRootHub ? "RootHub" : "Standard-USB-Hub"; } } 16 public override string DeviceDescription { get { return IsRootHub ? "RootHub" : "Standard-USB-Hub"; } }
16 internal UsbHub(UsbController parent, USB_DEVICE_DESCRIPTOR deviceDescriptor, string devicePath) 17
17 : this(null, deviceDescriptor, devicePath, true) { } 18 public override string DriverKey {
18 internal UsbHub(UsbDevice parent, USB_DEVICE_DESCRIPTOR deviceDescriptor, string devicePath, Boolean roothub) 19 get {
19 : base(parent, deviceDescriptor, 0, devicePath) { 20 if (Parent == null) return null;
21 using (SafeFileHandle handle = OpenHandle(Parent.DevicePath)) return UsbHub.GetNodeConnectionDriverKey(handle, AdapterNumber);
22 }
23 }
24
25 internal UsbHub(UsbDevice parent, USB_NODE_CONNECTION_INFORMATION_EX nci, string devicePath, uint port, Boolean roothub)
26 : base(parent, nci, port, devicePath) {
20 this.IsRootHub = roothub; 27 this.IsRootHub = roothub;
21 28 using (SafeFileHandle handle = OpenHandle(DevicePath)) {
22 // TODO: Get the driver key name for the root hub. 29 USB_NODE_INFORMATION NodeInfo;
23 // Now let's open the hub (based upon the hub name we got above). 30 GetNodeInformation(handle, out NodeInfo);
24 using (SafeFileHandle handel2 = Kernel32.CreateFile(this.DevicePath, Kernel32.GENERIC_WRITE, Kernel32.FILE_SHARE_WRITE, IntPtr.Zero, Kernel32.OPEN_EXISTING, 0, IntPtr.Zero)) { 31 this.NodeInformation = NodeInfo;
25 if (handel2.IsInvalid) throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
26 USB_NODE_INFORMATION NodeInfo = new USB_NODE_INFORMATION();
27 int nBytes = Marshal.SizeOf(typeof(USB_NODE_INFORMATION)); // Marshal.SizeOf(NodeInfo);
28 // Get the hub information.
29 int nBytesReturned = -1;
30 if (Kernel32.DeviceIoControl(handel2, UsbApi.IOCTL_USB_GET_NODE_INFORMATION, ref NodeInfo, nBytes, out NodeInfo, nBytes, out nBytesReturned, IntPtr.Zero)) {
31 this.NodeInformation = NodeInfo;
32 this.IsBusPowered = Convert.ToBoolean(NodeInfo.HubInformation.HubIsBusPowered);
33 this.PortCount = NodeInfo.HubInformation.HubDescriptor.bNumberOfPorts;
34 }
35
36 for (uint index = 1; index <= PortCount; index++) {
37 devices.Add(BuildDevice(this, index, this.DevicePath, handel2));
38 }
39 } 32 }
40 } 33 }
41 34
42 private static UsbDevice BuildDevice(UsbDevice parent, uint portCount, string devicePath, SafeFileHandle handel1) { 35 public override int GetDescriptor(byte descriptorType, byte index, short langId, byte[] buffer, int offset, int length) {
43 int nBytesReturned; 36 if (Parent == null) return 0;
44 int nBytes = Marshal.SizeOf(typeof(USB_NODE_CONNECTION_INFORMATION_EX)); 37 using (SafeFileHandle handle = UsbHub.OpenHandle(Parent.DevicePath)) return UsbHub.GetDescriptor(handle, AdapterNumber, descriptorType, index, langId, buffer, offset, length);
45 USB_NODE_CONNECTION_INFORMATION_EX nodeConnection = new USB_NODE_CONNECTION_INFORMATION_EX(); 38 }
46 nodeConnection.ConnectionIndex = portCount;
47 39
48 //DateTime t = DateTime.Now;
49 if (!Kernel32.DeviceIoControl(handel1, UsbApi.IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, ref nodeConnection, nBytes, out nodeConnection, nBytes, out nBytesReturned, IntPtr.Zero))
50 throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
51 //Console.WriteLine("IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX took {0} ms (class={1})", DateTime.Now.Subtract(t).TotalMilliseconds, nodeConnection.DeviceDescriptor.bDeviceClass);
52 bool isConnected = (nodeConnection.ConnectionStatus == USB_CONNECTION_STATUS.DeviceConnected);
53 40
54 UsbDevice _Device = null; 41 public IList<UsbDevice> Devices {
55 if (!isConnected) { 42 get {
56 _Device = new UsbDevice(parent, null, portCount); 43 List<UsbDevice> devices = new List<UsbDevice>();
44 using (SafeFileHandle handle = OpenHandle(DevicePath)) {
45 for (uint index = 1; index <= PortCount; index++) {
46 devices.Add(BuildDevice(this, index, this.DevicePath, handle));
47 }
48 }
49 return devices;
50 }
51 }
52
53 internal static UsbDevice BuildDevice(UsbDevice parent, uint portCount, string devicePath) {
54 using (SafeFileHandle handle = OpenHandle(devicePath)) return BuildDevice(parent, portCount, devicePath, handle);
55 }
56 internal static UsbDevice BuildDevice(UsbDevice parent, uint portCount, string devicePath, SafeFileHandle handle) {
57 USB_NODE_CONNECTION_INFORMATION_EX nodeConnection;
58 if (!GetNodeConnectionInformation(handle, portCount, out nodeConnection)) throw new Win32Exception(Marshal.GetLastWin32Error());
59 UsbDevice device = null;
60 if (nodeConnection.ConnectionStatus != USB_CONNECTION_STATUS.DeviceConnected) {
61 device = new UsbDevice(parent, nodeConnection, portCount, devicePath);
57 } else if (nodeConnection.DeviceDescriptor.bDeviceClass == UsbDeviceClass.HubDevice) { 62 } else if (nodeConnection.DeviceDescriptor.bDeviceClass == UsbDeviceClass.HubDevice) {
58 nBytes = Marshal.SizeOf(typeof(USB_NODE_CONNECTION_NAME)); 63 String nodeName = GetNodeConnectionName(handle, portCount);
59 USB_NODE_CONNECTION_NAME nameConnection = new USB_NODE_CONNECTION_NAME(); 64 device = new UsbHub(parent, nodeConnection, @"\\?\" + nodeName, portCount, false);
60 nameConnection.ConnectionIndex = portCount;
61 if (!Kernel32.DeviceIoControl(handel1, UsbApi.IOCTL_USB_GET_NODE_CONNECTION_NAME, ref nameConnection, nBytes, out nameConnection, nBytes, out nBytesReturned, IntPtr.Zero))
62 throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
63 _Device = new UsbHub(parent, nodeConnection.DeviceDescriptor, @"\\?\" + nameConnection.NodeName, false);
64 } else { 65 } else {
65 _Device = new UsbDevice(parent, nodeConnection.DeviceDescriptor, portCount, devicePath); 66 device = new UsbDevice(parent, nodeConnection, portCount, devicePath);
66 } 67 }
67 _Device.NodeConnectionInfo = nodeConnection; 68 device.NodeConnectionInfo = nodeConnection;
68 _Device.AdapterNumber = _Device.NodeConnectionInfo.ConnectionIndex; 69 return device;
69 _Device.Status = ((USB_CONNECTION_STATUS)_Device.NodeConnectionInfo.ConnectionStatus).ToString();
70 _Device.Speed = ((USB_DEVICE_SPEED)_Device.NodeConnectionInfo.Speed).ToString();
71 _Device.IsConnected = isConnected;
72 _Device.IsHub = Convert.ToBoolean(_Device.NodeConnectionInfo.DeviceIsHub);
73 return _Device;
74 } 70 }
75 } 71 }
76 } 72 }