changeset 68:e811297f5aa4

Updated USBLib: removed old LibUsbDotNet compatibility code and added new information helper classes
author Ivo Smits <Ivo@UCIS.nl>
date Wed, 16 Oct 2013 16:58:39 +0200
parents 2d16447eff12
children 82290dc1403c
files UCIS.Core.csproj USBLib/Communication/LibUsbDotNet.cs USBLib/Communication/USBIO/USBIODevice.cs USBLib/Communication/UsbDescriptorType.cs USBLib/Communication/WinUsb/WinUsbDevice.cs USBLib/Descriptor/UsbDescriptor.cs USBLib/Descriptor/UsbDescriptorType.cs USBLib/Descriptor/UsbInfo.cs USBLib/Internal/Windows/UsbApi.cs USBLib/Internal/Windows/Win32Kernel.cs USBLib/Windows/USB/UsbDevice.cs USBLib/Windows/USB/UsbHub.cs
diffstat 12 files changed, 343 insertions(+), 485 deletions(-) [+]
line wrap: on
line diff
--- a/UCIS.Core.csproj	Wed Oct 16 01:11:49 2013 +0200
+++ b/UCIS.Core.csproj	Wed Oct 16 16:58:39 2013 +0200
@@ -145,9 +145,8 @@
     <Compile Include="USBLib\Communication\LibUsb1\libusb1.cs" />
     <Compile Include="USBLib\Communication\LibUsb1\LibUsb1Device.cs" />
     <Compile Include="USBLib\Communication\LibUsb1\LibUsb1Registry.cs" />
-    <Compile Include="USBLib\Communication\LibUsbDotNet.cs" />
     <Compile Include="USBLib\Communication\UsbControlRequestType.cs" />
-    <Compile Include="USBLib\Communication\UsbDescriptorType.cs" />
+    <Compile Include="USBLib\Descriptor\UsbDescriptorType.cs" />
     <Compile Include="USBLib\Communication\UsbInterface.cs" />
     <Compile Include="USBLib\Communication\USBIO\USBIODevice.cs" />
     <Compile Include="USBLib\Communication\USBIO\USBIORegistry.cs" />
@@ -157,6 +156,7 @@
     <Compile Include="USBLib\Communication\WinUsb\WinUsbDevice.cs" />
     <Compile Include="USBLib\Communication\WinUsb\WinUsbRegistry.cs" />
     <Compile Include="USBLib\Descriptor\UsbDescriptor.cs" />
+    <Compile Include="USBLib\Descriptor\UsbInfo.cs" />
     <Compile Include="USBLib\Internal\Windows\SetupApi.cs" />
     <Compile Include="USBLib\Internal\Windows\UsbApi.cs" />
     <Compile Include="USBLib\Internal\Windows\Win32Kernel.cs" />
--- a/USBLib/Communication/LibUsbDotNet.cs	Wed Oct 16 01:11:49 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,353 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.IO;
-using System.Runtime.InteropServices;
-using System.Text;
-using System.Threading;
-using LibUsbDotNet.Descriptors;
-using LibUsbDotNet.Info;
-using LibUsbDotNet.Main;
-using UCIS.USBLib.Communication;
-using UCIS.USBLib.Descriptor;
-using LibUsb0Registry = UCIS.USBLib.Communication.LibUsb.LibUsb0Registry;
-using LibUsb1Registry = UCIS.USBLib.Communication.LibUsb1.LibUsb1Registry;
-using nIUsbDevice = UCIS.USBLib.Communication.IUsbDevice;
-using nIUsbInterface = UCIS.USBLib.Communication.IUsbInterface;
-using WinUsbRegistry = UCIS.USBLib.Communication.WinUsb.WinUsbRegistry;
-using USBIORegistry = UCIS.USBLib.Communication.USBIO.USBIORegistry;
-
-namespace LibUsbDotNet {
-	public class UsbDevice {
-		public nIUsbInterface Device { get; private set; }
-		public UsbDevice(nIUsbInterface dev) {
-			if (dev == null) throw new ArgumentNullException("dev");
-			Device = dev;
-		}
-		public bool GetDescriptor(byte descriptorType, byte index, short langId, Byte[] buffer, int bufferLength, out int transferLength) {
-			try {
-				transferLength = Device.GetDescriptor(descriptorType, index, langId, buffer, 0, bufferLength);
-				return true;
-			} catch {
-				transferLength = 0;
-				return false;
-			}
-		}
-		public bool ControlTransfer(ref UsbSetupPacket setupPacket, Byte[] buffer, int bufferLength, out int lengthTransferred) {
-			lengthTransferred = Device.ControlTransfer((UsbControlRequestType)setupPacket.RequestType, setupPacket.Request, setupPacket.Value, setupPacket.Index, buffer, 0, bufferLength);
-			return true;
-		}
-		public UsbEndpointReader OpenEndpointReader(ReadEndpointID readEndpointID, int buffersize, EndpointType endpointType) {
-			UsbEndpointReader reader = new UsbEndpointReader(Device, (Byte)readEndpointID, endpointType);
-			reader.ReadBufferSize = buffersize;
-			return reader;
-		}
-		public void Close() {
-			Device.Dispose();
-		}
-		public UsbDeviceInfo Info { get { return new UsbDeviceInfo(this); } }
-		public static IList<UsbRegistry> AllDevices {
-			get {
-				List<UsbRegistry> list = new List<UsbRegistry>();
-				if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
-					foreach (IUsbDeviceRegistry reg in WinUsbRegistry.DeviceList) list.Add(new UsbRegistry(reg));
-					foreach (IUsbDeviceRegistry reg in LibUsb0Registry.DeviceList) list.Add(new UsbRegistry(reg));
-					foreach (IUsbDeviceRegistry reg in USBIORegistry.DeviceList) list.Add(new UsbRegistry(reg));
-				} else {
-					foreach (IUsbDeviceRegistry reg in LibUsb1Registry.DeviceList) list.Add(new UsbRegistry(reg));
-				}
-				return list;
-			}
-		}
-		public bool SetConfiguration(byte config) {
-			nIUsbDevice dev = Device as nIUsbDevice;
-			if (dev == null) return false;
-			try {
-				dev.Configuration = config;
-				return true;
-			} catch {
-				return false;
-			}
-		}
-		public bool ClaimInterface(int interfaceID) {
-			nIUsbDevice dev = Device as nIUsbDevice;
-			if (dev == null) return false;
-			try {
-				if (dev.Configuration == 0) dev.Configuration = 1;
-				dev.ClaimInterface(interfaceID);
-				return true;
-			} catch {
-				return false;
-			}
-		}
-		public bool ReleaseInterface(int interfaceID) {
-			nIUsbDevice dev = Device as nIUsbDevice;
-			if (dev == null) return false;
-			try {
-				dev.ReleaseInterface(interfaceID);
-				return true;
-			} catch {
-				return false;
-			}
-		}
-		public IList<UsbConfigInfo> Configs {
-			get {
-				List<UsbConfigInfo> rtnConfigs = new List<UsbConfigInfo>();
-				int iConfigs = Info.Descriptor.NumConfigurations;
-				for (Byte iConfig = 0; iConfig < iConfigs; iConfig++) {
-					UsbConfigurationDescriptor configDescriptor = UsbConfigurationDescriptor.FromDevice(Device, iConfig);
-					if (configDescriptor.Length < UsbConfigurationDescriptor.Size || configDescriptor.Type != UsbDescriptorType.Configuration)
-						throw new Exception("GetDeviceConfigs: USB config descriptor is invalid.");
-					Byte[] cfgBuffer = new Byte[configDescriptor.TotalLength];
-					int iBytesTransmitted;
-					if (!GetDescriptor((byte)UsbDescriptorType.Configuration, (byte)iConfig, 0, cfgBuffer, cfgBuffer.Length, out iBytesTransmitted))
-						throw new Exception("Could not read configuration descriptor");
-					configDescriptor = UsbConfigurationDescriptor.FromByteArray(cfgBuffer, 0, iBytesTransmitted);
-					if (configDescriptor.Length < UsbConfigurationDescriptor.Size || configDescriptor.Type != UsbDescriptorType.Configuration)
-						throw new Exception("GetDeviceConfigs: USB config descriptor is invalid.");
-					if (configDescriptor.TotalLength != iBytesTransmitted) throw new Exception("GetDeviceConfigs: USB config descriptor length doesn't match the length received.");
-					List<byte[]> rawDescriptorList = new List<byte[]>();
-					int iRawLengthPosition = configDescriptor.Length;
-					while (iRawLengthPosition < configDescriptor.TotalLength) {
-						byte[] rawDescriptor = new byte[cfgBuffer[iRawLengthPosition]];
-						if (iRawLengthPosition + rawDescriptor.Length > iBytesTransmitted) throw new Exception("Descriptor length is out of range.");
-						Array.Copy(cfgBuffer, iRawLengthPosition, rawDescriptor, 0, rawDescriptor.Length);
-						rawDescriptorList.Add(rawDescriptor);
-						iRawLengthPosition += rawDescriptor.Length;
-					}
-					rtnConfigs.Add(new UsbConfigInfo(this, configDescriptor, rawDescriptorList));
-				}
-				return rtnConfigs;
-			}
-		}
-	}
-	public class UsbEndpointReader : IDisposable {
-		public nIUsbInterface Device { get; private set; }
-		public Byte EndpointID { get; private set; }
-		public EndpointType EndpointType { get; private set; }
-		public Byte EpNum { get { return EndpointID; } }
-		public int ReadBufferSize { get; set; }
-
-		public UsbEndpointReader(nIUsbInterface dev, byte epid, EndpointType eptype) {
-			Device = dev;
-			EndpointID = epid;
-			EndpointType = eptype;
-			ReadBufferSize = 4096;
-		}
-		public ErrorCode Read(byte[] buffer, int offset, int count, int timeout, out int transferLength) {
-			transferLength = Device.PipeTransfer(EndpointID, buffer, offset, count);
-			return ErrorCode.Ok;
-		}
-		public void Dispose() { DataReceivedEnabled = false; }
-
-		private bool mDataReceivedEnabled;
-		private Thread mReadThread;
-
-		public virtual bool DataReceivedEnabled {
-			get { return mDataReceivedEnabled; }
-			set {
-				if (value != mDataReceivedEnabled) {
-					if (mDataReceivedEnabled) {
-						mReadThread.Abort();
-					} else {
-						mDataReceivedEnabled = true;
-						mReadThread = new Thread(ReadDataProcess);
-						mReadThread.Start();
-					}
-				}
-			}
-		}
-
-		private void ReadDataProcess(object state) {
-			byte[] buffer = new byte[ReadBufferSize];
-			try {
-				while (mDataReceivedEnabled) {
-					int transferLength;
-					Read(buffer, 0, buffer.Length, -1, out transferLength);
-					EventHandler<EndpointDataEventArgs> eh = DataReceived;
-					if (!ReferenceEquals(eh, null)) eh(this, new EndpointDataEventArgs(buffer, transferLength));
-				}
-			} catch (Exception ex) {
-				if (ReadError != null) ReadError(this, new ErrorEventArgs(ex));
-			} finally {
-				mDataReceivedEnabled = false;
-			}
-		}
-
-		public event EventHandler<EndpointDataEventArgs> DataReceived;
-		public event ErrorEventHandler ReadError;
-	}
-}
-namespace LibUsbDotNet.Main {
-	public class EndpointDataEventArgs : EventArgs {
-		internal EndpointDataEventArgs(byte[] bytes, int size) {
-			Buffer = bytes;
-			Count = size;
-		}
-		public byte[] Buffer { get; private set; }
-		public int Count { get; private set; }
-	}
-	[StructLayout(LayoutKind.Sequential, Pack = 1)]
-	public struct UsbSetupPacket {
-		public byte RequestType;
-		public byte Request;
-		public short Value;
-		public short Index;
-		public short Length;
-		public UsbSetupPacket(byte requestType, byte request, short value, short index, short length) {
-			RequestType = requestType;
-			Request = request;
-			Value = value;
-			Index = index;
-			Length = length;
-		}
-	}
-	public enum UsbEndpointDirection : byte {
-		EndpointIn = 0x80,
-		EndpointOut = 0x00,
-	}
-	public enum UsbRequestType : byte {
-		TypeClass = (0x01 << 5),
-		TypeReserved = (0x03 << 5),
-		TypeStandard = (0x00 << 5),
-		TypeVendor = (0x02 << 5),
-	}
-	public enum ReadEndpointID : byte {
-		Ep01 = 0x81,
-		Ep02 = 0x82,
-		Ep03 = 0x83,
-		Ep04 = 0x84,
-		Ep05 = 0x85,
-		Ep06 = 0x86,
-		Ep07 = 0x87,
-		Ep08 = 0x88,
-		Ep09 = 0x89,
-		Ep10 = 0x8A,
-		Ep11 = 0x8B,
-		Ep12 = 0x8C,
-		Ep13 = 0x8D,
-		Ep14 = 0x8E,
-		Ep15 = 0x8F,
-	}
-	public enum UsbRequestRecipient : byte {
-		RecipDevice = 0x00,
-		RecipInterface = 0x01,
-		RecipEndpoint = 0x02,
-		RecipOther = 0x03,
-	}
-	public enum EndpointType : byte {
-		Control,
-		Isochronous,
-		Bulk,
-		Interrupt
-	}
-	public enum ErrorCode {
-		Ok = 0,
-		Error = 1,
-	}
-	public class UsbRegistry {
-		public IUsbDeviceRegistry Registry { get; private set; }
-		public UsbRegistry(IUsbDeviceRegistry reg) {
-			Registry = reg;
-		}
-		public int Vid { get { return Registry.Vid; } }
-		public int Pid { get { return Registry.Pid; } }
-		public int Rev { get { return 0; } }
-		public Boolean IsAlive { get { return true; } }
-		public Boolean Open(out UsbDevice hand) {
-			hand = new UsbDevice(Registry.Open());
-			return true;
-		}
-		public IDictionary<String, Object> DeviceProperties { get { return Registry.DeviceProperties; } }
-		public String FullName { get { return Registry.FullName; } }
-		public String Name { get { return Registry.Name; } }
-		public String SymbolicName { get { return Registry.SymbolicName; } }
-	}
-}
-namespace LibUsbDotNet.Info {
-	public class UsbDeviceInfo {
-		private readonly UsbDeviceDescriptor mDeviceDescriptor;
-		internal UsbDevice mUsbDevice;
-		internal UsbDeviceInfo(UsbDevice usbDevice) {
-			mUsbDevice = usbDevice;
-			mDeviceDescriptor = UsbDeviceDescriptor.FromDevice(usbDevice.Device);
-		}
-		public UsbDeviceDescriptor Descriptor { get { return mDeviceDescriptor; } }
-		public String ManufacturerString {
-			get {
-				if (Descriptor.ManufacturerStringID == 0) return null;
-				return UsbStringDescriptor.GetStringFromDevice(mUsbDevice.Device, Descriptor.ManufacturerStringID, 0);
-			}
-		}
-		public String ProductString {
-			get {
-				if (Descriptor.ProductStringID == 0) return null;
-				return UsbStringDescriptor.GetStringFromDevice(mUsbDevice.Device, Descriptor.ProductStringID, 0);
-			}
-		}
-		public String SerialString {
-			get {
-				if (Descriptor.SerialNumberStringID == 0) return null;
-				return UsbStringDescriptor.GetStringFromDevice(mUsbDevice.Device, Descriptor.SerialNumberStringID, 0);
-			}
-		}
-	}
-	public class UsbConfigInfo {
-		private readonly List<UsbInterfaceInfo> mInterfaceList = new List<UsbInterfaceInfo>();
-		internal readonly UsbConfigurationDescriptor mUsbConfigDescriptor;
-		internal UsbDevice mUsbDevice;
-		internal UsbConfigInfo(UsbDevice usbDevice, UsbConfigurationDescriptor descriptor, IEnumerable<byte[]> rawDescriptors) {
-			mUsbDevice = usbDevice;
-			mUsbConfigDescriptor = descriptor;
-			UsbInterfaceInfo currentInterface = null;
-			foreach (Byte[] bytesRawDescriptor in rawDescriptors) {
-				switch (bytesRawDescriptor[1]) {
-					case (byte)UsbDescriptorType.Interface:
-						currentInterface = new UsbInterfaceInfo(usbDevice, bytesRawDescriptor);
-						mInterfaceList.Add(currentInterface);
-						break;
-					case (byte)UsbDescriptorType.Endpoint:
-						if (currentInterface == null) throw new Exception("Recieved and endpoint descriptor before receiving an interface descriptor.");
-						currentInterface.mEndpointInfo.Add(new UsbEndpointInfo(bytesRawDescriptor));
-						break;
-				}
-			}
-		}
-		public UsbConfigurationDescriptor Descriptor { get { return mUsbConfigDescriptor; } }
-		public ReadOnlyCollection<UsbInterfaceInfo> InterfaceInfoList { get { return mInterfaceList.AsReadOnly(); } }
-	}
-	public class UsbInterfaceInfo {
-		internal readonly UsbInterfaceDescriptor mUsbInterfaceDescriptor;
-		internal UsbDevice mUsbDevice;
-		internal List<UsbEndpointInfo> mEndpointInfo = new List<UsbEndpointInfo>();
-		internal UsbInterfaceInfo(UsbDevice usbDevice, byte[] descriptor) {
-			mUsbDevice = usbDevice;
-			mUsbInterfaceDescriptor = UsbInterfaceDescriptor.FromByteArray(descriptor, 0, descriptor.Length);
-		}
-		public UsbInterfaceDescriptor Descriptor { get { return mUsbInterfaceDescriptor; } }
-		public ReadOnlyCollection<UsbEndpointInfo> EndpointInfoList { get { return mEndpointInfo.AsReadOnly(); } }
-	}
-	public class UsbEndpointInfo {
-		internal UsbEndpointDescriptor mUsbEndpointDescriptor;
-		internal UsbEndpointInfo(byte[] descriptor) {
-			mUsbEndpointDescriptor = UsbEndpointDescriptor.FromByteArray(descriptor, 0, descriptor.Length);
-		}
-		public UsbEndpointDescriptor Descriptor {
-			get { return mUsbEndpointDescriptor; }
-		}
-	}
-}
-namespace LibUsbDotNet.Descriptors {
-	public enum ClassCodeType : byte {
-		PerInterface = 0,
-		Audio = 1,
-		Comm = 2,
-		Hid = 3,
-		Printer = 7,
-		Ptp = 6,
-		MassStorage = 8,
-		Hub = 9,
-		Data = 10,
-		VendorSpec = 0xff
-	}
-}
--- a/USBLib/Communication/USBIO/USBIODevice.cs	Wed Oct 16 01:11:49 2013 +0200
+++ b/USBLib/Communication/USBIO/USBIODevice.cs	Wed Oct 16 16:58:39 2013 +0200
@@ -4,6 +4,7 @@
 using System.IO;
 using System.Runtime.InteropServices;
 using Microsoft.Win32.SafeHandles;
+using UCIS.USBLib.Descriptor;
 using UCIS.USBLib.Internal.Windows;
 
 namespace UCIS.USBLib.Communication.USBIO {
@@ -107,30 +108,24 @@
 		public override Byte Configuration {
 			get { return base.Configuration; }
 			set {
-				IList<LibUsbDotNet.Info.UsbConfigInfo> configs = (new LibUsbDotNet.UsbDevice(this)).Configs;
-				for (int i = 0; i < configs.Count; i++) {
-					LibUsbDotNet.Info.UsbConfigInfo config = configs[i];
-					if (config.Descriptor.ConfigurationValue == value) {
-						unsafe {
-							USBIO_SET_CONFIGURATION req = new USBIO_SET_CONFIGURATION();
-							req.ConfigurationIndex = (ushort)i;
-							req.NbOfInterfaces = Math.Min((ushort)32, config.Descriptor.NumInterfaces);
-							for (int j = 0; j < req.NbOfInterfaces; j++) {
-								LibUsbDotNet.Info.UsbInterfaceInfo intf = config.InterfaceInfoList[j];
-								*((USBIO_INTERFACE_SETTING*)(req.InterfaceList + sizeof(USBIO_INTERFACE_SETTING) * j)) =
-									new USBIO_INTERFACE_SETTING() { InterfaceIndex = intf.Descriptor.InterfaceNumber, AlternateSettingIndex = 0, MaximumTransferSize = UInt16.MaxValue };
-							}
-							try {
-								DeviceIoControl(DeviceHandle, IOCTL_USBIO_SET_CONFIGURATION, (IntPtr)(&req), sizeof(USBIO_SET_CONFIGURATION), IntPtr.Zero, 0);
-							} catch (Win32Exception ex) {
-								if (ex.NativeErrorCode == unchecked((int)0xE0001005L)) return;
-								throw;
-							}
-						}
-						return;
+				UsbConfigurationInfo configuration = UsbDeviceInfo.FromDevice(this).FindConfiguration(value);
+				if (configuration == null) throw new InvalidOperationException("Requested configuration ID not found");
+				unsafe {
+					USBIO_SET_CONFIGURATION req = new USBIO_SET_CONFIGURATION();
+					req.ConfigurationIndex = configuration.Index;
+					req.NbOfInterfaces = Math.Min((ushort)32, configuration.Descriptor.NumInterfaces);
+					for (int j = 0; j < req.NbOfInterfaces; j++) {
+						UsbInterfaceInfo intf = configuration.Interfaces[j];
+						*((USBIO_INTERFACE_SETTING*)(req.InterfaceList + sizeof(USBIO_INTERFACE_SETTING) * j)) =
+							new USBIO_INTERFACE_SETTING() { InterfaceIndex = intf.Descriptor.InterfaceNumber, AlternateSettingIndex = 0, MaximumTransferSize = UInt16.MaxValue };
+					}
+					try {
+						DeviceIoControl(DeviceHandle, IOCTL_USBIO_SET_CONFIGURATION, (IntPtr)(&req), sizeof(USBIO_SET_CONFIGURATION), IntPtr.Zero, 0);
+					} catch (Win32Exception ex) {
+						if (ex.NativeErrorCode == unchecked((int)0xE0001005L)) return;
+						throw;
 					}
 				}
-				throw new InvalidOperationException("Requested configuration ID not found");
 			}
 		}
 
--- a/USBLib/Communication/UsbDescriptorType.cs	Wed Oct 16 01:11:49 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-using System;
-
-namespace UCIS.USBLib.Communication {
-	[Flags]
-	public enum UsbDescriptorType : byte {
-		/// <summary>
-		/// Device descriptor type.
-		/// </summary>
-		Device = 1,
-		/// <summary>
-		/// Configuration descriptor type.
-		/// </summary>
-		Configuration = 2,
-		/// <summary>
-		/// String descriptor type.
-		/// </summary>
-		String = 3,
-		/// <summary>
-		/// Interface descriptor type.
-		/// </summary>
-		Interface = 4,
-		/// <summary>
-		/// Endpoint descriptor type.
-		/// </summary>
-		Endpoint = 5,
-		/// <summary>
-		/// Device Qualifier descriptor type.
-		/// </summary>
-		DeviceQualifier = 6,
-		/// <summary>
-		/// Other Speed Configuration descriptor type.
-		/// </summary>
-		OtherSpeedConfiguration = 7,
-		/// <summary>
-		/// Interface Power descriptor type.
-		/// </summary>
-		InterfacePower = 8,
-		/// <summary>
-		/// OTG descriptor type.
-		/// </summary>
-		OTG = 9,
-		/// <summary>
-		/// Debug descriptor type.
-		/// </summary>
-		Debug = 10,
-		/// <summary>
-		/// Interface Association descriptor type.
-		/// </summary>
-		InterfaceAssociation = 11,
-
-		///<summary> HID descriptor</summary>
-		Hid = 0x21,
-
-		///<summary> HID report descriptor</summary>
-		HidReport = 0x22,
-
-		///<summary> Physical descriptor</summary>
-		Physical = 0x23,
-
-		///<summary> Hub descriptor</summary>
-		Hub = 0x29
-	}
-}
\ No newline at end of file
--- a/USBLib/Communication/WinUsb/WinUsbDevice.cs	Wed Oct 16 01:11:49 2013 +0200
+++ b/USBLib/Communication/WinUsb/WinUsbDevice.cs	Wed Oct 16 16:58:39 2013 +0200
@@ -3,6 +3,7 @@
 using System.Runtime.InteropServices;
 using System.Security;
 using Microsoft.Win32.SafeHandles;
+using UCIS.USBLib.Descriptor;
 using UCIS.USBLib.Internal.Windows;
 
 namespace UCIS.USBLib.Communication.WinUsb {
@@ -79,19 +80,15 @@
 			if (!WinUsb_Initialize(DeviceHandle, out InterfaceHandle)) throw new Win32Exception(Marshal.GetLastWin32Error(), "Could not initialize WinUsb");
 			if (InterfaceHandle.IsInvalid || InterfaceHandle.IsClosed) throw new Win32Exception(Marshal.GetLastWin32Error(), "Could not open interface");
 			InterfaceHandles = new SafeWinUsbInterfaceHandle[1] { InterfaceHandle };
-			foreach (LibUsbDotNet.Info.UsbConfigInfo ci in (new LibUsbDotNet.UsbDevice(this)).Configs) {
-				if (ci.Descriptor.ConfigurationValue == Configuration) {
-					foreach (LibUsbDotNet.Info.UsbInterfaceInfo ifinfo in ci.InterfaceInfoList) {
-						foreach (LibUsbDotNet.Info.UsbEndpointInfo epinfo in ifinfo.EndpointInfoList) {
-							int epidx = epinfo.Descriptor.EndpointAddress & 0x7F;
-							if ((epinfo.Descriptor.EndpointAddress & 0x80) != 0) {
-								if (EndpointToInterfaceIn.Length <= epidx) Array.Resize(ref EndpointToInterfaceIn, epidx + 1);
-								EndpointToInterfaceIn[epidx] = ifinfo.Descriptor.InterfaceNumber;
-							} else {
-								if (EndpointToInterfaceOut.Length <= epidx) Array.Resize(ref EndpointToInterfaceOut, epidx + 1);
-								EndpointToInterfaceOut[epidx] = ifinfo.Descriptor.InterfaceNumber;
-							}
-						}
+			foreach (UsbInterfaceInfo ifinfo in UsbDeviceInfo.FromDevice(this).FindConfiguration(Configuration).Interfaces) {
+				foreach (UsbEndpointDescriptor epinfo in ifinfo.Endpoints) {
+					int epidx = epinfo.EndpointAddress & 0x7F;
+					if ((epinfo.EndpointAddress & 0x80) != 0) {
+						if (EndpointToInterfaceIn.Length <= epidx) Array.Resize(ref EndpointToInterfaceIn, epidx + 1);
+						EndpointToInterfaceIn[epidx] = ifinfo.Descriptor.InterfaceNumber;
+					} else {
+						if (EndpointToInterfaceOut.Length <= epidx) Array.Resize(ref EndpointToInterfaceOut, epidx + 1);
+						EndpointToInterfaceOut[epidx] = ifinfo.Descriptor.InterfaceNumber;
 					}
 				}
 			}
--- a/USBLib/Descriptor/UsbDescriptor.cs	Wed Oct 16 01:11:49 2013 +0200
+++ b/USBLib/Descriptor/UsbDescriptor.cs	Wed Oct 16 16:58:39 2013 +0200
@@ -2,8 +2,25 @@
 using System.Runtime.InteropServices;
 using System.Text;
 using UCIS.USBLib.Communication;
+using UCIS.Util;
 
 namespace UCIS.USBLib.Descriptor {
+	public struct UsbDescriptorBlob {
+		public UsbDescriptorBlob(ArraySegment<Byte> data) : this() { this.Data = data; }
+		public UsbDescriptorBlob(Byte[] data) : this() { this.Data = new ArraySegment<byte>(data); }
+		public UsbDescriptorBlob(Byte[] data, int offset) : this() { this.Data = new ArraySegment<byte>(data, offset, data[offset + 0]); }
+		public ArraySegment<Byte> Data { get; private set; }
+		public Byte Length { get { return Data.Array[Data.Offset + 0]; } }
+		public UsbDescriptorType Type { get { return (UsbDescriptorType)Data.Array[Data.Offset + 1]; } }
+		public Byte[] GetBytes() { return ArrayUtil.ToArray(Data); }
+		public static explicit operator UsbDescriptor(UsbDescriptorBlob self) { return UsbDescriptor.FromByteArray(self.Data.Array, self.Data.Offset, self.Data.Count); }
+		public static explicit operator UsbDeviceDescriptor(UsbDescriptorBlob self) { return UsbDeviceDescriptor.FromByteArray(self.Data.Array, self.Data.Offset, self.Data.Count); }
+		public static explicit operator UsbConfigurationDescriptor(UsbDescriptorBlob self) { return UsbConfigurationDescriptor.FromByteArray(self.Data.Array, self.Data.Offset, self.Data.Count); }
+		public static explicit operator UsbInterfaceDescriptor(UsbDescriptorBlob self) { return UsbInterfaceDescriptor.FromByteArray(self.Data.Array, self.Data.Offset, self.Data.Count); }
+		public static explicit operator UsbEndpointDescriptor(UsbDescriptorBlob self) { return UsbEndpointDescriptor.FromByteArray(self.Data.Array, self.Data.Offset, self.Data.Count); }
+		public static explicit operator UsbHidDescriptor(UsbDescriptorBlob self) { return UsbHidDescriptor.FromByteArray(self.Data.Array, self.Data.Offset, self.Data.Count); }
+		public static explicit operator UsbHubDescriptor(UsbDescriptorBlob self) { return UsbHubDescriptor.FromByteArray(self.Data.Array, self.Data.Offset, self.Data.Count); }
+	}
 	[StructLayout(LayoutKind.Sequential, Pack = 1)]
 	public struct UsbDescriptor {
 		byte bmLength;
@@ -56,7 +73,7 @@
 		public Byte Length { get { return bmLength; } }
 		public UsbDescriptorType Type { get { return (UsbDescriptorType)bType; }}
 		public short USBVersion { get { return UsbDescriptor.FromLittleEndian(bcdUSB); } }
-		public Byte DeviceClass { get { return bDeviceClass; } }
+		public UsbClassCode DeviceClass { get { return (UsbClassCode)bDeviceClass; } }
 		public Byte DeviceSubClass { get { return bDeviceSubClass; } }
 		public Byte DeviceProtocol { get { return bDeviceProtocol; } }
 		public UInt16 DeviceVersion { get { return (UInt16)UsbDescriptor.FromLittleEndian(bcdDevice); } }
@@ -67,14 +84,20 @@
 		public Byte ProductStringID { get { return iProduct; } }
 		public Byte SerialNumberStringID { get { return iSerialNumber; } }
 		public Byte NumConfigurations { get { return numConfigurations; } }
+		public unsafe Byte[] GetBytes() {
+			Byte[] buffer = new Byte[Size];
+			fixed (Byte* ptr = buffer) *(UsbDeviceDescriptor*)ptr = this;
+			return buffer;
+		}
 		public unsafe static UsbDeviceDescriptor FromByteArray(Byte[] buffer, int offset, int length) {
 			if (length < Size) throw new ArgumentOutOfRangeException("length", "The data length is smaller than the descriptor length");
 			if (offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer dimensions");
 			fixed (Byte* ptr = buffer) return *(UsbDeviceDescriptor*)(ptr + offset);
 		}
 		public static UsbDeviceDescriptor FromDevice(IUsbInterface device) {
-			Byte[] buff = new Byte[UsbDeviceDescriptor.Size];
+			Byte[] buff = new Byte[Size];
 			int len = device.GetDescriptor((Byte)UsbDescriptorType.Device, 0, 0, buff, 0, buff.Length);
+			if (len == 0) return new UsbDeviceDescriptor();
 			return FromByteArray(buff, 0, len);
 		}
 		public static unsafe int Size { get { return sizeof(UsbDeviceDescriptor); } }
@@ -106,6 +129,7 @@
 		public static UsbConfigurationDescriptor FromDevice(IUsbInterface device, Byte index) {
 			Byte[] buff = new Byte[UsbConfigurationDescriptor.Size];
 			int len = device.GetDescriptor((Byte)UsbDescriptorType.Configuration, index, 0, buff, 0, buff.Length);
+			if (len == 0) return new UsbConfigurationDescriptor();
 			return FromByteArray(buff, 0, len);
 		}
 		public static unsafe int Size { get { return sizeof(UsbConfigurationDescriptor); } }
@@ -126,7 +150,7 @@
 		public Byte InterfaceNumber { get { return bInterfaceNumber; } }
 		public Byte AlternateSetting { get { return bAlternateSetting; } }
 		public Byte NumEndpoints { get { return bNumEndpoints; } }
-		public Byte InterfaceClass { get { return bInterfaceClass; } }
+		public UsbClassCode InterfaceClass { get { return (UsbClassCode)bInterfaceClass; } }
 		public Byte InterfaceSubClass { get { return bInterfaceSubClass; } }
 		public Byte InterfaceProtocol { get { return bInterfaceProtocol; } }
 		public Byte InterfaceStringID { get { return bInterfaceStringID; } }
@@ -165,7 +189,7 @@
 		public static unsafe int Size { get { return sizeof(UsbEndpointDescriptor); } }
 	}
 	[StructLayout(LayoutKind.Sequential, Pack = 1)]
-	public struct UsbHIDDescriptor {
+	public struct UsbHidDescriptor {
 		byte bmLength;
 		byte bType;
 		short bcdHID;
@@ -180,12 +204,12 @@
 		public Byte NumDescriptors { get { return bNumDescriptors; } }
 		public UsbDescriptorType DescriptorType { get { return (UsbDescriptorType)bDescriptorType; } }
 		public short DescriptorLength { get { return UsbDescriptor.FromLittleEndian(wDescriptorLength); } }
-		public unsafe static UsbHIDDescriptor FromByteArray(Byte[] buffer, int offset, int length) {
+		public unsafe static UsbHidDescriptor FromByteArray(Byte[] buffer, int offset, int length) {
 			if (length < Size) throw new ArgumentOutOfRangeException("length", "The data length is smaller than the descriptor length");
 			if (offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer dimensions");
-			fixed (Byte* ptr = buffer) return *(UsbHIDDescriptor*)(ptr + offset);
+			fixed (Byte* ptr = buffer) return *(UsbHidDescriptor*)(ptr + offset);
 		}
-		public static unsafe int Size { get { return sizeof(UsbHIDDescriptor); } }
+		public static unsafe int Size { get { return sizeof(UsbHidDescriptor); } }
 	}
 	[StructLayout(LayoutKind.Sequential, Pack = 1)]
 	public struct UsbHubDescriptor {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBLib/Descriptor/UsbDescriptorType.cs	Wed Oct 16 16:58:39 2013 +0200
@@ -0,0 +1,84 @@
+using System;
+
+namespace UCIS.USBLib.Descriptor {
+	public enum UsbDescriptorType : byte {
+		/// <summary>
+		/// Device descriptor type.
+		/// </summary>
+		Device = 1,
+		/// <summary>
+		/// Configuration descriptor type.
+		/// </summary>
+		Configuration = 2,
+		/// <summary>
+		/// String descriptor type.
+		/// </summary>
+		String = 3,
+		/// <summary>
+		/// Interface descriptor type.
+		/// </summary>
+		Interface = 4,
+		/// <summary>
+		/// Endpoint descriptor type.
+		/// </summary>
+		Endpoint = 5,
+		/// <summary>
+		/// Device Qualifier descriptor type.
+		/// </summary>
+		DeviceQualifier = 6,
+		/// <summary>
+		/// Other Speed Configuration descriptor type.
+		/// </summary>
+		OtherSpeedConfiguration = 7,
+		/// <summary>
+		/// Interface Power descriptor type.
+		/// </summary>
+		InterfacePower = 8,
+		/// <summary>
+		/// OTG descriptor type.
+		/// </summary>
+		OTG = 9,
+		/// <summary>
+		/// Debug descriptor type.
+		/// </summary>
+		Debug = 10,
+		/// <summary>
+		/// Interface Association descriptor type.
+		/// </summary>
+		InterfaceAssociation = 11,
+
+		///<summary> HID descriptor</summary>
+		Hid = 0x21,
+
+		///<summary> HID report descriptor</summary>
+		HidReport = 0x22,
+
+		///<summary> Physical descriptor</summary>
+		Physical = 0x23,
+
+		///<summary> Hub descriptor</summary>
+		Hub = 0x29
+	}
+	public enum UsbClassCode : byte {
+		Unspecified = 0x00,
+		Audio = 0x01,
+		Communications = 0x02,
+		HID = 0x03,
+		PID = 0x05,
+		Image = 0x06,
+		Printer = 0x07,
+		MassStorage = 0x08,
+		Hub = 0x09,
+		Data = 0x0A,
+		SmartCard = 0x0B,
+		ContentSecurity = 0x0D,
+		Video = 0x0E,
+		Healthcare = 0x0F,
+		AV = 0x10,
+		Diagnostic = 0xDC,
+		Wireless = 0xE0,
+		Miscellaneous = 0xEF,
+		ApplicationSpecific = 0xFE,
+		VendorSpecific = 0xFF
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBLib/Descriptor/UsbInfo.cs	Wed Oct 16 16:58:39 2013 +0200
@@ -0,0 +1,187 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using UCIS.USBLib.Communication;
+using UCIS.Util;
+
+namespace UCIS.USBLib.Descriptor {
+	public class UsbDeviceInfo {
+		private UsbDeviceDescriptor mDeviceDescriptor;
+		private Boolean mHasDeviceDescriptor = false;
+		private UsbConfigurationInfo[] mConfigurations = null;
+		private short language = 0;
+		public IUsbInterface Device { get; private set; }
+		public UsbDeviceInfo(IUsbInterface device) {
+			if (device == null) throw new ArgumentNullException("device");
+			this.Device = device;
+		}
+		private void GetDescriptor() {
+			if (mHasDeviceDescriptor) return;
+			mDeviceDescriptor = UsbDeviceDescriptor.FromDevice(Device);
+			mHasDeviceDescriptor = (mDeviceDescriptor.Length >= UsbDeviceDescriptor.Size && mDeviceDescriptor.Type == UsbDescriptorType.Device);
+		}
+		public String GetString(Byte index, short langId) {
+			if (index == 0) return null;
+			return UsbStringDescriptor.GetStringFromDevice(Device, index, langId);
+		}
+		public String GetString(Byte index) {
+			if (language == 0) {
+				Byte[] buff = new Byte[4];
+				int len = Device.GetDescriptor((Byte)UsbDescriptorType.String, 0, 0, buff, 0, buff.Length);
+				if (len >= 4) language = BitConverter.ToInt16(buff, 2);
+			}
+			return GetString(index, language);
+		}
+		public UsbDeviceDescriptor Descriptor { get { GetDescriptor(); return mDeviceDescriptor; } }
+		public String ManufacturerString { get { return GetString(Descriptor.ManufacturerStringID); } }
+		public String ProductString { get { return GetString(Descriptor.ProductStringID); } }
+		public String SerialString { get { return GetString(Descriptor.SerialNumberStringID); } }
+		public IList<UsbConfigurationInfo> Configurations {
+			get {
+				if (mConfigurations == null) {
+					mConfigurations = new UsbConfigurationInfo[Descriptor.NumConfigurations];
+					for (Byte i = 0; i < mConfigurations.Length; i++) mConfigurations[i] = new UsbConfigurationInfo(this, i);
+				}
+				return mConfigurations;
+			}
+		}
+		public UsbConfigurationInfo FindConfiguration(Byte value) {
+			foreach (UsbConfigurationInfo configuration in Configurations) if (configuration.Descriptor.ConfigurationValue == value) return configuration;
+			return null;
+		}
+		public static UsbDeviceInfo FromDevice(IUsbInterface device) {
+			return new UsbDeviceInfo(device);
+		}
+		public static UsbDeviceInfo FromDeviceNode(UCIS.HWLib.Windows.Devices.DeviceNode devnode) {
+			IUsbInterface device = UCIS.HWLib.Windows.USB.UsbDevice.GetUsbDevice(devnode);
+			if (device == null) return null;
+			return new UsbDeviceInfo(device);
+		}
+	}
+	public class UsbConfigurationInfo {
+		private UsbConfigurationDescriptor mConfigurationDescriptor;
+		private Boolean mHasConfigurationDescriptor = false;
+		private Byte[] mConfigurationBlob = null;
+		private UsbDescriptorBlob[] mDescriptors = null;
+		private UsbInterfaceInfo[] mInterfaces = null;
+		public UsbDeviceInfo Device { get; private set; }
+		public Byte Index { get; private set; }
+		internal UsbConfigurationInfo(UsbDeviceInfo device, Byte index) {
+			this.Device = device;
+			this.Index = index;
+		}
+		private void GetConfigurationBlob() {
+			if (mConfigurationBlob != null) return;
+			int length = Descriptor.TotalLength;
+			if (!mHasConfigurationDescriptor) throw new Exception("Configuration descriptor is invalid");
+			Byte[] blob = new Byte[length];
+			length = Device.Device.GetDescriptor((Byte)UsbDescriptorType.Configuration, Index, 0, blob, 0, length);
+			if (length != blob.Length) throw new Exception("Could not read configuration descriptor");
+			List<UsbDescriptorBlob> descriptors = new List<UsbDescriptorBlob>();
+			for (int offset = 0; offset < length; ) {
+				if (length - offset < 2) throw new Exception("Descriptor has been truncated");
+				UsbDescriptorBlob descriptor = new UsbDescriptorBlob(blob, offset);
+				if (length - offset < descriptor.Length) throw new Exception("Descriptor has been truncated");
+				descriptors.Add(descriptor);
+				offset += descriptor.Length;
+			}
+			mConfigurationBlob = blob;
+			mDescriptors = descriptors.ToArray();
+		}
+		public UsbConfigurationDescriptor Descriptor {
+			get {
+				if (!mHasConfigurationDescriptor) {
+					mConfigurationDescriptor = UsbConfigurationDescriptor.FromDevice(Device.Device, Index);
+					mHasConfigurationDescriptor = (mConfigurationDescriptor.Length >= UsbConfigurationDescriptor.Size && mConfigurationDescriptor.Type == UsbDescriptorType.Configuration);
+				}
+				return mConfigurationDescriptor;
+			}
+		}
+		public IList<UsbDescriptorBlob> Descriptors { get { GetConfigurationBlob(); return mDescriptors; } }
+		private void GetInterfaces() {
+			if (mInterfaces != null) return;
+			GetConfigurationBlob();
+			UsbInterfaceInfo[] interfaces = new UsbInterfaceInfo[Descriptor.NumInterfaces];
+			int index = 0;
+			int first = -1;
+			for (int i = 0; i < mDescriptors.Length; i++) {
+				UsbDescriptorBlob descriptor = mDescriptors[i];
+				if (descriptor.Type != UsbDescriptorType.Interface) continue;
+				if (first != -1) {
+					if (index >= interfaces.Length) Array.Resize(ref interfaces, index + 1);
+					interfaces[index] = new UsbInterfaceInfo(this, ArrayUtil.Slice(mDescriptors, first, i - first));
+					index++;
+				}
+				first = i;
+			}
+			if (first != -1) {
+				if (index >= interfaces.Length) Array.Resize(ref interfaces, index + 1);
+				interfaces[index] = new UsbInterfaceInfo(this, ArrayUtil.Slice(mDescriptors, first, mDescriptors.Length - first));
+			}
+			mInterfaces = interfaces;
+		}
+		public IList<UsbInterfaceInfo> Interfaces { get { GetInterfaces(); return mInterfaces; } }
+		public UsbInterfaceInfo FindInterface(Predicate<UsbInterfaceInfo> predicate) {
+			GetInterfaces();
+			foreach (UsbInterfaceInfo interf in mInterfaces) if (predicate(interf)) return interf;
+			return null;
+		}
+		public UsbInterfaceInfo FindInterface(Byte number) {
+			return FindInterface(number, 0);
+		}
+		public UsbInterfaceInfo FindInterface(Byte number, Byte alternateSetting) {
+			return FindInterface(delegate(UsbInterfaceInfo interf) { return interf.Descriptor.InterfaceNumber == number && interf.Descriptor.AlternateSetting == alternateSetting; });
+		}
+		public UsbInterfaceInfo FindInterfaceByClass(UsbClassCode usbclass) {
+			return FindInterface(delegate(UsbInterfaceInfo interf) { return interf.Descriptor.InterfaceClass == usbclass; });
+		}
+		public UsbInterfaceInfo FindInterfaceByClass(UsbClassCode usbclass, Byte subclass) {
+			return FindInterface(delegate(UsbInterfaceInfo interf) { return interf.Descriptor.InterfaceClass == usbclass && interf.Descriptor.InterfaceSubClass == subclass; });
+		}
+		public UsbDescriptorBlob FindDescriptor(UsbDescriptorType type) {
+			GetConfigurationBlob();
+			return Array.Find(mDescriptors, delegate(UsbDescriptorBlob descriptor) { return descriptor.Type == type; });
+		}
+		public UsbDescriptorBlob[] FindDescriptors(UsbDescriptorType type) {
+			GetConfigurationBlob();
+			return Array.FindAll(mDescriptors, delegate(UsbDescriptorBlob descriptor) { return descriptor.Type == type; });
+		}
+	}
+	public class UsbInterfaceInfo {
+		public UsbConfigurationInfo Configuration { get; private set; }
+		private UsbDescriptorBlob[] mDescriptors;
+		public UsbInterfaceInfo(UsbConfigurationInfo configuration, UsbDescriptorBlob[] descriptors) {
+			this.Configuration = configuration;
+			this.mDescriptors = descriptors;
+		}
+		public UsbInterfaceDescriptor Descriptor { get { return (UsbInterfaceDescriptor)mDescriptors[0]; } }
+		public IList<UsbEndpointDescriptor> Endpoints {
+			get {
+				return Array.ConvertAll(FindDescriptors(UsbDescriptorType.Endpoint), delegate(UsbDescriptorBlob descriptor) { return (UsbEndpointDescriptor)descriptor; });
+			}
+		}
+		public UsbEndpointDescriptor FindEndpoint(Predicate<UsbEndpointDescriptor> predicate) {
+			foreach (UsbDescriptorBlob descriptor in mDescriptors) {
+				if (descriptor.Type != UsbDescriptorType.Endpoint) continue;
+				UsbEndpointDescriptor ep = (UsbEndpointDescriptor)descriptor;
+				if (predicate(ep)) return ep;
+			}
+			return default(UsbEndpointDescriptor);
+		}
+		public UsbEndpointDescriptor FindEndpoint(Byte address) {
+			return FindEndpoint(delegate(UsbEndpointDescriptor ep) { return ep.EndpointAddress == address; });
+		}
+		public UsbEndpointDescriptor FindEndpoint(Boolean input) {
+			return FindEndpoint(delegate(UsbEndpointDescriptor ep) { return ep.IsInput == input; });
+		}
+		public UsbEndpointDescriptor FindEndpoint(Boolean input, int transferType) {
+			return FindEndpoint(delegate(UsbEndpointDescriptor ep) { return ep.TransferType == transferType && ep.IsInput == input; });
+		}
+		public UsbDescriptorBlob FindDescriptor(UsbDescriptorType type) {
+			return Array.Find(mDescriptors, delegate(UsbDescriptorBlob descriptor) { return descriptor.Type == type; });
+		}
+		public UsbDescriptorBlob[] FindDescriptors(UsbDescriptorType type) {
+			return Array.FindAll(mDescriptors, delegate(UsbDescriptorBlob descriptor) { return descriptor.Type == type; });
+		}
+	}
+}
--- a/USBLib/Internal/Windows/UsbApi.cs	Wed Oct 16 01:11:49 2013 +0200
+++ b/USBLib/Internal/Windows/UsbApi.cs	Wed Oct 16 16:58:39 2013 +0200
@@ -27,28 +27,6 @@
 		public const int DICS_DISABLE = 0x00000002;
 	}
 
-	enum UsbDeviceClass : byte {
-		UnspecifiedDevice = 0x00,
-		AudioInterface = 0x01,
-		CommunicationsAndCDCControlBoth = 0x02,
-		HIDInterface = 0x03,
-		PhysicalInterfaceDevice = 0x5,
-		ImageInterface = 0x06,
-		PrinterInterface = 0x07,
-		MassStorageInterface = 0x08,
-		HubDevice = 0x09,
-		CDCDataInterface = 0x0A,
-		SmartCardInterface = 0x0B,
-		ContentSecurityInterface = 0x0D,
-		VidioInterface = 0x0E,
-		PersonalHeathcareInterface = 0x0F,
-		DiagnosticDeviceBoth = 0xDC,
-		WirelessControllerInterface = 0xE0,
-		MiscellaneousBoth = 0xEF,
-		ApplicationSpecificInterface = 0xFE,
-		VendorSpecificBoth = 0xFF
-	}
-
 	enum HubCharacteristics : byte {
 		GangedPowerSwitching = 0x00,
 		IndividualPotPowerSwitching = 0x01,
--- a/USBLib/Internal/Windows/Win32Kernel.cs	Wed Oct 16 01:11:49 2013 +0200
+++ b/USBLib/Internal/Windows/Win32Kernel.cs	Wed Oct 16 16:58:39 2013 +0200
@@ -16,7 +16,9 @@
 		unsafe internal static extern bool DeviceIoControl(SafeHandle hDevice, int IoControlCode, IntPtr InBuffer, int nInBufferSize, IntPtr OutBuffer, int nOutBufferSize, out int pBytesReturned, NativeOverlapped* Overlapped);
 		[DllImport("kernel32.dll", SetLastError = true)]
 		unsafe internal static extern bool DeviceIoControl(SafeHandle hDevice, int IoControlCode, void* InBuffer, int nInBufferSize, void* OutBuffer, int nOutBufferSize, out int pBytesReturned, NativeOverlapped* Overlapped);
-		[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
+		[DllImport("kernel32.dll", SetLastError = true)]
+		unsafe internal static extern bool DeviceIoControl(SafeHandle hDevice, int IoControlCode, Byte[] InBuffer, int nInBufferSize, Byte[] OutBuffer, int nOutBufferSize, out int pBytesReturned, IntPtr Overlapped);
+		[DllImport("kernel32.dll", SetLastError = true)]
 		unsafe internal static extern bool GetOverlappedResult(SafeHandle hFile, NativeOverlapped* lpOverlapped, out int lpNumberOfBytesTransferred, Boolean bWait);
 
 		[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
--- a/USBLib/Windows/USB/UsbDevice.cs	Wed Oct 16 01:11:49 2013 +0200
+++ b/USBLib/Windows/USB/UsbDevice.cs	Wed Oct 16 16:58:39 2013 +0200
@@ -141,8 +141,14 @@
 				int nBytes = length + szRequest;
 				Byte[] bigbuffer = new Byte[nBytes];
 				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)) {
+					if (descriptorType == (Byte)UsbDescriptorType.Device && index == 0 && langId == 0) {
+						Byte[] descbytes = DeviceDescriptor.GetBytes();
+						length = Math.Min(descbytes.Length, length);
+						Array.Copy(descbytes, 0, buffer, 0, length);
+						return length;
+					}
 					int err = Marshal.GetLastWin32Error();
-					if (err != 2 && err != 31 && err != 87) throw new Win32Exception(err);
+					if (err != 31) throw new Win32Exception(err);
 					return 0;
 				}
 				nBytes -= szRequest;
--- a/USBLib/Windows/USB/UsbHub.cs	Wed Oct 16 01:11:49 2013 +0200
+++ b/USBLib/Windows/USB/UsbHub.cs	Wed Oct 16 16:58:39 2013 +0200
@@ -4,6 +4,7 @@
 using System.Runtime.InteropServices;
 using Microsoft.Win32.SafeHandles;
 using UCIS.HWLib.Windows.Devices;
+using UCIS.USBLib.Descriptor;
 using UCIS.USBLib.Internal.Windows;
 
 namespace UCIS.HWLib.Windows.USB {
@@ -59,7 +60,7 @@
 						UsbDevice device;
 						if (nodeConnection.ConnectionStatus != USB_CONNECTION_STATUS.DeviceConnected) {
 							device = new UsbDevice(null, this, index);
-						} else if (nodeConnection.DeviceDescriptor.DeviceClass == (Byte)UsbDeviceClass.HubDevice) {
+						} else if (nodeConnection.DeviceDescriptor.DeviceClass == UsbClassCode.Hub) {
 							int nBytes = Marshal.SizeOf(typeof(USB_NODE_CONNECTION_NAME));
 							USB_NODE_CONNECTION_NAME nameConnection = new USB_NODE_CONNECTION_NAME();
 							nameConnection.ConnectionIndex = index;