Mercurial > hg > ucis.core
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(); } } |