comparison USBLib/Windows/USB/UsbDevice.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 abe0d55a2201
comparison
equal deleted inserted replaced
62:edc41c861d96 63:309c705d7460
7 using UCIS.USBLib.Descriptor; 7 using UCIS.USBLib.Descriptor;
8 using UCIS.USBLib.Internal.Windows; 8 using UCIS.USBLib.Internal.Windows;
9 9
10 namespace UCIS.HWLib.Windows.USB { 10 namespace UCIS.HWLib.Windows.USB {
11 public class UsbDevice : IUsbDevice, IUsbInterface { 11 public class UsbDevice : IUsbDevice, IUsbInterface {
12 protected internal static SafeFileHandle OpenHandle(String path) { 12 internal static USB_NODE_CONNECTION_INFORMATION_EX GetNodeConnectionInformation(SafeFileHandle handle, UInt32 port) {
13 SafeFileHandle handle = Kernel32.CreateFile(path, Kernel32.GENERIC_WRITE, Kernel32.FILE_SHARE_WRITE, IntPtr.Zero, Kernel32.OPEN_EXISTING, 0, IntPtr.Zero);
14 if (handle.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error());
15 return handle;
16 }
17 internal static Boolean GetNodeInformation(SafeFileHandle handle, out USB_NODE_INFORMATION nodeInfo) {
18 nodeInfo = new USB_NODE_INFORMATION();
19 int nBytes = Marshal.SizeOf(typeof(USB_NODE_INFORMATION));
20 return Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_NODE_INFORMATION, ref nodeInfo, nBytes, out nodeInfo, nBytes, out nBytes, IntPtr.Zero);
21 }
22 internal static Boolean GetNodeConnectionInformation(SafeFileHandle handle, UInt32 port, out USB_NODE_CONNECTION_INFORMATION_EX nodeConnection) {
23 int nBytes = Marshal.SizeOf(typeof(USB_NODE_CONNECTION_INFORMATION_EX)); 13 int nBytes = Marshal.SizeOf(typeof(USB_NODE_CONNECTION_INFORMATION_EX));
24 nodeConnection = new USB_NODE_CONNECTION_INFORMATION_EX(); 14 USB_NODE_CONNECTION_INFORMATION_EX nodeConnection = new USB_NODE_CONNECTION_INFORMATION_EX();
25 nodeConnection.ConnectionIndex = port; 15 nodeConnection.ConnectionIndex = port;
26 if (!Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, ref nodeConnection, nBytes, out nodeConnection, nBytes, out nBytes, IntPtr.Zero)) 16 if (!Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, ref nodeConnection, nBytes, out nodeConnection, nBytes, out nBytes, IntPtr.Zero))
27 throw new Win32Exception(Marshal.GetLastWin32Error()); 17 throw new Win32Exception(Marshal.GetLastWin32Error());
28 return true; 18 return nodeConnection;
29 }
30 protected static String GetNodeConnectionName(SafeFileHandle handle, UInt32 port) {
31 int nBytes = Marshal.SizeOf(typeof(USB_NODE_CONNECTION_NAME));
32 USB_NODE_CONNECTION_NAME nameConnection = new USB_NODE_CONNECTION_NAME();
33 nameConnection.ConnectionIndex = port;
34 if (!Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_NODE_CONNECTION_NAME, ref nameConnection, nBytes, out nameConnection, nBytes, out nBytes, IntPtr.Zero))
35 throw new Win32Exception(Marshal.GetLastWin32Error());
36 return nameConnection.NodeName;
37 }
38 protected unsafe static int GetDescriptor(SafeFileHandle handle, UInt32 port, byte descriptorType, byte index, short langId, byte[] buffer, int offset, int length) {
39 int szRequest = Marshal.SizeOf(typeof(USB_DESCRIPTOR_REQUEST));
40 USB_DESCRIPTOR_REQUEST request = new USB_DESCRIPTOR_REQUEST();
41 request.ConnectionIndex = port;
42 request.SetupPacket.Value = (short)((descriptorType << 8) + index);
43 request.SetupPacket.Index = (short)langId;
44 request.SetupPacket.Length = (short)length;
45 int nBytes = length + szRequest;
46 Byte[] bigbuffer = new Byte[nBytes];
47 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)) {
48 int err = Marshal.GetLastWin32Error();
49 if (err != 2 && err != 31 && err != 87) throw new Win32Exception(err);
50 return 0;
51 }
52 nBytes -= szRequest;
53 if (nBytes > length) nBytes = length;
54 if (nBytes < 0) return 0;
55 if (nBytes > 0) Buffer.BlockCopy(bigbuffer, szRequest, buffer, offset, nBytes);
56 return nBytes;
57 }
58 protected internal unsafe static String GetRootHubName(SafeFileHandle handle) {
59 USB_ROOT_HUB_NAME rootHubName = new USB_ROOT_HUB_NAME();
60 int nBytesReturned;
61 if (!Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_ROOT_HUB_NAME, IntPtr.Zero, 0, out rootHubName, Marshal.SizeOf(rootHubName), out nBytesReturned, IntPtr.Zero))
62 throw new Win32Exception(Marshal.GetLastWin32Error());
63 if (rootHubName.ActualLength <= 0) return null;
64 return rootHubName.RootHubName;
65 }
66 protected unsafe static String GetNodeConnectionDriverKey(SafeFileHandle handle, UInt32 port) {
67 USB_NODE_CONNECTION_DRIVERKEY_NAME DriverKeyStruct = new USB_NODE_CONNECTION_DRIVERKEY_NAME();
68 int nBytes = Marshal.SizeOf(DriverKeyStruct);
69 DriverKeyStruct.ConnectionIndex = port;
70 if (!Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, ref DriverKeyStruct, nBytes, out DriverKeyStruct, nBytes, out nBytes, IntPtr.Zero))
71 return null;
72 return DriverKeyStruct.DriverKeyName;
73 } 19 }
74 20
75 public UsbDevice Parent { get; protected set; } 21 private Boolean HasNodeConnectionInfo = false;
76 public String DevicePath { get; private set; } 22 private USB_NODE_CONNECTION_INFORMATION_EX NodeConnectionInfo;
77 public UInt32 AdapterNumber { get; private set; }
78 internal USB_NODE_CONNECTION_INFORMATION_EX NodeConnectionInfo { get; set; }
79 public UsbDeviceDescriptor DeviceDescriptor { get { return NodeConnectionInfo.DeviceDescriptor; } }
80 23
81 public bool IsHub { get { return NodeConnectionInfo.DeviceIsHub != 0; } } 24 private void GetNodeConnectionInfo() {
82 public bool IsConnected { get { return NodeConnectionInfo.ConnectionStatus == USB_CONNECTION_STATUS.DeviceConnected; } } 25 if (HasNodeConnectionInfo) return;
83 public string Status { get { return NodeConnectionInfo.ConnectionStatus.ToString(); } } 26 if (Parent == null) {
84 public string Speed { get { return NodeConnectionInfo.Speed.ToString(); } } 27 HasNodeConnectionInfo = true;
85 public Byte CurrentConfigurationValue { get { return NodeConnectionInfo.CurrentConfigurationValue; } } 28 return;
86 public UInt16 DeviceAddress { get { return NodeConnectionInfo.DeviceAddress; } } 29 }
87 public UInt32 NumberOfOpenPipes { get { return NodeConnectionInfo.NumberOfOpenPipes; } } 30 using (SafeFileHandle handle = Parent.OpenHandle()) NodeConnectionInfo = GetNodeConnectionInformation(handle, AdapterNumber);
31 HasNodeConnectionInfo = true;
32 }
33 internal void SetNodeConnectionInfo(USB_NODE_CONNECTION_INFORMATION_EX nci) {
34 NodeConnectionInfo = nci;
35 HasNodeConnectionInfo = true;
36 }
88 37
89 SafeFileHandle OpenHandle() { 38 public UsbDeviceDescriptor DeviceDescriptor { get { GetNodeConnectionInfo(); return NodeConnectionInfo.DeviceDescriptor; } }
90 return OpenHandle(DevicePath); 39
91 } 40 public bool IsHub { get { GetNodeConnectionInfo(); return NodeConnectionInfo.DeviceIsHub != 0; } }
41 public bool IsConnected { get { GetNodeConnectionInfo(); return NodeConnectionInfo.ConnectionStatus == USB_CONNECTION_STATUS.DeviceConnected; } }
42 public string Status { get { GetNodeConnectionInfo(); return NodeConnectionInfo.ConnectionStatus.ToString(); } }
43 public string Speed { get { GetNodeConnectionInfo(); return NodeConnectionInfo.Speed.ToString(); } }
44 public Byte CurrentConfigurationValue { get { GetNodeConnectionInfo(); return NodeConnectionInfo.CurrentConfigurationValue; } }
45 public UInt16 DeviceAddress { get { GetNodeConnectionInfo(); return NodeConnectionInfo.DeviceAddress; } }
46 public UInt32 NumberOfOpenPipes { get { GetNodeConnectionInfo(); return NodeConnectionInfo.NumberOfOpenPipes; } }
92 47
93 public int NumConfigurations { get { return DeviceDescriptor.NumConfigurations; } } 48 public int NumConfigurations { get { return DeviceDescriptor.NumConfigurations; } }
94 public int VendorID { get { return DeviceDescriptor.VendorID; } } 49 public int VendorID { get { return DeviceDescriptor.VendorID; } }
95 public int ProductID { get { return DeviceDescriptor.ProductID; } } 50 public int ProductID { get { return DeviceDescriptor.ProductID; } }
96 51
97 private String GetStringSafe(Byte id) { 52 private String GetStringSafe(Byte id) {
98 if (id == 0) return null; 53 if (id == 0) return null;
99 String s = GetStringDescriptor(id); 54 String s = GetString(id, 0);
100 if (s == null) return s; 55 if (s == null) return s;
101 return s.Trim(' ', '\0'); 56 return s.Trim(' ', '\0');
102 } 57 }
103 58
104 public string Manufacturer { get { return GetStringSafe(DeviceDescriptor.ManufacturerStringID); } } 59 public string Manufacturer { get { return GetStringSafe(DeviceDescriptor.ManufacturerStringID); } }
105 public string Product { get { return GetStringSafe(DeviceDescriptor.ProductStringID); } } 60 public string Product { get { return GetStringSafe(DeviceDescriptor.ProductStringID); } }
106 public string SerialNumber { get { return GetStringSafe(DeviceDescriptor.SerialNumberStringID); } } 61 public string SerialNumber { get { return GetStringSafe(DeviceDescriptor.SerialNumberStringID); } }
107 public virtual string DriverKey { get { using (SafeFileHandle handle = OpenHandle(DevicePath)) return UsbHub.GetNodeConnectionDriverKey(handle, AdapterNumber); } } 62 public String DriverKey {
63 get {
64 if (mParent != null) {
65 using (SafeFileHandle handle = mParent.OpenHandle()) {
66 USB_NODE_CONNECTION_DRIVERKEY_NAME DriverKeyStruct = new USB_NODE_CONNECTION_DRIVERKEY_NAME();
67 int nBytes = Marshal.SizeOf(DriverKeyStruct);
68 DriverKeyStruct.ConnectionIndex = AdapterNumber;
69 if (!Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, ref DriverKeyStruct, nBytes, out DriverKeyStruct, nBytes, out nBytes, IntPtr.Zero))
70 return null;
71 return DriverKeyStruct.DriverKeyName;
72 }
73 }
74 if (mDeviceNode != null) return mDeviceNode.DriverKey;
75 return null;
76 }
77 }
108 78
109 public virtual string DeviceDescription { get { return DeviceNode == null ? null : DeviceNode.DeviceDescription; } } 79 public virtual string DeviceDescription { get { return DeviceNode == null ? null : DeviceNode.DeviceDescription; } }
110 public string DeviceID { get { return DeviceNode == null ? null : DeviceNode.DeviceID; } } 80 public string DeviceID { get { return DeviceNode == null ? null : DeviceNode.DeviceID; } }
111 81
112 private DeviceNode mDeviceNode; 82 protected DeviceNode mDeviceNode = null;
113 public DeviceNode DeviceNode { 83 public DeviceNode DeviceNode {
114 get { 84 get {
115 String dk = DriverKey; 85 String dk = DriverKey;
116 if (mDeviceNode == null && dk != null) { 86 if (mDeviceNode == null && dk != null) {
117 foreach (DeviceNode node in DeviceNode.GetDevices("USB")) { 87 foreach (DeviceNode node in DeviceNode.GetDevices("USB")) {
122 } 92 }
123 } 93 }
124 return mDeviceNode; 94 return mDeviceNode;
125 } 95 }
126 } 96 }
97 protected UsbHub mParent = null;
98 private UInt32 mAdapterNumber = 0;
99 private UsbHub GetParent() {
100 if (mParent == null && mDeviceNode != null) {
101 mParent = UsbHub.GetHubForDeviceNode(mDeviceNode.GetParent());
102 if (mParent != null) {
103 UsbDevice self = mParent.FindChildForDeviceNode(mDeviceNode);
104 if (self != null) mAdapterNumber = self.AdapterNumber;
105 }
106 }
107 return mParent;
108 }
109 public UsbHub Parent { get { return GetParent(); } }
110 public UInt32 AdapterNumber { get { GetParent(); return mAdapterNumber; } }
127 111
128 internal UsbDevice(UsbDevice parent, USB_NODE_CONNECTION_INFORMATION_EX nci, uint port, string devicePath) { 112 internal UsbDevice(DeviceNode devnode, UsbHub parent, uint port) {
129 this.Parent = parent; 113 this.mDeviceNode = devnode;
130 this.NodeConnectionInfo = nci; 114 this.mParent = parent;
131 this.DevicePath = devicePath; 115 this.mAdapterNumber = port;
132 this.AdapterNumber = port;
133 if (devicePath == null) return;
134 } 116 }
135 117
136 private String GetStringDescriptor(Byte index) { 118 public static UsbDevice GetUsbDevice(DeviceNode node) {
137 return UsbStringDescriptor.GetStringFromDevice(this, index, 0); //0x409 119 if (node == null) return null;
120 //UsbController controller = UsbController.GetControllerForDeviceNode(node);
121 //if (controller != null) return controller;
122 UsbHub hub = UsbHub.GetHubForDeviceNode(node);
123 if (hub != null) return hub;
124 DeviceNode parent = node.GetParent();
125 if (parent == null) return null;
126 if (parent.Service == "usbccgp") return GetUsbDevice(parent);
127 hub = UsbHub.GetHubForDeviceNode(parent);
128 if (hub == null) return null;
129 return hub.FindChildForDeviceNode(node);
138 } 130 }
139 131
140 static UsbDevice GetUsbDevice(DeviceNode node, out Boolean isHostController) { 132 #region IUsbInterface and IUsbDevice Members
141 UsbController controller = UsbController.GetControllerForDeviceNode(node); 133 public int GetDescriptor(byte descriptorType, byte index, short langId, byte[] buffer, int offset, int length) {
142 if (controller != null) { 134 using (SafeFileHandle handle = Parent.OpenHandle()) {
143 isHostController = true; 135 int szRequest = Marshal.SizeOf(typeof(USB_DESCRIPTOR_REQUEST));
144 return controller.RootHub; 136 USB_DESCRIPTOR_REQUEST request = new USB_DESCRIPTOR_REQUEST();
137 request.ConnectionIndex = AdapterNumber;
138 request.SetupPacket.Value = (short)((descriptorType << 8) + index);
139 request.SetupPacket.Index = (short)langId;
140 request.SetupPacket.Length = (short)length;
141 int nBytes = length + szRequest;
142 Byte[] bigbuffer = new Byte[nBytes];
143 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)) {
144 int err = Marshal.GetLastWin32Error();
145 if (err != 2 && err != 31 && err != 87) throw new Win32Exception(err);
146 return 0;
147 }
148 nBytes -= szRequest;
149 if (nBytes > length) nBytes = length;
150 if (nBytes < 0) return 0;
151 if (nBytes > 0) Buffer.BlockCopy(bigbuffer, szRequest, buffer, offset, nBytes);
152 return nBytes;
145 } 153 }
146 isHostController = false;
147 DeviceNode parent = node.GetParent();
148 if (parent == null) return null;
149 Boolean isHostControllerA;
150 UsbDevice usbdev = GetUsbDevice(parent, out isHostControllerA);
151 if (isHostControllerA) return usbdev;
152 UsbHub usbhub = usbdev as UsbHub;
153 if (usbhub == null) {
154 if (parent.Service == "usbccgp") return usbdev;
155 return null;
156 }
157 String driverkey = node.DriverKey;
158 if (driverkey == null) return null;
159 foreach (UsbDevice child in usbhub.Devices) {
160 if (driverkey.Equals(child.DriverKey, StringComparison.InvariantCultureIgnoreCase)) return child;
161 }
162 return null;
163 } 154 }
164 public static UsbDevice GetUsbDevice(DeviceNode node) { 155 public String GetString(short langId, byte stringIndex) {
165 Boolean isHostController; 156 return UsbStringDescriptor.GetStringFromDevice(this, stringIndex, langId);
166 return GetUsbDevice(node, out isHostController);
167 } 157 }
168
169 #region IUsbInterface Members
170 byte IUsbInterface.Configuration { get { throw new NotImplementedException(); } } 158 byte IUsbInterface.Configuration { get { throw new NotImplementedException(); } }
171 void IUsbInterface.Close() { } 159 void IUsbInterface.Close() { }
172 public virtual int GetDescriptor(byte descriptorType, byte index, short langId, byte[] buffer, int offset, int length) {
173 using (SafeFileHandle handle = UsbHub.OpenHandle(DevicePath)) return UsbHub.GetDescriptor(handle, AdapterNumber, descriptorType, index, langId, buffer, offset, length);
174 }
175 string IUsbInterface.GetString(short langId, byte stringIndex) {
176 return UsbStringDescriptor.GetStringFromDevice(this, stringIndex, langId);
177 }
178 int IUsbInterface.BulkWrite(byte endpoint, byte[] buffer, int offset, int length) { throw new NotImplementedException(); } 160 int IUsbInterface.BulkWrite(byte endpoint, byte[] buffer, int offset, int length) { throw new NotImplementedException(); }
179 int IUsbInterface.BulkRead(byte endpoint, byte[] buffer, int offset, int length) { throw new NotImplementedException(); } 161 int IUsbInterface.BulkRead(byte endpoint, byte[] buffer, int offset, int length) { throw new NotImplementedException(); }
180 void IUsbInterface.BulkReset(byte endpoint) { throw new NotImplementedException(); } 162 void IUsbInterface.BulkReset(byte endpoint) { throw new NotImplementedException(); }
181 int IUsbInterface.InterruptWrite(byte endpoint, byte[] buffer, int offset, int length) { throw new NotImplementedException(); } 163 int IUsbInterface.InterruptWrite(byte endpoint, byte[] buffer, int offset, int length) { throw new NotImplementedException(); }
182 int IUsbInterface.InterruptRead(byte endpoint, byte[] buffer, int offset, int length) { throw new NotImplementedException(); } 164 int IUsbInterface.InterruptRead(byte endpoint, byte[] buffer, int offset, int length) { throw new NotImplementedException(); }
184 int IUsbInterface.ControlWrite(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) { throw new NotImplementedException(); } 166 int IUsbInterface.ControlWrite(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) { throw new NotImplementedException(); }
185 int IUsbInterface.ControlRead(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) { throw new NotImplementedException(); } 167 int IUsbInterface.ControlRead(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) { throw new NotImplementedException(); }
186 UsbPipeStream IUsbInterface.GetBulkStream(byte endpoint) { throw new NotImplementedException(); } 168 UsbPipeStream IUsbInterface.GetBulkStream(byte endpoint) { throw new NotImplementedException(); }
187 UsbPipeStream IUsbInterface.GetInterruptStream(byte endpoint) { throw new NotImplementedException(); } 169 UsbPipeStream IUsbInterface.GetInterruptStream(byte endpoint) { throw new NotImplementedException(); }
188 void IDisposable.Dispose() { } 170 void IDisposable.Dispose() { }
189 #endregion
190 #region IUsbDevice Members
191 byte IUsbDevice.Configuration { get { throw new NotSupportedException(); } set { throw new NotSupportedException(); } } 171 byte IUsbDevice.Configuration { get { throw new NotSupportedException(); } set { throw new NotSupportedException(); } }
192 void IUsbDevice.ClaimInterface(int interfaceID) { } 172 void IUsbDevice.ClaimInterface(int interfaceID) { }
193 void IUsbDevice.ReleaseInterface(int interfaceID) { } 173 void IUsbDevice.ReleaseInterface(int interfaceID) { }
194 void IUsbDevice.ResetDevice() { throw new NotSupportedException(); } 174 void IUsbDevice.ResetDevice() { throw new NotSupportedException(); }
195 IUsbDeviceRegistry IUsbDevice.Registry { get { throw new NotImplementedException(); } } 175 IUsbDeviceRegistry IUsbDevice.Registry { get { throw new NotImplementedException(); } }