21
|
1 ???using System; |
|
2 using System.Runtime.InteropServices; |
|
3 |
|
4 namespace UCIS.USBLib.Communication.LibUsb { |
|
5 /// <summary> Transfers data to the main control endpoint (Endpoint 0). |
|
6 /// </summary> |
|
7 /// <remarks> All USB devices respond to requests from the host on the device???s Default Control Pipe. These requests are made using control transfers. The request and the request???s parameters are sent to the device in the Setup packet. The host is responsible for establishing the values passed in the fields. Every Setup packet has eight bytes. |
|
8 /// </remarks> |
|
9 [StructLayout(LayoutKind.Sequential, Pack = 1)] |
|
10 struct UsbSetupPacket { |
|
11 /// <summary> |
|
12 /// This bitmapped field identifies the characteristics of the specific request. In particular, this field identifies the direction of data transfer in the second phase of the control transfer. The state of the Direction bit is ignored if the wLength field is zero, signifying there is no Data stage. |
|
13 /// The USB Specification defines a series of standard requests that all devices must support. In addition, a device class may define additional requests. A device vendor may also define requests supported by the device. |
|
14 /// Requests may be directed to the device, an interface on the device, or a specific endpoint on a device. This field also specifies the intended recipient of the request. When an interface or endpoint is specified, the wIndex field identifies the interface or endpoint. |
|
15 /// </summary> |
|
16 /// <remarks> |
|
17 /// <ul>Characteristics of request: |
|
18 /// <li>D7: Data transfer direction</li> |
|
19 /// <li>0 = Host-to-device</li> |
|
20 /// <li>1 = Device-to-host</li> |
|
21 /// <li>D6...5: Type</li> |
|
22 /// <li>0 = Standard</li> |
|
23 /// <li>1 = Class</li> |
|
24 /// <li>2 = Vendor</li> |
|
25 /// <li>3 = Reserved</li> |
|
26 /// <li>D4...0: Recipient</li> |
|
27 /// <li>0 = Device</li> |
|
28 /// <li>1 = Interface</li> |
|
29 /// <li>2 = Endpoint</li> |
|
30 /// <li>3 = Other</li> |
|
31 /// <li>4...31 = Reserved</li> |
|
32 /// </ul> |
|
33 /// </remarks> |
|
34 public byte RequestType; |
|
35 |
|
36 /// <summary> |
|
37 /// This field specifies the particular request. The Type bits in the bmRequestType field modify the meaning of this field. This specification defines values for the bRequest field only when the bits are reset to zero, indicating a standard request. |
|
38 /// </summary> |
|
39 public byte Request; |
|
40 |
|
41 /// <summary> |
|
42 /// The contents of this field vary according to the request. It is used to pass a parameter to the device, specific to the request. |
|
43 /// </summary> |
|
44 public short Value; |
|
45 |
|
46 /// <summary> |
|
47 /// The contents of this field vary according to the request. It is used to pass a parameter to the device, specific to the request. |
|
48 /// </summary> |
|
49 public short Index; |
|
50 |
|
51 /// <summary> |
|
52 /// This field specifies the length of the data transferred during the second phase of the control transfer. The direction of data transfer (host-to-device or device-to-host) is indicated by the Direction bit of the <see cref="RequestType"/> field. If this field is zero, there is no data transfer phase. On an input request, a device must never return more data than is indicated by the wLength value; it may return less. On an output request, wLength will always indicate the exact amount of data to be sent by the host. Device behavior is undefined if the host should send more data than is specified in wLength. |
|
53 /// </summary> |
|
54 public short Length; |
|
55 |
|
56 /// <summary> |
|
57 /// Creates a new instance of a <see cref="UsbSetupPacket"/> and initializes all the fields with the following parameters. |
|
58 /// </summary> |
|
59 /// <param name="requestType">See <see cref="UsbSetupPacket.RequestType"/>.</param> |
|
60 /// <param name="request">See <see cref="UsbSetupPacket.Request"/>.</param> |
|
61 /// <param name="value">See <see cref="UsbSetupPacket.Value"/>.</param> |
|
62 /// <param name="index">See <see cref="UsbSetupPacket.Index"/>.</param> |
|
63 /// <param name="length">See <see cref="UsbSetupPacket.Length"/>.</param> |
|
64 public UsbSetupPacket(byte requestType, byte request, short value, short index, short length) { |
|
65 RequestType = requestType; |
|
66 Request = request; |
|
67 Value = value; |
|
68 Index = index; |
|
69 Length = length; |
|
70 } |
|
71 } |
|
72 /// <summary> Standard Windows registry properties for USB devices and other hardware. |
|
73 /// </summary> |
|
74 /// DeviceRegistryProperty or DEVICE_REGISTRY_PROPERTY on MSDN |
|
75 enum DevicePropertyType { |
|
76 /// <summary> |
|
77 /// Requests a string describing the device, such as "Microsoft PS/2 Port Mouse", typically defined by the manufacturer. |
|
78 /// </summary> |
|
79 DeviceDesc = 0, |
|
80 /// <summary> |
|
81 /// Requests the hardware IDs provided by the device that identify the device. |
|
82 /// </summary> |
|
83 HardwareId = 1, |
|
84 /// <summary> |
|
85 /// Requests the compatible IDs reported by the device. |
|
86 /// </summary> |
|
87 CompatibleIds = 2, |
|
88 /// <summary> |
|
89 /// Requests the name of the device's setup class, in text format. |
|
90 /// </summary> |
|
91 Class = 5, |
|
92 /// <summary> |
|
93 /// Requests the GUID for the device's setup class. |
|
94 /// </summary> |
|
95 ClassGuid = 6, |
|
96 /// <summary> |
|
97 /// Requests the name of the driver-specific registry key. |
|
98 /// </summary> |
|
99 Driver = 7, |
|
100 /// <summary> |
|
101 /// Requests a string identifying the manufacturer of the device. |
|
102 /// </summary> |
|
103 Mfg = 8, |
|
104 /// <summary> |
|
105 /// Requests a string that can be used to distinguish between two similar devices, typically defined by the class installer. |
|
106 /// </summary> |
|
107 FriendlyName = 9, |
|
108 /// <summary> |
|
109 /// Requests information about the device's location on the bus; the interpretation of this information is bus-specific. |
|
110 /// </summary> |
|
111 LocationInformation = 10, |
|
112 /// <summary> |
|
113 /// Requests the name of the PDO for this device. |
|
114 /// </summary> |
|
115 PhysicalDeviceObjectName = 11, |
|
116 /// <summary> |
|
117 /// Requests the GUID for the bus that the device is connected to. |
|
118 /// </summary> |
|
119 BusTypeGuid = 12, |
|
120 /// <summary> |
|
121 /// Requests the bus type, such as PCIBus or PCMCIABus. |
|
122 /// </summary> |
|
123 LegacyBusType = 13, |
|
124 /// <summary> |
|
125 /// Requests the legacy bus number of the bus the device is connected to. |
|
126 /// </summary> |
|
127 BusNumber = 14, |
|
128 /// <summary> |
|
129 /// Requests the name of the enumerator for the device, such as "USB". |
|
130 /// </summary> |
|
131 EnumeratorName = 15, |
|
132 /// <summary> |
|
133 /// Requests the address of the device on the bus. |
|
134 /// </summary> |
|
135 Address = 16, |
|
136 /// <summary> |
|
137 /// Requests a number associated with the device that can be displayed in the user interface. |
|
138 /// </summary> |
|
139 UiNumber = 17, |
|
140 /// <summary> |
|
141 /// Windows XP and later.) Requests the device's installation state. |
|
142 /// </summary> |
|
143 InstallState = 18, |
|
144 /// <summary> |
|
145 /// (Windows XP and later.) Requests the device's current removal policy. The operating system uses this value as a hint to determine how the device is normally removed. |
|
146 /// </summary> |
|
147 RemovalPolicy = 19 |
|
148 } |
|
149 /// <summary> Various USB constants. |
|
150 /// </summary> |
|
151 static class UsbConstants { |
|
152 /// <summary> |
|
153 /// Default timeout for all USB IO operations. |
|
154 /// </summary> |
|
155 public const int DEFAULT_TIMEOUT = 1000; |
|
156 |
|
157 /// <summary> |
|
158 /// Maximum size of a config descriptor. |
|
159 /// </summary> |
|
160 public const int MAX_CONFIG_SIZE = 4096; |
|
161 |
|
162 /// <summary> |
|
163 /// Maximum number of USB devices. |
|
164 /// </summary> |
|
165 public const int MAX_DEVICES = 128; |
|
166 |
|
167 /// <summary> |
|
168 /// Maximum number of endpoints per device. |
|
169 /// </summary> |
|
170 public const int MAX_ENDPOINTS = 32; |
|
171 |
|
172 /// <summary> |
|
173 /// Endpoint direction mask. |
|
174 /// </summary> |
|
175 public const byte ENDPOINT_DIR_MASK = 0x80; |
|
176 |
|
177 /// <summary> |
|
178 /// Endpoint number mask. |
|
179 /// </summary> |
|
180 public const byte ENDPOINT_NUMBER_MASK = 0xf; |
|
181 |
|
182 } |
|
183 ///<summary>Endpoint direction.</summary> |
|
184 /// <seealso cref="UsbCtrlFlags"/> |
|
185 [Flags] |
|
186 enum UsbEndpointDirection : byte { |
|
187 /// <summary> |
|
188 /// In Direction |
|
189 /// </summary> |
|
190 EndpointIn = 0x80, |
|
191 /// <summary> |
|
192 /// Out Direction |
|
193 /// </summary> |
|
194 EndpointOut = 0x00, |
|
195 } |
|
196 ///<summary> |
|
197 /// Contains version information for the LibUsb Sys driver. |
|
198 ///</summary> |
|
199 /// <remarks> |
|
200 /// This version is not related to LibUsbDotNet. TO get the LibUsbDotNet version use .NET reflections. |
|
201 /// </remarks> |
|
202 [StructLayout(LayoutKind.Sequential, Pack = 1)] |
|
203 struct UsbKernelVersion { |
|
204 /// <summary> |
|
205 /// True if Major == 0 and Minor == 0 and Micro == 0 and Nano == 0. |
|
206 /// </summary> |
|
207 public bool IsEmpty { |
|
208 get { |
|
209 if (Major == 0 && Minor == 0 && Micro == 0 && Nano == 0) return true; |
|
210 return false; |
|
211 } |
|
212 } |
|
213 |
|
214 internal UsbKernelVersion(int major, int minor, int micro, int nano, int bcdLibUsbDotNetKernelMod) { |
|
215 Major = major; |
|
216 Minor = minor; |
|
217 Micro = micro; |
|
218 Nano = nano; |
|
219 BcdLibUsbDotNetKernelMod = bcdLibUsbDotNetKernelMod; |
|
220 } |
|
221 |
|
222 /// <summary> |
|
223 /// LibUsb-Win32 Major version |
|
224 /// </summary> |
|
225 public readonly int Major; |
|
226 |
|
227 /// <summary> |
|
228 /// LibUsb-Win32 Minor version |
|
229 /// </summary> |
|
230 public readonly int Minor; |
|
231 |
|
232 /// <summary> |
|
233 /// LibUsb-Win32 Micro version |
|
234 /// </summary> |
|
235 public readonly int Micro; |
|
236 |
|
237 /// <summary> |
|
238 /// LibUsb-Win32 Nano version |
|
239 /// </summary> |
|
240 public readonly int Nano; |
|
241 |
|
242 /// <summary> |
|
243 /// The LibUsbDotNet - LibUsb-Win32 binary mod code. if not running the LibUsbDotNet LibUsb-Win32 modified kernel driver, this value is 0. |
|
244 /// </summary> |
|
245 public readonly int BcdLibUsbDotNetKernelMod; |
|
246 |
|
247 ///<summary> |
|
248 ///The full LibUsb-Win32 kernel driver version (libusb0.sys). |
|
249 ///</summary> |
|
250 /// |
|
251 ///<returns> |
|
252 ///A <see cref="System.String"/> containing the full LibUsb-Win32 version. |
|
253 ///</returns> |
|
254 public override string ToString() { return string.Format("{0}.{1}.{2}.{3}", Major, Minor, Micro, Nano); } |
|
255 } |
|
256 [StructLayout(LayoutKind.Explicit, Pack = 1, Size = sizeof(int) * 6)] |
|
257 struct LibUsbRequest { |
|
258 public static int Size = Marshal.SizeOf(typeof(LibUsbRequest)); |
|
259 [FieldOffset(0)] |
|
260 public int Timeout; // = UsbConstants.DEFAULT_TIMEOUT; |
|
261 |
|
262 #region Union Struct |
|
263 |
|
264 [FieldOffset(sizeof(int))] |
|
265 public Control Control; |
|
266 |
|
267 [FieldOffset(sizeof(int))] |
|
268 public Config Config; |
|
269 |
|
270 [FieldOffset(sizeof(int))] |
|
271 public Debug Debug; |
|
272 |
|
273 [FieldOffset(sizeof(int))] |
|
274 public Descriptor Descriptor; |
|
275 |
|
276 [FieldOffset(sizeof(int))] |
|
277 public Endpoint Endpoint; |
|
278 |
|
279 [FieldOffset(sizeof(int))] |
|
280 public Feature Feature; |
|
281 |
|
282 [FieldOffset(sizeof(int))] |
|
283 public Iface Iface; |
|
284 |
|
285 [FieldOffset(sizeof(int))] |
|
286 public Status Status; |
|
287 |
|
288 [FieldOffset(sizeof(int))] |
|
289 public Vendor Vendor; |
|
290 |
|
291 [FieldOffset(sizeof(int))] |
|
292 public UsbKernelVersion Version; |
|
293 |
|
294 [FieldOffset(sizeof(int))] |
|
295 public DeviceProperty DeviceProperty; |
|
296 |
|
297 [FieldOffset(sizeof(int))] |
|
298 public DeviceRegKey DeviceRegKey; |
|
299 |
|
300 [FieldOffset(sizeof(int))] |
|
301 public BusQueryID BusQueryID; |
|
302 #endregion |
|
303 |
|
304 public Byte[] Bytes { |
|
305 get { |
|
306 Byte[] rtn = new byte[Size]; |
|
307 |
|
308 for (int i = 0; i < Size; i++) |
|
309 rtn[i] = Marshal.ReadByte(this, i); |
|
310 |
|
311 return rtn; |
|
312 } |
|
313 } |
|
314 |
|
315 |
|
316 public void RequestConfigDescriptor(int index) { |
|
317 Timeout = UsbConstants.DEFAULT_TIMEOUT; |
|
318 |
|
319 int value = ((int)UsbDescriptorType.Configuration << 8) + index; |
|
320 |
|
321 Descriptor.Recipient = (byte)UsbEndpointDirection.EndpointIn & 0x1F; |
|
322 Descriptor.Type = (value >> 8) & 0xFF; |
|
323 Descriptor.Index = value & 0xFF; |
|
324 Descriptor.LangID = 0; |
|
325 } |
|
326 |
|
327 public void RequestStringDescriptor(int index, short langid) { |
|
328 Timeout = UsbConstants.DEFAULT_TIMEOUT; |
|
329 |
|
330 int value = ((int)UsbDescriptorType.String << 8) + index; |
|
331 |
|
332 Descriptor.Recipient = (byte)UsbEndpointDirection.EndpointIn & 0x1F; |
|
333 Descriptor.Type = value >> 8 & 0xFF; |
|
334 Descriptor.Index = value & 0xFF; |
|
335 Descriptor.LangID = langid; |
|
336 } |
|
337 } |
|
338 [StructLayout(LayoutKind.Sequential, Pack = 1)] |
|
339 struct Descriptor { |
|
340 public int Type; |
|
341 public int Index; |
|
342 public int LangID; |
|
343 public int Recipient; |
|
344 } |
|
345 [StructLayout(LayoutKind.Sequential, Pack = 1)] |
|
346 struct Config { |
|
347 public int ID; |
|
348 } |
|
349 [StructLayout(LayoutKind.Sequential, Pack = 1)] |
|
350 struct Control { |
|
351 public byte RequestType; |
|
352 public byte Request; |
|
353 public ushort Value; |
|
354 public ushort Index; |
|
355 public ushort Length; |
|
356 } |
|
357 [StructLayout(LayoutKind.Sequential, Pack = 1)] |
|
358 struct DeviceProperty { |
|
359 public int ID; |
|
360 } |
|
361 [StructLayout(LayoutKind.Sequential, Pack = 1)] |
|
362 struct Iface { |
|
363 public int ID; |
|
364 public int AlternateID; |
|
365 } |
|
366 [StructLayout(LayoutKind.Sequential, Pack = 1)] |
|
367 struct Endpoint { |
|
368 public int ID; |
|
369 public int PacketSize; |
|
370 } |
|
371 [StructLayout(LayoutKind.Sequential, Pack = 1)] |
|
372 struct Vendor { |
|
373 public int Type; |
|
374 public int Recipient; |
|
375 public int Request; |
|
376 public int ID; |
|
377 public int Index; |
|
378 } |
|
379 [StructLayout(LayoutKind.Sequential, Pack = 1)] |
|
380 struct Feature { |
|
381 public int Recipient; |
|
382 public int ID; |
|
383 public int Index; |
|
384 } |
|
385 [StructLayout(LayoutKind.Sequential, Pack = 1)] |
|
386 struct Status { |
|
387 public int Recipient; |
|
388 public int Index; |
|
389 public int ID; |
|
390 } |
|
391 [StructLayout(LayoutKind.Sequential, Pack = 1)] |
|
392 struct Debug { |
|
393 public int Level; |
|
394 } |
|
395 [StructLayout(LayoutKind.Sequential, Pack = 1)] |
|
396 struct DeviceRegKey { |
|
397 public int KeyType; |
|
398 public int NameOffset; |
|
399 public int ValueOffset; |
|
400 public int ValueLength; |
|
401 } |
|
402 [StructLayout(LayoutKind.Sequential, Pack = 1)] |
|
403 struct BusQueryID { |
|
404 public ushort IDType; |
|
405 } |
|
406 static class LibUsbIoCtl { |
|
407 private const int FILE_ANY_ACCESS = 0; |
|
408 private const int FILE_DEVICE_UNKNOWN = 0x00000022; |
|
409 |
|
410 private const int METHOD_BUFFERED = 0; |
|
411 private const int METHOD_IN_DIRECT = 1; |
|
412 private const int METHOD_OUT_DIRECT = 2; |
|
413 private const int METHOD_NEITHER = 3; |
|
414 |
|
415 public static readonly int ABORT_ENDPOINT = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80F, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
416 public static readonly int CLAIM_INTERFACE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x815, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
417 public static readonly int CLEAR_FEATURE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
418 public static readonly int CONTROL_TRANSFER = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x903, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
419 |
|
420 public static readonly int GET_CONFIGURATION = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
421 public static readonly int GET_CUSTOM_REG_PROPERTY = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
422 public static readonly int GET_DESCRIPTOR = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x809, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
423 public static readonly int GET_INTERFACE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
424 public static readonly int GET_STATUS = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x807, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
425 public static readonly int GET_VERSION = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x812, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
426 public static readonly int GET_REG_PROPERTY = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
427 public static readonly int INTERRUPT_OR_BULK_READ = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80B, METHOD_OUT_DIRECT, FILE_ANY_ACCESS); |
|
428 public static readonly int INTERRUPT_OR_BULK_WRITE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80A, METHOD_IN_DIRECT, FILE_ANY_ACCESS); |
|
429 public static readonly int ISOCHRONOUS_READ = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x814, METHOD_OUT_DIRECT, FILE_ANY_ACCESS); |
|
430 public static readonly int ISOCHRONOUS_WRITE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x813, METHOD_IN_DIRECT, FILE_ANY_ACCESS); |
|
431 public static readonly int RELEASE_INTERFACE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x816, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
432 public static readonly int RESET_DEVICE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x810, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
433 public static readonly int RESET_ENDPOINT = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80E, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
434 public static readonly int SET_CONFIGURATION = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
435 public static readonly int SET_DEBUG_LEVEL = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x811, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
436 public static readonly int SET_DESCRIPTOR = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x808, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
437 public static readonly int SET_FEATURE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
438 public static readonly int SET_INTERFACE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
439 public static readonly int VENDOR_READ = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80D, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
440 public static readonly int VENDOR_WRITE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80C, METHOD_BUFFERED, FILE_ANY_ACCESS); |
|
441 |
|
442 private static int CTL_CODE(int DeviceType, int Function, int Method, int Access) { return ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method); } |
|
443 } |
|
444 } |