# HG changeset patch # User Ivo Smits # Date 1381935519 -7200 # Node ID e811297f5aa48e436cd0ffb9f9f8e07344d7ce06 # Parent 2d16447eff12354705d3a421bd6ecfe5a1184c8c Updated USBLib: removed old LibUsbDotNet compatibility code and added new information helper classes diff -r 2d16447eff12 -r e811297f5aa4 UCIS.Core.csproj --- 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 @@ - - + @@ -157,6 +156,7 @@ + diff -r 2d16447eff12 -r e811297f5aa4 USBLib/Communication/LibUsbDotNet.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 AllDevices { - get { - List list = new List(); - 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 Configs { - get { - List rtnConfigs = new List(); - 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 rawDescriptorList = new List(); - 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 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 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 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 mInterfaceList = new List(); - internal readonly UsbConfigurationDescriptor mUsbConfigDescriptor; - internal UsbDevice mUsbDevice; - internal UsbConfigInfo(UsbDevice usbDevice, UsbConfigurationDescriptor descriptor, IEnumerable 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 InterfaceInfoList { get { return mInterfaceList.AsReadOnly(); } } - } - public class UsbInterfaceInfo { - internal readonly UsbInterfaceDescriptor mUsbInterfaceDescriptor; - internal UsbDevice mUsbDevice; - internal List mEndpointInfo = new List(); - internal UsbInterfaceInfo(UsbDevice usbDevice, byte[] descriptor) { - mUsbDevice = usbDevice; - mUsbInterfaceDescriptor = UsbInterfaceDescriptor.FromByteArray(descriptor, 0, descriptor.Length); - } - public UsbInterfaceDescriptor Descriptor { get { return mUsbInterfaceDescriptor; } } - public ReadOnlyCollection 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 - } -} diff -r 2d16447eff12 -r e811297f5aa4 USBLib/Communication/USBIO/USBIODevice.cs --- 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 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"); } } diff -r 2d16447eff12 -r e811297f5aa4 USBLib/Communication/UsbDescriptorType.cs --- 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 { - /// - /// Device descriptor type. - /// - Device = 1, - /// - /// Configuration descriptor type. - /// - Configuration = 2, - /// - /// String descriptor type. - /// - String = 3, - /// - /// Interface descriptor type. - /// - Interface = 4, - /// - /// Endpoint descriptor type. - /// - Endpoint = 5, - /// - /// Device Qualifier descriptor type. - /// - DeviceQualifier = 6, - /// - /// Other Speed Configuration descriptor type. - /// - OtherSpeedConfiguration = 7, - /// - /// Interface Power descriptor type. - /// - InterfacePower = 8, - /// - /// OTG descriptor type. - /// - OTG = 9, - /// - /// Debug descriptor type. - /// - Debug = 10, - /// - /// Interface Association descriptor type. - /// - InterfaceAssociation = 11, - - /// HID descriptor - Hid = 0x21, - - /// HID report descriptor - HidReport = 0x22, - - /// Physical descriptor - Physical = 0x23, - - /// Hub descriptor - Hub = 0x29 - } -} \ No newline at end of file diff -r 2d16447eff12 -r e811297f5aa4 USBLib/Communication/WinUsb/WinUsbDevice.cs --- 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; } } } diff -r 2d16447eff12 -r e811297f5aa4 USBLib/Descriptor/UsbDescriptor.cs --- 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 data) : this() { this.Data = data; } + public UsbDescriptorBlob(Byte[] data) : this() { this.Data = new ArraySegment(data); } + public UsbDescriptorBlob(Byte[] data, int offset) : this() { this.Data = new ArraySegment(data, offset, data[offset + 0]); } + public ArraySegment 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 { diff -r 2d16447eff12 -r e811297f5aa4 USBLib/Descriptor/UsbDescriptorType.cs --- /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 { + /// + /// Device descriptor type. + /// + Device = 1, + /// + /// Configuration descriptor type. + /// + Configuration = 2, + /// + /// String descriptor type. + /// + String = 3, + /// + /// Interface descriptor type. + /// + Interface = 4, + /// + /// Endpoint descriptor type. + /// + Endpoint = 5, + /// + /// Device Qualifier descriptor type. + /// + DeviceQualifier = 6, + /// + /// Other Speed Configuration descriptor type. + /// + OtherSpeedConfiguration = 7, + /// + /// Interface Power descriptor type. + /// + InterfacePower = 8, + /// + /// OTG descriptor type. + /// + OTG = 9, + /// + /// Debug descriptor type. + /// + Debug = 10, + /// + /// Interface Association descriptor type. + /// + InterfaceAssociation = 11, + + /// HID descriptor + Hid = 0x21, + + /// HID report descriptor + HidReport = 0x22, + + /// Physical descriptor + Physical = 0x23, + + /// Hub descriptor + 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 diff -r 2d16447eff12 -r e811297f5aa4 USBLib/Descriptor/UsbInfo.cs --- /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 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 descriptors = new List(); + 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 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 Interfaces { get { GetInterfaces(); return mInterfaces; } } + public UsbInterfaceInfo FindInterface(Predicate 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 Endpoints { + get { + return Array.ConvertAll(FindDescriptors(UsbDescriptorType.Endpoint), delegate(UsbDescriptorBlob descriptor) { return (UsbEndpointDescriptor)descriptor; }); + } + } + public UsbEndpointDescriptor FindEndpoint(Predicate 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; }); + } + } +} diff -r 2d16447eff12 -r e811297f5aa4 USBLib/Internal/Windows/UsbApi.cs --- 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, diff -r 2d16447eff12 -r e811297f5aa4 USBLib/Internal/Windows/Win32Kernel.cs --- 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)] diff -r 2d16447eff12 -r e811297f5aa4 USBLib/Windows/USB/UsbDevice.cs --- 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; diff -r 2d16447eff12 -r e811297f5aa4 USBLib/Windows/USB/UsbHub.cs --- 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;