comparison USBLib/Communication/LibUsbDotNet.cs @ 21:dcfec2be27c9

Added USBLib
author Ivo Smits <Ivo@UCIS.nl>
date Mon, 15 Apr 2013 01:04:59 +0200
parents
children 5b14fed54a89
comparison
equal deleted inserted replaced
20:c873e3dd73fe 21:dcfec2be27c9
1 using System;
2 using System.Collections.ObjectModel;
3 using System.Collections.Generic;
4 using System.Runtime.InteropServices;
5 using System.Threading;
6 using System.Text;
7 using System.IO;
8 using LibUsbDotNet.Main;
9 using LibUsbDotNet.Info;
10 using LibUsbDotNet.Descriptors;
11 using UCIS.USBLib.Communication;
12 using LibUsb0Registry = UCIS.USBLib.Communication.LibUsb.LibUsb0Registry;
13 using LibUsb1Registry = UCIS.USBLib.Communication.LibUsb1.LibUsb1Registry;
14 using nIUsbDevice = UCIS.USBLib.Communication.IUsbDevice;
15 using nIUsbInterface = UCIS.USBLib.Communication.IUsbInterface;
16 using WinUsbRegistry = UCIS.USBLib.Communication.WinUsb.WinUsbRegistry;
17
18 namespace LibUsbDotNet {
19 public class UsbDevice : IUsbDevice {
20 public nIUsbInterface Device { get; private set; }
21 public UsbDevice(nIUsbInterface dev) {
22 Device = dev;
23 }
24 public bool GetDescriptor(byte descriptorType, byte index, short langId, Byte[] buffer, int bufferLength, out int transferLength) {
25 try {
26 transferLength = Device.GetDescriptor(descriptorType, index, langId, buffer, 0, bufferLength);
27 return true;
28 } catch {
29 transferLength = 0;
30 return false;
31 }
32 }
33 public bool ControlTransfer(ref UsbSetupPacket setupPacket, Byte[] buffer, int bufferLength, out int lengthTransferred) {
34 if ((setupPacket.RequestType & 128) != 0) {
35 lengthTransferred = Device.ControlRead((UsbControlRequestType)setupPacket.RequestType, setupPacket.Request, setupPacket.Value, setupPacket.Index, buffer, 0, bufferLength);
36 } else {
37 lengthTransferred = Device.ControlWrite((UsbControlRequestType)setupPacket.RequestType, setupPacket.Request, setupPacket.Value, setupPacket.Index, buffer, 0, bufferLength);
38 }
39 return true;
40 }
41 public DriverModeType DriverMode { get { return DriverModeType.Unknown; } }
42 public enum DriverModeType {
43 Unknown,
44 LibUsb,
45 WinUsb,
46 MonoLibUsb,
47 LibUsbWinBack
48 }
49 public UsbEndpointWriter OpenEndpointWriter(WriteEndpointID writeEndpointID, EndpointType endpointType) {
50 return new UsbEndpointWriter(Device, (Byte)writeEndpointID, endpointType);
51 }
52 public UsbEndpointReader OpenEndpointReader(ReadEndpointID readEndpointID, int buffersize, EndpointType endpointType) {
53 UsbEndpointReader reader = new UsbEndpointReader(Device, (Byte)readEndpointID, endpointType);
54 reader.ReadBufferSize = buffersize;
55 return reader;
56 }
57 public void Close() {
58 Device.Dispose();
59 }
60 public UsbDeviceInfo Info { get { return new UsbDeviceInfo(this); } }
61 public static IList<UsbRegistry> AllDevices {
62 get {
63 List<UsbRegistry> list = new List<UsbRegistry>();
64 if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
65 foreach (IUsbDeviceRegistry reg in WinUsbRegistry.DeviceList) list.Add(new UsbRegistry(reg));
66 foreach (IUsbDeviceRegistry reg in LibUsb0Registry.DeviceList) list.Add(new UsbRegistry(reg));
67 } else {
68 foreach (IUsbDeviceRegistry reg in LibUsb1Registry.DeviceList) list.Add(new UsbRegistry(reg));
69 }
70 return list;
71 }
72 }
73 private SafeHandle Handle { get { return null; } }
74 public bool SetConfiguration(byte config) {
75 nIUsbDevice dev = Device as nIUsbDevice;
76 if (dev == null) return false;
77 try {
78 dev.Configuration = config;
79 return true;
80 } catch {
81 return false;
82 }
83 }
84 public bool ClaimInterface(int interfaceID) {
85 nIUsbDevice dev = Device as nIUsbDevice;
86 if (dev == null) return false;
87 try {
88 dev.ClaimInterface(interfaceID);
89 return true;
90 } catch {
91 return false;
92 }
93 }
94 public bool ReleaseInterface(int interfaceID) {
95 nIUsbDevice dev = Device as nIUsbDevice;
96 if (dev == null) return false;
97 try {
98 dev.ReleaseInterface(interfaceID);
99 return true;
100 } catch {
101 return false;
102 }
103 }
104 public IList<UsbConfigInfo> Configs {
105 get {
106 List<UsbConfigInfo> rtnConfigs = new List<UsbConfigInfo>();
107 byte[] cfgBuffer = new byte[UsbConstants.MAX_CONFIG_SIZE];
108 int iConfigs = Info.Descriptor.ConfigurationCount;
109 for (int iConfig = 0; iConfig < iConfigs; iConfig++) {
110 int iBytesTransmitted;
111 if (!GetDescriptor((byte)UsbDescriptorType.Configuration, 0, 0, cfgBuffer, cfgBuffer.Length, out iBytesTransmitted))
112 throw new Exception("Could not read configuration descriptor");
113 if (iBytesTransmitted < UsbConfigDescriptor.Size || cfgBuffer[1] != (byte)UsbDescriptorType.Configuration)
114 throw new Exception("GetDeviceConfigs: USB config descriptor is invalid.");
115 UsbConfigDescriptor configDescriptor = new UsbConfigDescriptor();
116 Helper.BytesToObject(cfgBuffer, 0, Math.Min(UsbConfigDescriptor.Size, cfgBuffer[0]), configDescriptor);
117 if (configDescriptor.TotalLength != iBytesTransmitted) throw new Exception("GetDeviceConfigs: USB config descriptor length doesn't match the length received.");
118 List<byte[]> rawDescriptorList = new List<byte[]>();
119 int iRawLengthPosition = configDescriptor.Length;
120 while (iRawLengthPosition < configDescriptor.TotalLength) {
121 byte[] rawDescriptor = new byte[cfgBuffer[iRawLengthPosition]];
122 if (iRawLengthPosition + rawDescriptor.Length > iBytesTransmitted) throw new Exception("Descriptor length is out of range.");
123 Array.Copy(cfgBuffer, iRawLengthPosition, rawDescriptor, 0, rawDescriptor.Length);
124 rawDescriptorList.Add(rawDescriptor);
125 iRawLengthPosition += rawDescriptor.Length;
126 }
127 rtnConfigs.Add(new UsbConfigInfo(this, configDescriptor, ref rawDescriptorList));
128 }
129 return rtnConfigs;
130 }
131 }
132 }
133 public interface IUsbDevice {
134 bool SetConfiguration(byte config);
135 bool ClaimInterface(int interfaceID);
136 bool ReleaseInterface(int interfaceID);
137 }
138 public class UsbEndpointWriter : IDisposable {
139 public nIUsbInterface Device { get; private set; }
140 public Byte EndpointID { get; private set; }
141 public EndpointType EndpointType { get; private set; }
142 public Byte EpNum { get { return EndpointID; } }
143 public UsbEndpointWriter(nIUsbInterface dev, byte epid, EndpointType eptype) {
144 Device = dev;
145 EndpointID = epid;
146 EndpointType = eptype;
147 }
148 public ErrorCode Write(byte[] buffer, int offset, int count, int timeout, out int transferLength) {
149 switch (EndpointType) {
150 case EndpointType.Bulk: transferLength = Device.BulkWrite(EndpointID, buffer, offset, count); break;
151 case EndpointType.Interrupt: transferLength = Device.InterruptWrite(EndpointID, buffer, offset, count); break;
152 default: transferLength = 0; return ErrorCode.Error;
153 }
154 return ErrorCode.Ok;
155 }
156 public void Dispose() { }
157 }
158 public class UsbEndpointReader : IDisposable {
159 public nIUsbInterface Device { get; private set; }
160 public Byte EndpointID { get; private set; }
161 public EndpointType EndpointType { get; private set; }
162 public Byte EpNum { get { return EndpointID; } }
163 public int ReadBufferSize { get; set; }
164
165 public UsbEndpointReader(nIUsbInterface dev, byte epid, EndpointType eptype) {
166 Device = dev;
167 EndpointID = epid;
168 EndpointType = eptype;
169 ReadBufferSize = 4096;
170 }
171 public ErrorCode Read(byte[] buffer, int offset, int count, int timeout, out int transferLength) {
172 switch (EndpointType) {
173 case EndpointType.Bulk: transferLength = Device.BulkRead(EndpointID, buffer, offset, count); break;
174 case EndpointType.Interrupt: transferLength = Device.InterruptRead(EndpointID, buffer, offset, count); break;
175 default: transferLength = 0; return ErrorCode.Error;
176 }
177 return ErrorCode.Ok;
178 }
179 public void Dispose() { DataReceivedEnabled = false; }
180
181 private bool mDataReceivedEnabled;
182 private Thread mReadThread;
183
184 public virtual bool DataReceivedEnabled {
185 get { return mDataReceivedEnabled; }
186 set {
187 if (value != mDataReceivedEnabled) {
188 if (mDataReceivedEnabled) {
189 mReadThread.Abort();
190 } else {
191 mDataReceivedEnabled = true;
192 mReadThread = new Thread(ReadDataProcess);
193 mReadThread.Start();
194 }
195 }
196 }
197 }
198
199 private void ReadDataProcess(object state) {
200 byte[] buffer = new byte[ReadBufferSize];
201 try {
202 while (mDataReceivedEnabled) {
203 int transferLength;
204 Read(buffer, 0, buffer.Length, -1, out transferLength);
205 EventHandler<EndpointDataEventArgs> eh = DataReceived;
206 if (!ReferenceEquals(eh, null)) eh(this, new EndpointDataEventArgs(buffer, transferLength));
207 }
208 } catch (Exception ex) {
209 if (ReadError != null) ReadError(this, new ErrorEventArgs(ex));
210 } finally {
211 mDataReceivedEnabled = false;
212 }
213 }
214
215 public event EventHandler<EndpointDataEventArgs> DataReceived;
216 public event ErrorEventHandler ReadError;
217 }
218 }
219 namespace LibUsbDotNet.Main {
220 public static class UsbConstants {
221 public const int MAX_CONFIG_SIZE = 4096;
222 public const int MAX_DEVICES = 128;
223 public const int MAX_ENDPOINTS = 32;
224 public const byte ENDPOINT_DIR_MASK = 0x80;
225 public const byte ENDPOINT_NUMBER_MASK = 0xf;
226 }
227 public static class Helper {
228 public static void BytesToObject(byte[] sourceBytes, int iStartIndex, int iLength, object destObject) {
229 GCHandle gch = GCHandle.Alloc(destObject, GCHandleType.Pinned);
230 IntPtr ptrDestObject = gch.AddrOfPinnedObject();
231 Marshal.Copy(sourceBytes, iStartIndex, ptrDestObject, iLength);
232 gch.Free();
233 }
234 public static string ToString(string sep0, string[] names, string sep1, object[] values, string sep2) {
235 StringBuilder sb = new StringBuilder();
236 for (int i = 0; i < names.Length; i++) sb.Append(sep0 + names[i] + sep1 + values[i] + sep2);
237 return sb.ToString();
238 }
239 }
240 public class EndpointDataEventArgs : EventArgs {
241 internal EndpointDataEventArgs(byte[] bytes, int size) {
242 Buffer = bytes;
243 Count = size;
244 }
245 public byte[] Buffer { get; private set; }
246 public int Count { get; private set; }
247 }
248 [StructLayout(LayoutKind.Sequential, Pack = 1)]
249 public struct UsbSetupPacket {
250 public byte RequestType;
251 public byte Request;
252 public short Value;
253 public short Index;
254 public short Length;
255 public UsbSetupPacket(byte requestType, byte request, short value, short index, short length) {
256 RequestType = requestType;
257 Request = request;
258 Value = value;
259 Index = index;
260 Length = length;
261 }
262 }
263 public enum UsbEndpointDirection : byte {
264 EndpointIn = 0x80,
265 EndpointOut = 0x00,
266 }
267 public enum UsbRequestType : byte {
268 TypeClass = (0x01 << 5),
269 TypeReserved = (0x03 << 5),
270 TypeStandard = (0x00 << 5),
271 TypeVendor = (0x02 << 5),
272 }
273 public enum WriteEndpointID : byte {
274 Ep01 = 0x01,
275 Ep02 = 0x02,
276 Ep03 = 0x03,
277 Ep04 = 0x04,
278 Ep05 = 0x05,
279 Ep06 = 0x06,
280 Ep07 = 0x07,
281 Ep08 = 0x08,
282 Ep09 = 0x09,
283 Ep10 = 0x0A,
284 Ep11 = 0x0B,
285 Ep12 = 0x0C,
286 Ep13 = 0x0D,
287 Ep14 = 0x0E,
288 Ep15 = 0x0F,
289 }
290 public enum ReadEndpointID : byte {
291 Ep01 = 0x81,
292 Ep02 = 0x82,
293 Ep03 = 0x83,
294 Ep04 = 0x84,
295 Ep05 = 0x85,
296 Ep06 = 0x86,
297 Ep07 = 0x87,
298 Ep08 = 0x88,
299 Ep09 = 0x89,
300 Ep10 = 0x8A,
301 Ep11 = 0x8B,
302 Ep12 = 0x8C,
303 Ep13 = 0x8D,
304 Ep14 = 0x8E,
305 Ep15 = 0x8F,
306 }
307 public enum UsbRequestRecipient : byte {
308 RecipDevice = 0x00,
309 RecipInterface = 0x01,
310 RecipEndpoint = 0x02,
311 RecipOther = 0x03,
312 }
313 public enum EndpointType : byte {
314 Control,
315 Isochronous,
316 Bulk,
317 Interrupt
318 }
319 public enum ErrorCode {
320 Ok = 0,
321 Error = 1,
322 }
323 public class UsbRegistry {
324 public IUsbDeviceRegistry Registry { get; private set; }
325 public UsbRegistry(IUsbDeviceRegistry reg) {
326 Registry = reg;
327 }
328 public int Vid { get { return Registry.Vid; } }
329 public int Pid { get { return Registry.Pid; } }
330 public int Rev { get { return 0; } }
331 public Boolean IsAlive { get { return true; } }
332 public Boolean Open(out UsbDevice hand) {
333 hand = new UsbDevice(Registry.Open());
334 return true;
335 }
336 public IDictionary<String, Object> DeviceProperties { get { return Registry.DeviceProperties; } }
337 public String FullName { get { return Registry.FullName; } }
338 public String Name { get { return Registry.Name; } }
339 public String SymbolicName { get { return Registry.SymbolicName; } }
340 }
341 }
342 namespace LibUsbDotNet.Info {
343 public class UsbDeviceInfo {
344 private readonly UsbDeviceDescriptor mDeviceDescriptor;
345 internal UsbDevice mUsbDevice;
346 internal UsbDeviceInfo(UsbDevice usbDevice) {
347 mUsbDevice = usbDevice;
348 mDeviceDescriptor = new UsbDeviceDescriptor();
349 Byte[] bytes = new Byte[UsbDeviceDescriptor.Size];
350 int ret;
351 usbDevice.GetDescriptor((byte)UsbDescriptorType.Device, 0, 0, bytes, UsbDeviceDescriptor.Size, out ret);
352 Object asobj = mDeviceDescriptor;
353 Helper.BytesToObject(bytes, 0, ret, asobj);
354 mDeviceDescriptor = (UsbDeviceDescriptor)asobj;
355 }
356 public UsbDeviceDescriptor Descriptor { get { return mDeviceDescriptor; } }
357 public String ManufacturerString {
358 get {
359 if (Descriptor.ManufacturerStringIndex == 0) return null;
360 return mUsbDevice.Device.GetString(0, Descriptor.ManufacturerStringIndex);
361 }
362 }
363 public String ProductString {
364 get {
365 if (Descriptor.ProductStringIndex == 0) return null;
366 return mUsbDevice.Device.GetString(0, Descriptor.ProductStringIndex);
367 }
368 }
369 public String SerialString {
370 get {
371 if (Descriptor.SerialStringIndex == 0) return null;
372 return mUsbDevice.Device.GetString(0, Descriptor.SerialStringIndex);
373 }
374 }
375 }
376 public class UsbConfigInfo {
377 private readonly List<UsbInterfaceInfo> mInterfaceList = new List<UsbInterfaceInfo>();
378 internal readonly UsbConfigDescriptor mUsbConfigDescriptor;
379 internal UsbDevice mUsbDevice;
380 internal UsbConfigInfo(UsbDevice usbDevice, UsbConfigDescriptor descriptor, ref List<byte[]> rawDescriptors) {
381 mUsbDevice = usbDevice;
382 mUsbConfigDescriptor = descriptor;
383 UsbInterfaceInfo currentInterface = null;
384 for (int iRawDescriptor = 0; iRawDescriptor < rawDescriptors.Count; iRawDescriptor++) {
385 byte[] bytesRawDescriptor = rawDescriptors[iRawDescriptor];
386 switch (bytesRawDescriptor[1]) {
387 case (byte)UsbDescriptorType.Interface:
388 currentInterface = new UsbInterfaceInfo(usbDevice, bytesRawDescriptor);
389 mInterfaceList.Add(currentInterface);
390 break;
391 case (byte)UsbDescriptorType.Endpoint:
392 if (currentInterface == null) throw new Exception("Recieved and endpoint descriptor before receiving an interface descriptor.");
393 currentInterface.mEndpointInfo.Add(new UsbEndpointInfo(bytesRawDescriptor));
394 break;
395 }
396 }
397 }
398 public UsbConfigDescriptor Descriptor { get { return mUsbConfigDescriptor; } }
399 public ReadOnlyCollection<UsbInterfaceInfo> InterfaceInfoList { get { return mInterfaceList.AsReadOnly(); } }
400 }
401 public class UsbInterfaceInfo {
402 internal readonly UsbInterfaceDescriptor mUsbInterfaceDescriptor;
403 internal UsbDevice mUsbDevice;
404 internal List<UsbEndpointInfo> mEndpointInfo = new List<UsbEndpointInfo>();
405 internal UsbInterfaceInfo(UsbDevice usbDevice, byte[] descriptor) {
406 mUsbDevice = usbDevice;
407 mUsbInterfaceDescriptor = new UsbInterfaceDescriptor();
408 Helper.BytesToObject(descriptor, 0, Math.Min(UsbInterfaceDescriptor.Size, descriptor[0]), mUsbInterfaceDescriptor);
409 }
410 public UsbInterfaceDescriptor Descriptor { get { return mUsbInterfaceDescriptor; } }
411 public ReadOnlyCollection<UsbEndpointInfo> EndpointInfoList { get { return mEndpointInfo.AsReadOnly(); } }
412 }
413 public class UsbEndpointInfo {
414 internal UsbEndpointDescriptor mUsbEndpointDescriptor;
415 internal UsbEndpointInfo(byte[] descriptor) {
416 mUsbEndpointDescriptor = new UsbEndpointDescriptor();
417 Helper.BytesToObject(descriptor, 0, Math.Min(UsbEndpointDescriptor.Size, descriptor[0]), mUsbEndpointDescriptor);
418 }
419 public UsbEndpointDescriptor Descriptor {
420 get { return mUsbEndpointDescriptor; }
421 }
422 }
423 }
424 namespace LibUsbDotNet.Descriptors {
425 public enum DescriptorType : byte {
426 Device = 1,
427 Configuration = 2,
428 String = 3,
429 Interface = 4,
430 Endpoint = 5,
431 DeviceQualifier = 6,
432 OtherSpeedConfiguration = 7,
433 InterfacePower = 8,
434 OTG = 9,
435 Debug = 10,
436 InterfaceAssociation = 11,
437 Hid = 0x21,
438 HidReport = 0x22,
439 Physical = 0x23,
440 Hub = 0x29
441 }
442 public enum ClassCodeType : byte {
443 PerInterface = 0,
444 Audio = 1,
445 Comm = 2,
446 Hid = 3,
447 Printer = 7,
448 Ptp = 6,
449 MassStorage = 8,
450 Hub = 9,
451 Data = 10,
452 VendorSpec = 0xff
453 }
454 [StructLayout(LayoutKind.Sequential, Pack = 1)]
455 public abstract class UsbDescriptor {
456 public static readonly int Size = Marshal.SizeOf(typeof(UsbDescriptor));
457 public byte Length;
458 public DescriptorType DescriptorType;
459 }
460 [StructLayout(LayoutKind.Sequential, Pack = 1)]
461 public class UsbDeviceDescriptor : UsbDescriptor {
462 public new static readonly int Size = Marshal.SizeOf(typeof(UsbDeviceDescriptor));
463 public short BcdUsb;
464 public ClassCodeType Class;
465 public byte SubClass;
466 public byte Protocol;
467 public byte MaxPacketSize0;
468 public short VendorID;
469 public short ProductID;
470 public short BcdDevice;
471 public byte ManufacturerStringIndex;
472 public byte ProductStringIndex;
473 public byte SerialStringIndex;
474 public byte ConfigurationCount;
475 internal UsbDeviceDescriptor() { }
476 }
477 [StructLayout(LayoutKind.Sequential, Pack = 1)]
478 public class UsbConfigDescriptor : UsbDescriptor {
479 public new static readonly int Size = Marshal.SizeOf(typeof(UsbConfigDescriptor));
480 public readonly short TotalLength;
481 public readonly byte InterfaceCount;
482 public readonly byte ConfigID;
483 public readonly byte StringIndex;
484 public readonly byte Attributes;
485 public readonly byte MaxPower;
486 internal UsbConfigDescriptor() { }
487 }
488 [StructLayout(LayoutKind.Sequential, Pack = 1)]
489 public class UsbInterfaceDescriptor : UsbDescriptor {
490 public new static readonly int Size = Marshal.SizeOf(typeof(UsbInterfaceDescriptor));
491 public readonly byte InterfaceID;
492 public readonly byte AlternateID;
493 public readonly byte EndpointCount;
494 public readonly ClassCodeType Class;
495 public readonly byte SubClass;
496 public readonly byte Protocol;
497 public readonly byte StringIndex;
498 internal UsbInterfaceDescriptor() { }
499 }
500 [StructLayout(LayoutKind.Sequential, Pack = 1)]
501 public class UsbEndpointDescriptor : UsbDescriptor {
502 public new static readonly int Size = Marshal.SizeOf(typeof(UsbEndpointDescriptor));
503 public readonly byte EndpointID;
504 public readonly byte Attributes;
505 public readonly short MaxPacketSize;
506 public readonly byte Interval;
507 public readonly byte Refresh;
508 public readonly byte SynchAddress;
509 internal UsbEndpointDescriptor() { }
510 }
511 }
512 namespace MonoLibUsb {
513 public static class MonoUsbApi {
514 internal const CallingConvention CC = 0;
515 internal const string LIBUSB_DLL = "libusb-1.0.dll";
516 [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_detach_kernel_driver")]
517 public static extern int DetachKernelDriver([In] MonoUsbDeviceHandle deviceHandle, int interfaceNumber);
518 public static int ControlTransfer(MonoUsbDeviceHandle deviceHandle, byte requestType, byte request, short value, short index, object data, short dataLength, int timeout) {
519 throw new NotImplementedException();
520 }
521 public static int BulkTransfer(MonoUsbDeviceHandle deviceHandle, byte endpoint, object data, int length, out int actualLength, int timeout) {
522 throw new NotImplementedException();
523 }
524 }
525 public abstract class MonoUsbDeviceHandle : SafeHandle {
526 public MonoUsbDeviceHandle(Boolean bOwnsHandle) : base(IntPtr.Zero, bOwnsHandle) { }
527 }
528 }