Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/hakchi2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2017-03-05 14:38:01 +0300
committerAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2017-03-05 14:40:12 +0300
commitd1fb6c4ab4e259a8082a2c24e28538351880d0fc (patch)
tree4fa7a422ab71de2ab1a8a6603c80e714a2d57ea5 /LibWinUsb
parent8aee67b69c23a11ebdac6858466bf3bec8cd6b27 (diff)
USB library changed to LibWinUsb, it's more portable
Diffstat (limited to 'LibWinUsb')
-rw-r--r--LibWinUsb/Descriptors/ClassCodeType.cs60
-rw-r--r--LibWinUsb/Descriptors/DescriptorType.cs89
-rw-r--r--LibWinUsb/Descriptors/LangStringDescriptor.cs131
-rw-r--r--LibWinUsb/Descriptors/StringDescriptor.cs24
-rw-r--r--LibWinUsb/Descriptors/UsbConfigDescriptor.cs113
-rw-r--r--LibWinUsb/Descriptors/UsbDescriptor.cs73
-rw-r--r--LibWinUsb/Descriptors/UsbDeviceDescriptor.cs232
-rw-r--r--LibWinUsb/Descriptors/UsbEndpointDescriptor.cs134
-rw-r--r--LibWinUsb/Descriptors/UsbInterfaceDescriptor.cs126
-rw-r--r--LibWinUsb/DeviceNotify/DeviceNotifier.cs48
-rw-r--r--LibWinUsb/DeviceNotify/DeviceNotifyEventArgs.cs112
-rw-r--r--LibWinUsb/DeviceNotify/DeviceType.cs58
-rw-r--r--LibWinUsb/DeviceNotify/EventType.cs58
-rw-r--r--LibWinUsb/DeviceNotify/IDeviceNotifier.cs52
-rw-r--r--LibWinUsb/DeviceNotify/Info/IPortNotifyInfo.cs43
-rw-r--r--LibWinUsb/DeviceNotify/Info/IUsbDeviceNotifyInfo.cs70
-rw-r--r--LibWinUsb/DeviceNotify/Info/IVolumeNotifyInfo.cs63
-rw-r--r--LibWinUsb/DeviceNotify/Info/PortNotifyInfo.cs63
-rw-r--r--LibWinUsb/DeviceNotify/Info/UsbDeviceNotifyInfo.cs112
-rw-r--r--LibWinUsb/DeviceNotify/Info/VolumeNotifyInfo.cs114
-rw-r--r--LibWinUsb/DeviceNotify/Internal/DevBroadcastDeviceinterface.cs44
-rw-r--r--LibWinUsb/DeviceNotify/Internal/DevBroadcastHdr.cs35
-rw-r--r--LibWinUsb/DeviceNotify/Internal/DevBroadcastPort.cs39
-rw-r--r--LibWinUsb/DeviceNotify/Internal/DevBroadcastVolume.cs38
-rw-r--r--LibWinUsb/DeviceNotify/Internal/DevNotifyNativeWindow.cs79
-rw-r--r--LibWinUsb/DeviceNotify/Internal/SafeNotifyHandle.cs45
-rw-r--r--LibWinUsb/DeviceNotify/Linux/LinuxDevItem.cs90
-rw-r--r--LibWinUsb/DeviceNotify/Linux/LinuxDevItemList.cs36
-rw-r--r--LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifier.DevMonitor.cs187
-rw-r--r--LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifier.DeviceListPolling.cs99
-rw-r--r--LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifier.cs139
-rw-r--r--LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifierMode.cs44
-rw-r--r--LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifyEventArgs.cs70
-rw-r--r--LibWinUsb/DeviceNotify/Linux/LinuxUsbDeviceNotifyInfo.cs127
-rw-r--r--LibWinUsb/DeviceNotify/WindowsDeviceNotifier.cs146
-rw-r--r--LibWinUsb/DeviceNotify/WindowsDeviceNotifyEventArgs.cs57
-rw-r--r--LibWinUsb/IUsbDevice.cs100
-rw-r--r--LibWinUsb/IUsbInterface.cs187
-rw-r--r--LibWinUsb/Info/UsbBaseInfo.cs44
-rw-r--r--LibWinUsb/Info/UsbConfigInfo.cs158
-rw-r--r--LibWinUsb/Info/UsbDeviceInfo.cs215
-rw-r--r--LibWinUsb/Info/UsbEndpointInfo.cs70
-rw-r--r--LibWinUsb/Info/UsbInterfaceInfo.cs120
-rw-r--r--LibWinUsb/Internal/Kernel32.cs197
-rw-r--r--LibWinUsb/Internal/OverlappedTransferContext.cs113
-rw-r--r--LibWinUsb/Internal/SafeOverlapped.cs115
-rw-r--r--LibWinUsb/Internal/SetupApi.cs670
-rw-r--r--LibWinUsb/Internal/TransferContextBase.cs195
-rw-r--r--LibWinUsb/Internal/UsbApiBase.cs81
-rw-r--r--LibWinUsb/Internal/UsbRegex/BaseRegSymbolicName.cs37
-rw-r--r--LibWinUsb/Internal/UsbRegex/NamedGroup.cs35
-rw-r--r--LibWinUsb/Internal/UsbRegex/RegHardwareID.cs105
-rw-r--r--LibWinUsb/Internal/UsbRegex/RegSymbolicName.cs95
-rw-r--r--LibWinUsb/LibUsb/Internal/LibUsbAPI.cs151
-rw-r--r--LibWinUsb/LibUsb/Internal/LibUsbDriverIO.cs100
-rw-r--r--LibWinUsb/LibUsb/Internal/LibUsbDriverIO_IOControlMessage.cs199
-rw-r--r--LibWinUsb/LibUsb/Internal/LibUsbIoCtl.cs65
-rw-r--r--LibWinUsb/LibUsb/Internal/LibUsbRequest.cs195
-rw-r--r--LibWinUsb/LibUsb/LibUsbDevice.cs320
-rw-r--r--LibWinUsb/LibUsb/LibUsbDeviceRegistryKeyRequest.cs116
-rw-r--r--LibWinUsb/LibUsb/LibUsbKernelType.cs46
-rw-r--r--LibWinUsb/LibUsb/LibUsbRegistry.cs321
-rw-r--r--LibWinUsb/Main/ControlEpLockType.cs54
-rw-r--r--LibWinUsb/Main/DataEpLockType.cs44
-rw-r--r--LibWinUsb/Main/DataReceivedEnabledChangedEventArgs.cs59
-rw-r--r--LibWinUsb/Main/DeviceLockType.cs48
-rw-r--r--LibWinUsb/Main/DevicePropertyType.cs101
-rw-r--r--LibWinUsb/Main/EndpointDataEventArgs.cs58
-rw-r--r--LibWinUsb/Main/EndpointType.cs48
-rw-r--r--LibWinUsb/Main/ErrorCode.cs184
-rw-r--r--LibWinUsb/Main/Helper.cs283
-rw-r--r--LibWinUsb/Main/LegacyUsbRegistry.cs245
-rw-r--r--LibWinUsb/Main/ReadEndpointID.cs90
-rw-r--r--LibWinUsb/Main/SPDRP.cs110
-rw-r--r--LibWinUsb/Main/SafeContextHandle.cs65
-rw-r--r--LibWinUsb/Main/SetupApiRegistry.cs210
-rw-r--r--LibWinUsb/Main/UsbConstants.cs66
-rw-r--r--LibWinUsb/Main/UsbCtrlFlags.cs73
-rw-r--r--LibWinUsb/Main/UsbDeviceFinder.cs319
-rw-r--r--LibWinUsb/Main/UsbEndpointBase.cs391
-rw-r--r--LibWinUsb/Main/UsbEndpointDirection.cs40
-rw-r--r--LibWinUsb/Main/UsbEndpointList.cs147
-rw-r--r--LibWinUsb/Main/UsbException.cs46
-rw-r--r--LibWinUsb/Main/UsbKernelVersion.cs91
-rw-r--r--LibWinUsb/Main/UsbLockStyle.cs146
-rw-r--r--LibWinUsb/Main/UsbRegDeviceList.cs179
-rw-r--r--LibWinUsb/Main/UsbRegistry.cs332
-rw-r--r--LibWinUsb/Main/UsbRequestRecipient.cs48
-rw-r--r--LibWinUsb/Main/UsbRequestType.cs50
-rw-r--r--LibWinUsb/Main/UsbSetupPacket.cs95
-rw-r--r--LibWinUsb/Main/UsbStandardRequest.cs78
-rw-r--r--LibWinUsb/Main/UsbStatusClodes.cs31
-rw-r--r--LibWinUsb/Main/UsbStream.cs286
-rw-r--r--LibWinUsb/Main/UsbSymbolicName.cs227
-rw-r--r--LibWinUsb/Main/UsbTransfer.cs629
-rw-r--r--LibWinUsb/Main/WriteEndpointID.cs89
-rw-r--r--LibWinUsb/MonoLibUsb/CallbackDelegates.cs31
-rw-r--r--LibWinUsb/MonoLibUsb/Descriptors/MonoUsbAltInterfaceDescriptor.cs103
-rw-r--r--LibWinUsb/MonoLibUsb/Descriptors/MonoUsbConfigDescriptor.cs115
-rw-r--r--LibWinUsb/MonoLibUsb/Descriptors/MonoUsbDeviceDescriptor.cs134
-rw-r--r--LibWinUsb/MonoLibUsb/Descriptors/MonoUsbEndpointDescriptor.cs77
-rw-r--r--LibWinUsb/MonoLibUsb/Descriptors/MonoUsbInterface.cs59
-rw-r--r--LibWinUsb/MonoLibUsb/MonoLibUsbApi.cs1470
-rw-r--r--LibWinUsb/MonoLibUsb/MonoUsbDevice.cs522
-rw-r--r--LibWinUsb/MonoLibUsb/MonoUsbDeviceHandle.cs136
-rw-r--r--LibWinUsb/MonoLibUsb/MonoUsbEndpointReader.cs81
-rw-r--r--LibWinUsb/MonoLibUsb/MonoUsbEndpointWriter.cs76
-rw-r--r--LibWinUsb/MonoLibUsb/MonoUsbError.cs106
-rw-r--r--LibWinUsb/MonoLibUsb/MonoUsbEventHandler.cs192
-rw-r--r--LibWinUsb/MonoLibUsb/MonoUsbSessionHandle.cs116
-rw-r--r--LibWinUsb/MonoLibUsb/Profile/AddRemoveEventArgs.cs34
-rw-r--r--LibWinUsb/MonoLibUsb/Profile/AddRemoveType.cs38
-rw-r--r--LibWinUsb/MonoLibUsb/Profile/MonoUsbConfigHandle.cs41
-rw-r--r--LibWinUsb/MonoLibUsb/Profile/MonoUsbProfile.cs186
-rw-r--r--LibWinUsb/MonoLibUsb/Profile/MonoUsbProfileHandle.cs110
-rw-r--r--LibWinUsb/MonoLibUsb/Profile/MonoUsbProfileHandleEnumerator.cs111
-rw-r--r--LibWinUsb/MonoLibUsb/Profile/MonoUsbProfileList.cs259
-rw-r--r--LibWinUsb/MonoLibUsb/Profile/MonoUsbProfileListHandle.cs74
-rw-r--r--LibWinUsb/MonoLibUsb/Profile/PollfdItem.cs28
-rw-r--r--LibWinUsb/MonoLibUsb/Transfer/Internal/libusb_control_setup.cs35
-rw-r--r--LibWinUsb/MonoLibUsb/Transfer/Internal/libusb_iso_packet_descriptor.cs29
-rw-r--r--LibWinUsb/MonoLibUsb/Transfer/Internal/libusb_transfer.cs52
-rw-r--r--LibWinUsb/MonoLibUsb/Transfer/MonoUsbControlSetup.cs145
-rw-r--r--LibWinUsb/MonoLibUsb/Transfer/MonoUsbControlSetupHandle.cs113
-rw-r--r--LibWinUsb/MonoLibUsb/Transfer/MonoUsbIsoPacket.cs58
-rw-r--r--LibWinUsb/MonoLibUsb/Transfer/MonoUsbTansferStatus.cs65
-rw-r--r--LibWinUsb/MonoLibUsb/Transfer/MonoUsbTransfer.cs519
-rw-r--r--LibWinUsb/MonoLibUsb/Transfer/MonoUsbTransferContext.cs232
-rw-r--r--LibWinUsb/MonoLibUsb/Transfer/MonoUsbTransferFlags.cs51
-rw-r--r--LibWinUsb/MonoLibUsb/UnixNativeTimeval.cs69
-rw-r--r--LibWinUsb/UsbDevice.Common.cs249
-rw-r--r--LibWinUsb/UsbDevice.Error.cs166
-rw-r--r--LibWinUsb/UsbDevice.OS.Specific.cs291
-rw-r--r--LibWinUsb/UsbDevice.cs495
-rw-r--r--LibWinUsb/UsbEndpointReader.cs290
-rw-r--r--LibWinUsb/UsbEndpointWriter.cs100
-rw-r--r--LibWinUsb/UsbGlobals.cs34
-rw-r--r--LibWinUsb/WinUsb/DeviceInformationTypes.cs33
-rw-r--r--LibWinUsb/WinUsb/DeviceSpeedTypes.cs45
-rw-r--r--LibWinUsb/WinUsb/Internal/SafeWinUsbInterfaceHandle.cs67
-rw-r--r--LibWinUsb/WinUsb/Internal/WinUsbAPI.cs226
-rw-r--r--LibWinUsb/WinUsb/PipeInformation.cs57
-rw-r--r--LibWinUsb/WinUsb/PipePolicies.cs288
-rw-r--r--LibWinUsb/WinUsb/PipePolicyType.cs35
-rw-r--r--LibWinUsb/WinUsb/PowerPolicies.cs98
-rw-r--r--LibWinUsb/WinUsb/PowerPolicyType.cs30
-rw-r--r--LibWinUsb/WinUsb/WinUsbDevice.cs317
-rw-r--r--LibWinUsb/WinUsb/WinUsbRegistry.cs518
148 files changed, 20868 insertions, 0 deletions
diff --git a/LibWinUsb/Descriptors/ClassCodeType.cs b/LibWinUsb/Descriptors/ClassCodeType.cs
new file mode 100644
index 00000000..87a5129e
--- /dev/null
+++ b/LibWinUsb/Descriptors/ClassCodeType.cs
@@ -0,0 +1,60 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+
+namespace LibUsbDotNet.Descriptors
+{
+ ///<summary> Device and/or Interface Class codes</summary>
+ [Flags]
+ public enum ClassCodeType : byte
+ {
+ ///<summary>In the context of a "device descriptor", this bDeviceClass value indicates that each interface specifies its own class information and all interfaces operate independently.</summary>
+ PerInterface = 0,
+
+ ///<summary>Audio class</summary>
+ Audio = 1,
+
+ ///<summary> Communications class</summary>
+ Comm = 2,
+
+ ///<summary> Human Interface Device class</summary>
+ Hid = 3,
+
+ ///<summary> Printer dclass</summary>
+ Printer = 7,
+
+ ///<summary> Picture transfer protocol class</summary>
+ Ptp = 6,
+
+ ///<summary> Mass storage class</summary>
+ MassStorage = 8,
+
+ ///<summary> Hub class</summary>
+ Hub = 9,
+
+ ///<summary> Data class</summary>
+ Data = 10,
+
+ ///<summary> Class is vendor-specific</summary>
+ VendorSpec = 0xff
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Descriptors/DescriptorType.cs b/LibWinUsb/Descriptors/DescriptorType.cs
new file mode 100644
index 00000000..f91bda53
--- /dev/null
+++ b/LibWinUsb/Descriptors/DescriptorType.cs
@@ -0,0 +1,89 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+
+using System;
+
+namespace LibUsbDotNet.Descriptors
+{
+ /// <summary> Standard USB descriptor types.
+ /// </summary>
+ [Flags]
+ public enum DescriptorType : 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
diff --git a/LibWinUsb/Descriptors/LangStringDescriptor.cs b/LibWinUsb/Descriptors/LangStringDescriptor.cs
new file mode 100644
index 00000000..3f3d384d
--- /dev/null
+++ b/LibWinUsb/Descriptors/LangStringDescriptor.cs
@@ -0,0 +1,131 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace LibUsbDotNet.Descriptors
+{
+ internal abstract class UsbMemChunk
+ {
+ private readonly int mMaxSize;
+
+ private IntPtr mMemPointer = IntPtr.Zero;
+
+ protected UsbMemChunk(int maxSize)
+ {
+ mMaxSize = maxSize;
+ mMemPointer = Marshal.AllocHGlobal(maxSize);
+ }
+
+ public int MaxSize
+ {
+ get { return mMaxSize; }
+ }
+
+ public IntPtr Ptr
+ {
+ get { return mMemPointer; }
+ }
+
+ public void Free()
+ {
+ if (mMemPointer != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(mMemPointer);
+ mMemPointer = IntPtr.Zero;
+ }
+ }
+
+ ~UsbMemChunk() { Free(); }
+ }
+
+ internal class LangStringDescriptor : UsbMemChunk
+ {
+ #region FIELD_OFFSETS
+
+ private static readonly int OfsDescriptorType = Marshal.OffsetOf(typeof (UsbDescriptor), "DescriptorType").ToInt32();
+ private static readonly int OfsLength = Marshal.OffsetOf(typeof (UsbDescriptor), "Length").ToInt32();
+
+ #endregion
+
+ public LangStringDescriptor(int maxSize)
+ : base(maxSize) { }
+
+ public DescriptorType DescriptorType
+ {
+ get { return (DescriptorType) Marshal.ReadByte(Ptr, OfsDescriptorType); }
+ set { Marshal.WriteByte(Ptr, OfsDescriptorType, (byte) value); }
+ }
+
+ public byte Length
+ {
+ get { return Marshal.ReadByte(Ptr, OfsLength); }
+ set { Marshal.WriteByte(Ptr, OfsLength, value); }
+ }
+
+ public bool Get(out short[] langIds)
+ {
+ langIds = new short[0];
+ int totalLength = Length;
+ if (totalLength <= 2) return false;
+
+ int elementCount = (totalLength - 2)/2;
+ langIds = new short[elementCount];
+
+ int startOffset = UsbDescriptor.Size;
+ for (int iElement = 0; iElement < langIds.Length; iElement++)
+ {
+ langIds[iElement] = Marshal.ReadInt16(Ptr, startOffset + (sizeof (ushort)*iElement));
+ }
+ return true;
+ }
+
+ public bool Get(out byte[] bytes)
+ {
+ bytes = new byte[Length];
+ Marshal.Copy(Ptr, bytes, 0, bytes.Length);
+ return true;
+ }
+
+ public bool Get(out string str)
+ {
+ str = string.Empty;
+
+ byte[] bytes;
+ if (Get(out bytes))
+ {
+ if (bytes.Length <= UsbDescriptor.Size)
+ {
+ str = string.Empty;
+ }
+ else
+ {
+ str = Encoding.Unicode.GetString(bytes, UsbDescriptor.Size, bytes.Length - UsbDescriptor.Size);
+ }
+ return true;
+ }
+
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Descriptors/StringDescriptor.cs b/LibWinUsb/Descriptors/StringDescriptor.cs
new file mode 100644
index 00000000..282f1f97
--- /dev/null
+++ b/LibWinUsb/Descriptors/StringDescriptor.cs
@@ -0,0 +1,24 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.Descriptors
+{
+} \ No newline at end of file
diff --git a/LibWinUsb/Descriptors/UsbConfigDescriptor.cs b/LibWinUsb/Descriptors/UsbConfigDescriptor.cs
new file mode 100644
index 00000000..423b9458
--- /dev/null
+++ b/LibWinUsb/Descriptors/UsbConfigDescriptor.cs
@@ -0,0 +1,113 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Main;
+using MonoLibUsb.Descriptors;
+
+#pragma warning disable 649
+
+namespace LibUsbDotNet.Descriptors
+{
+ /// <summary> Usb Configuration Descriptor.
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public class UsbConfigDescriptor : UsbDescriptor
+ {
+ /// <summary>
+ /// Total size of this structure in bytes.
+ /// </summary>
+ public new static readonly int Size = Marshal.SizeOf(typeof (UsbConfigDescriptor));
+
+ /// <summary>
+ /// Total length in bytes of data returned
+ /// </summary>
+ public readonly short TotalLength;
+
+ /// <summary>
+ /// Number of Interfaces
+ /// </summary>
+ public readonly byte InterfaceCount;
+
+ /// <summary>
+ /// Value to use as an argument to select this Configuration
+ /// </summary>
+ public readonly byte ConfigID;
+
+ /// <summary>
+ /// Index of String Descriptor describing this Configuration
+ /// </summary>
+ public readonly byte StringIndex;
+
+ /// <summary>
+ /// D7 Reserved, set to 1. (USB 1.0 Bus Powered)
+ /// D6 Self Powered
+ /// D5 Remote Wakeup
+ /// D4..0 Reserved, set to 0.
+ /// </summary>
+ public readonly byte Attributes;
+
+ /// <summary>
+ /// Maximum Power Consumption in 2mA units
+ /// </summary>
+ public readonly byte MaxPower;
+
+ internal UsbConfigDescriptor(MonoUsbConfigDescriptor descriptor)
+ {
+ Attributes = descriptor.bmAttributes;
+ ConfigID = descriptor.bConfigurationValue;
+ DescriptorType = descriptor.bDescriptorType;
+ InterfaceCount = descriptor.bNumInterfaces;
+ Length = descriptor.bLength;
+ MaxPower = descriptor.MaxPower;
+ StringIndex = descriptor.iConfiguration;
+ TotalLength = (short) descriptor.wTotalLength;
+ }
+
+ internal UsbConfigDescriptor() { }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbConfigDescriptor"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="UsbConfigDescriptor"/>.
+ ///</returns>
+ public override string ToString() { return ToString("", ToStringParamValueSeperator, ToStringFieldSeperator); }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbConfigDescriptor"/>.
+ ///</summary>
+ ///
+ ///<param name="prefixSeperator">The field prefix string.</param>
+ ///<param name="entitySperator">The field/value seperator string.</param>
+ ///<param name="suffixSeperator">The value suffix string.</param>
+ ///<returns>A formatted representation of the <see cref="UsbConfigDescriptor"/>.</returns>
+ public string ToString(string prefixSeperator, string entitySperator, string suffixSeperator)
+ {
+ Object[] values = {Length, DescriptorType, TotalLength, InterfaceCount, ConfigID, StringIndex, "0x" + Attributes.ToString("X2"), MaxPower};
+ string[] names = {"Length", "DescriptorType", "TotalLength", "InterfaceCount", "ConfigID", "StringIndex", "Attributes", "MaxPower"};
+
+ return Helper.ToString(prefixSeperator, names, entitySperator, values, suffixSeperator);
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Descriptors/UsbDescriptor.cs b/LibWinUsb/Descriptors/UsbDescriptor.cs
new file mode 100644
index 00000000..7135ad65
--- /dev/null
+++ b/LibWinUsb/Descriptors/UsbDescriptor.cs
@@ -0,0 +1,73 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Main;
+
+#pragma warning disable 649
+
+namespace LibUsbDotNet.Descriptors
+{
+ /// <summary> Base class for all usb descriptors structures.
+ /// </summary>
+ /// <remarks> This is the actual descriptor as described in the USB 2.0 Specifications.
+ /// </remarks>
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public abstract class UsbDescriptor
+ {
+ /// <summary>
+ /// String value used to seperate the name/value pairs for all ToString overloads of the descriptor classes.
+ /// </summary>
+ public static string ToStringParamValueSeperator = ":";
+
+ /// <summary>
+ /// String value used to seperate the name/value groups for all ToString overloads of the descriptor classes.
+ /// </summary>
+ public static string ToStringFieldSeperator = "\r\n";
+
+ /// <summary>
+ /// Total size of this structure in bytes.
+ /// </summary>
+ public static readonly int Size = Marshal.SizeOf(typeof (UsbDescriptor));
+
+ /// <summary>
+ /// Length of structure reported by the associated usb device.
+ /// </summary>
+ public byte Length;
+
+ /// <summary>
+ /// Type of structure reported by the associated usb device.
+ /// </summary>
+ public DescriptorType DescriptorType;
+
+ /// <summary>
+ /// String representation of the UsbDescriptor class.
+ /// </summary>
+ public override string ToString()
+ {
+ Object[] values = {Length, DescriptorType};
+ string[] names = {"Length", "DescriptorType"};
+
+ return Helper.ToString("", names, ToStringParamValueSeperator, values, ToStringFieldSeperator);
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Descriptors/UsbDeviceDescriptor.cs b/LibWinUsb/Descriptors/UsbDeviceDescriptor.cs
new file mode 100644
index 00000000..f545ce13
--- /dev/null
+++ b/LibWinUsb/Descriptors/UsbDeviceDescriptor.cs
@@ -0,0 +1,232 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Main;
+using MonoLibUsb.Descriptors;
+
+#pragma warning disable 649
+
+namespace LibUsbDotNet.Descriptors
+{
+ /// <summary> Usb Device Descriptor
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public class UsbDeviceDescriptor : UsbDescriptor
+ {
+ /// <summary>
+ /// Total size of this structure in bytes.
+ /// </summary>
+ public new static readonly int Size = Marshal.SizeOf(typeof (UsbDeviceDescriptor));
+
+ /// <summary>
+ /// USB Specification Number which device complies too.
+ /// </summary>
+ public short BcdUsb;
+
+ /// <summary>
+ /// Class Code (Assigned by USB Org)
+ /// If equal to Zero, each interface specifies it’s own class code; If equal to 0xFF, the class code is vendor specified; Otherwise field is valid Class Code.
+ /// </summary>
+ public ClassCodeType Class;
+
+ /// <summary>
+ /// Subclass Code (Assigned by USB Org)
+ /// </summary>
+ public byte SubClass;
+
+ /// <summary>
+ /// Protocol Code (Assigned by USB Org)
+ /// </summary>
+ public byte Protocol;
+
+ /// <summary>
+ /// Maximum Packet Size for Zero Endpoint. Valid Sizes are 8, 16, 32, 64
+ /// </summary>
+ public byte MaxPacketSize0;
+
+ /// <summary>
+ /// Vendor ID (Assigned by USB Org)
+ /// </summary>
+ public short VendorID;
+
+ /// <summary>
+ /// Product ID (Assigned by Manufacturer)
+ /// </summary>
+ public short ProductID;
+
+ /// <summary>
+ /// Device Release Number
+ /// </summary>
+ public short BcdDevice;
+
+ /// <summary>
+ /// Index of Manufacturer String Descriptor
+ /// </summary>
+ public byte ManufacturerStringIndex;
+
+ /// <summary>
+ /// Index of Product String Descriptor
+ /// </summary>
+ public byte ProductStringIndex;
+
+ /// <summary>
+ /// Index of Serial Number String Descriptor
+ /// </summary>
+ public byte SerialStringIndex;
+
+ /// <summary>
+ /// Number of Possible Configurations
+ /// </summary>
+ public byte ConfigurationCount;
+
+ internal UsbDeviceDescriptor() { }
+
+ internal UsbDeviceDescriptor(MonoUsbDeviceDescriptor usbDeviceDescriptor)
+ {
+ BcdDevice = usbDeviceDescriptor.BcdDevice;
+ BcdUsb = usbDeviceDescriptor.BcdUsb;
+ Class = usbDeviceDescriptor.Class;
+ ConfigurationCount = usbDeviceDescriptor.ConfigurationCount;
+ DescriptorType = usbDeviceDescriptor.DescriptorType;
+ Length = usbDeviceDescriptor.Length;
+ ManufacturerStringIndex = usbDeviceDescriptor.ManufacturerStringIndex;
+ MaxPacketSize0 = usbDeviceDescriptor.MaxPacketSize0;
+ ProductID = usbDeviceDescriptor.ProductID;
+ ProductStringIndex = usbDeviceDescriptor.ProductStringIndex;
+ Protocol = usbDeviceDescriptor.Protocol;
+ SerialStringIndex = usbDeviceDescriptor.SerialStringIndex;
+ SubClass = usbDeviceDescriptor.SubClass;
+ VendorID = usbDeviceDescriptor.VendorID;
+ }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbDeviceDescriptor"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="UsbDeviceDescriptor"/>.
+ ///</returns>
+ public override string ToString() { return ToString("", ToStringParamValueSeperator, ToStringFieldSeperator); }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbDeviceDescriptor"/>.
+ ///</summary>
+ ///
+ ///<param name="prefixSeperator">The field prefix string.</param>
+ ///<param name="entitySperator">The field/value seperator string.</param>
+ ///<param name="suffixSeperator">The value suffix string.</param>
+ ///<returns>A formatted representation of the <see cref="UsbDeviceDescriptor"/>.</returns>
+ public string ToString(string prefixSeperator, string entitySperator, string suffixSeperator)
+ {
+ Object[] values = {
+ Length, DescriptorType, "0x" + BcdUsb.ToString("X4"), Class, "0x" + SubClass.ToString("X2"),
+ "0x" + Protocol.ToString("X2"), MaxPacketSize0,
+ "0x" + VendorID.ToString("X4"), "0x" + ProductID.ToString("X4"), "0x" + BcdDevice.ToString("X4"),
+ ManufacturerStringIndex, ProductStringIndex, SerialStringIndex, ConfigurationCount
+ };
+ string[] names = {
+ "Length", "DescriptorType", "BcdUsb", "Class", "SubClass", "Protocol", "MaxPacketSize0", "VendorID", "ProductID",
+ "BcdDevice",
+ "ManufacturerStringIndex", "ProductStringIndex", "SerialStringIndex", "ConfigurationCount"
+ };
+
+ return Helper.ToString(prefixSeperator, names, entitySperator, values, suffixSeperator);
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="UsbDeviceDescriptor"/> is equal to the current <see cref="UsbDeviceDescriptor"/>.
+ /// </summary>
+ /// <returns>
+ /// true if the specified <see cref="UsbDeviceDescriptor"/> is equal to the current <see cref="UsbDeviceDescriptor"/>; otherwise, false.
+ /// </returns>
+ /// <param name="other">The <see cref="UsbDeviceDescriptor"/> to compare with the current <see cref="UsbDeviceDescriptor"/>. </param><exception cref="T:System.NullReferenceException">The <paramref name="other"/> parameter is null.</exception><filterpriority>2</filterpriority>
+ public bool Equals(UsbDeviceDescriptor other)
+ {
+ if (ReferenceEquals(null, other)) return false;
+ if (ReferenceEquals(this, other)) return true;
+ return other.BcdUsb == BcdUsb && other.Class == Class && other.SubClass == SubClass && other.Protocol == Protocol &&
+ other.MaxPacketSize0 == MaxPacketSize0 && other.VendorID == VendorID && other.ProductID == ProductID &&
+ other.BcdDevice == BcdDevice && other.ManufacturerStringIndex == ManufacturerStringIndex &&
+ other.ProductStringIndex == ProductStringIndex && other.SerialStringIndex == SerialStringIndex &&
+ other.ConfigurationCount == ConfigurationCount;
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
+ /// </summary>
+ /// <returns>
+ /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
+ /// </returns>
+ /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>. </param><exception cref="T:System.NullReferenceException">The <paramref name="obj"/> parameter is null.</exception><filterpriority>2</filterpriority>
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != typeof (UsbDeviceDescriptor)) return false;
+ return Equals((UsbDeviceDescriptor) obj);
+ }
+
+ /// <summary>
+ /// Serves as a hash function for a particular type.
+ /// </summary>
+ /// <returns>
+ /// A hash code for the current <see cref="T:System.Object"/>.
+ /// </returns>
+ /// <filterpriority>2</filterpriority>
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int result = BcdUsb.GetHashCode();
+ result = (result*397) ^ Class.GetHashCode();
+ result = (result*397) ^ SubClass.GetHashCode();
+ result = (result*397) ^ Protocol.GetHashCode();
+ result = (result*397) ^ MaxPacketSize0.GetHashCode();
+ result = (result*397) ^ VendorID.GetHashCode();
+ result = (result*397) ^ ProductID.GetHashCode();
+ result = (result*397) ^ BcdDevice.GetHashCode();
+ result = (result*397) ^ ManufacturerStringIndex.GetHashCode();
+ result = (result*397) ^ ProductStringIndex.GetHashCode();
+ result = (result*397) ^ SerialStringIndex.GetHashCode();
+ result = (result*397) ^ ConfigurationCount.GetHashCode();
+ return result;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="left"></param>
+ /// <param name="right"></param>
+ /// <returns></returns>
+ public static bool operator ==(UsbDeviceDescriptor left, UsbDeviceDescriptor right) { return Equals(left, right); }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="left"></param>
+ /// <param name="right"></param>
+ /// <returns></returns>
+ public static bool operator !=(UsbDeviceDescriptor left, UsbDeviceDescriptor right) { return !Equals(left, right); }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Descriptors/UsbEndpointDescriptor.cs b/LibWinUsb/Descriptors/UsbEndpointDescriptor.cs
new file mode 100644
index 00000000..cc7f41a9
--- /dev/null
+++ b/LibWinUsb/Descriptors/UsbEndpointDescriptor.cs
@@ -0,0 +1,134 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Main;
+using MonoLibUsb.Descriptors;
+
+#pragma warning disable 649
+
+namespace LibUsbDotNet.Descriptors
+{
+ /// <summary> Usb Endpoint Descriptor
+ /// </summary>
+ /// <remarks> This is the actual descriptor as described in the USB 2.0 Specifications.
+ /// </remarks>
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public class UsbEndpointDescriptor : UsbDescriptor
+ {
+ /// <summary>
+ /// Total size of this structure in bytes.
+ /// </summary>
+ public new static readonly int Size = Marshal.SizeOf(typeof (UsbEndpointDescriptor));
+
+ /// <summary>
+ /// Endpoint Address
+ /// Bits 0..3b Endpoint Number.
+ /// Bits 4..6b Reserved. Set to Zero
+ /// Bits 7 Direction 0 = Out, 1 = In (Ignored for Control Endpoints)
+ /// </summary>
+ public readonly byte EndpointID;
+
+ /// <summary>
+ /// Bits 0..1 Transfer Type
+ /// 00 = Control
+ /// 01 = Isochronous
+ /// 10 = Bulk
+ /// 11 = Interrupt
+ ///
+ /// Bits 2..7 are reserved. If Isochronous endpoint,
+ /// Bits 3..2 = Synchronisation Type (Iso Mode)
+ /// 00 = No Synchonisation
+ /// 01 = Asynchronous
+ /// 10 = Adaptive
+ /// 11 = Synchronous
+ ///
+ /// Bits 5..4 = Usage Type (Iso Mode)
+ /// 00 = Data Endpoint
+ /// 01 = Feedback Endpoint
+ /// 10 = Explicit Feedback Data Endpoint
+ /// 11 = Reserved
+ /// </summary>
+ public readonly byte Attributes;
+
+ /// <summary>
+ /// Maximum Packet Size this endpoint is capable of sending or receiving
+ /// </summary>
+ public readonly short MaxPacketSize;
+
+ /// <summary>
+ /// Interval for polling endpoint data transfers. Value in frame counts. Ignored for Bulk and Control Endpoints. Isochronous must equal 1 and field may range from 1 to 255 for interrupt endpoints.
+ /// </summary>
+ public readonly byte Interval;
+
+ /// <summary>
+ /// Audio endpoint specific.
+ /// </summary>
+ public readonly byte Refresh;
+
+ /// <summary>
+ /// Audio endpoint specific.
+ /// </summary>
+ public readonly byte SynchAddress;
+
+ internal UsbEndpointDescriptor() { }
+
+ internal UsbEndpointDescriptor(MonoUsbEndpointDescriptor descriptor)
+ {
+ Attributes = descriptor.bmAttributes;
+ DescriptorType = descriptor.bDescriptorType;
+ EndpointID = descriptor.bEndpointAddress;
+ Interval = descriptor.bInterval;
+ Length = descriptor.bLength;
+ MaxPacketSize = (short) descriptor.wMaxPacketSize;
+ SynchAddress = descriptor.bSynchAddress;
+ }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbEndpointDescriptor"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="UsbEndpointDescriptor"/>.
+ ///</returns>
+ public override string ToString() { return ToString("", ToStringParamValueSeperator, ToStringFieldSeperator); }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbEndpointDescriptor"/>.
+ ///</summary>
+ ///
+ ///<param name="prefixSeperator">The field prefix string.</param>
+ ///<param name="entitySperator">The field/value seperator string.</param>
+ ///<param name="suffixSeperator">The value suffix string.</param>
+ ///<returns>A formatted representation of the <see cref="UsbEndpointDescriptor"/>.</returns>
+ public string ToString(string prefixSeperator, string entitySperator, string suffixSeperator)
+ {
+ Object[] values = {
+ Length, DescriptorType, "0x" + EndpointID.ToString("X2"), "0x" + Attributes.ToString("X2"), MaxPacketSize, Interval,
+ Refresh, "0x" + SynchAddress.ToString("X2")
+ };
+ string[] names = {"Length", "DescriptorType", "EndpointID", "Attributes", "MaxPacketSize", "Interval", "Refresh", "SynchAddress"};
+
+ return Helper.ToString(prefixSeperator, names, entitySperator, values, suffixSeperator);
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Descriptors/UsbInterfaceDescriptor.cs b/LibWinUsb/Descriptors/UsbInterfaceDescriptor.cs
new file mode 100644
index 00000000..66246020
--- /dev/null
+++ b/LibWinUsb/Descriptors/UsbInterfaceDescriptor.cs
@@ -0,0 +1,126 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Main;
+using MonoLibUsb.Descriptors;
+
+#pragma warning disable 649
+
+namespace LibUsbDotNet.Descriptors
+{
+ /// <summary> Usb Interface Descriptor.
+ /// </summary>
+ /// <remarks> This is the actual descriptor as described in the USB 2.0 Specifications.
+ /// </remarks>
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public class UsbInterfaceDescriptor : UsbDescriptor
+ {
+ /// <summary>
+ /// Total size of this structure in bytes.
+ /// </summary>
+ public new static readonly int Size = Marshal.SizeOf(typeof (UsbInterfaceDescriptor));
+
+ /// <summary>
+ /// Number of Interface
+ /// </summary>
+ public readonly byte InterfaceID;
+
+ /// <summary>
+ /// Value used to select alternative setting
+ /// </summary>
+ public readonly byte AlternateID;
+
+ /// <summary>
+ /// Number of Endpoints used for this interface
+ /// </summary>
+ public readonly byte EndpointCount;
+
+ /// <summary>
+ /// Class Code (Assigned by USB Org)
+ /// </summary>
+ public readonly ClassCodeType Class;
+
+ /// <summary>
+ /// Subclass Code (Assigned by USB Org)
+ /// </summary>
+ public readonly byte SubClass;
+
+ /// <summary>
+ /// Protocol Code (Assigned by USB Org)
+ /// </summary>
+ public readonly byte Protocol;
+
+ /// <summary>
+ /// Index of String Descriptor Describing this interface
+ /// </summary>
+ public readonly byte StringIndex;
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbInterfaceDescriptor"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="UsbInterfaceDescriptor"/>.
+ ///</returns>
+ public override string ToString() { return ToString("", ToStringParamValueSeperator, ToStringFieldSeperator); }
+
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbInterfaceDescriptor"/>.
+ ///</summary>
+ ///
+ ///<param name="prefixSeperator">The field prefix string.</param>
+ ///<param name="entitySperator">The field/value seperator string.</param>
+ ///<param name="suffixSeperator">The value suffix string.</param>
+ ///<returns>A formatted representation of the <see cref="UsbInterfaceDescriptor"/>.</returns>
+ public string ToString(string prefixSeperator, string entitySperator, string suffixSeperator)
+ {
+ Object[] values = {
+ Length, DescriptorType, InterfaceID, AlternateID, EndpointCount, Class, "0x" + SubClass.ToString("X2"),
+ "0x" + Protocol.ToString("X2"), StringIndex
+ };
+ string[] names = {
+ "Length", "DescriptorType", "InterfaceID", "AlternateID", "EndpointCount", "Class", "SubClass", "Protocol",
+ "StringIndex"
+ };
+
+ return Helper.ToString(prefixSeperator, names, entitySperator, values, suffixSeperator);
+ }
+
+
+ internal UsbInterfaceDescriptor() { }
+
+ internal UsbInterfaceDescriptor(MonoUsbAltInterfaceDescriptor altInterfaceDescriptor)
+ {
+ AlternateID = altInterfaceDescriptor.bAlternateSetting;
+ Class = altInterfaceDescriptor.bInterfaceClass;
+ DescriptorType = altInterfaceDescriptor.bDescriptorType;
+ EndpointCount = altInterfaceDescriptor.bNumEndpoints;
+ InterfaceID = altInterfaceDescriptor.bInterfaceNumber;
+ Length = altInterfaceDescriptor.bLength;
+ Protocol = altInterfaceDescriptor.bInterfaceProtocol;
+ StringIndex = altInterfaceDescriptor.iInterface;
+ SubClass = altInterfaceDescriptor.bInterfaceSubClass;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/DeviceNotifier.cs b/LibWinUsb/DeviceNotify/DeviceNotifier.cs
new file mode 100644
index 00000000..37991c93
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/DeviceNotifier.cs
@@ -0,0 +1,48 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using LibUsbDotNet.DeviceNotify.Linux;
+
+namespace LibUsbDotNet.DeviceNotify
+{
+ /// <summary>
+ /// Platform independent class for linux/windows device notification.
+ /// </summary>
+ /// <code source="..\Examples\Device.Notification\DeviceNotification.cs" lang="cs"/>
+ public static class DeviceNotifier
+ {
+ /// <summary>
+ /// Creates a new instance of a device notifier class.
+ /// </summary>
+ /// <returns>A <see cref="WindowsDeviceNotifier"/> under windows and a <see cref="LinuxDeviceNotifier"/> under linux.</returns>
+ public static IDeviceNotifier OpenDeviceNotifier()
+ {
+ if (UsbDevice.IsLinux)
+ {
+ return new LinuxDeviceNotifier();
+ }
+ else
+ {
+ return new WindowsDeviceNotifier();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/DeviceNotifyEventArgs.cs b/LibWinUsb/DeviceNotify/DeviceNotifyEventArgs.cs
new file mode 100644
index 00000000..18b40618
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/DeviceNotifyEventArgs.cs
@@ -0,0 +1,112 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using LibUsbDotNet.DeviceNotify.Info;
+
+namespace LibUsbDotNet.DeviceNotify
+{
+ /// <summary>
+ /// Describes the device notify event
+ /// </summary>
+ public abstract class DeviceNotifyEventArgs : EventArgs
+ {
+ internal IUsbDeviceNotifyInfo mDevice;
+ internal DeviceType mDeviceType;
+ internal EventType mEventType;
+ internal object mObject;
+ internal IPortNotifyInfo mPort;
+ internal IVolumeNotifyInfo mVolume;
+
+ /// <summary>
+ /// Gets the <see cref="VolumeNotifyInfo"/> class.
+ /// </summary>
+ /// <remarks>
+ /// This value is null if the <see cref="DeviceNotifyEventArgs.DeviceType"/> is not set to <see cref="DeviceNotify.DeviceType.Volume"/>
+ /// </remarks>
+ public IVolumeNotifyInfo Volume
+ {
+ get { return mVolume; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="PortNotifyInfo"/> class.
+ /// </summary>
+ /// <remarks>
+ /// This value is null if the <see cref="DeviceNotifyEventArgs.DeviceType"/> is not set to <see cref="DeviceNotify.DeviceType.Port"/>
+ /// </remarks>
+ public IPortNotifyInfo Port
+ {
+ get { return mPort; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="UsbDeviceNotifyInfo"/> class.
+ /// </summary>
+ /// <remarks>
+ /// This value is null if the <see cref="DeviceNotifyEventArgs.DeviceType"/> is not set to <see cref="DeviceNotify.DeviceType.DeviceInterface"/>
+ /// </remarks>
+ public IUsbDeviceNotifyInfo Device
+ {
+ get { return mDevice; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="EventType"/> for this notification.
+ /// </summary>
+ public EventType EventType
+ {
+ get { return mEventType; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="DeviceType"/> for this notification.
+ /// </summary>
+ public DeviceType DeviceType
+ {
+ get { return mDeviceType; }
+ }
+
+ /// <summary>
+ /// Gets the notification class as an object.
+ /// </summary>
+ /// <remarks>
+ /// This value is never null.
+ /// </remarks>
+ public object Object
+ {
+ get { return mObject; }
+ }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="DeviceNotifyEventArgs"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="DeviceNotifyEventArgs"/>.
+ ///</returns>
+ public override string ToString()
+ {
+ object[] o = {DeviceType, EventType, mObject.ToString()};
+ return string.Format("[DeviceType:{0}] [EventType:{1}] {2}", o);
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/DeviceType.cs b/LibWinUsb/DeviceNotify/DeviceType.cs
new file mode 100644
index 00000000..e671bfb6
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/DeviceType.cs
@@ -0,0 +1,58 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.DeviceNotify
+{
+ /// <summary>
+ /// Type of notification device.
+ /// </summary>
+ public enum DeviceType
+ {
+ /// <summary>
+ /// oem-defined device type.
+ /// </summary>
+ Oem = 0x00000000,
+ /// <summary>
+ /// devnode number.
+ /// </summary>
+ DevNode = 0x00000001,
+ /// <summary>
+ /// logical volume.
+ /// </summary>
+ Volume = 0x00000002,
+ /// <summary>
+ /// serial, parallel.
+ /// </summary>
+ Port = 0x00000003,
+ /// <summary>
+ /// network resource.
+ /// </summary>
+ Net = 0x00000004,
+ /// <summary>
+ /// device interface class
+ /// </summary>
+ DeviceInterface = 0x00000005,
+ /// <summary>
+ /// file system handle.
+ /// </summary>
+ Handle = 0x00000006
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/EventType.cs b/LibWinUsb/DeviceNotify/EventType.cs
new file mode 100644
index 00000000..88ed700f
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/EventType.cs
@@ -0,0 +1,58 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.DeviceNotify
+{
+ /// <summary>
+ /// Type of notification event.
+ /// </summary>
+ public enum EventType
+ {
+ /// <summary>
+ /// A custom event has occurred.
+ /// </summary>
+ CustomEvent = 0x8006,
+ /// <summary>
+ /// A device or piece of media has been inserted and is now available.
+ /// </summary>
+ DeviceArrival = 0x8000,
+ /// <summary>
+ /// Permission is requested to remove a device or piece of media. Any application can deny this request and cancel the removal.
+ /// </summary>
+ DeviceQueryRemove = 0x8001,
+ /// <summary>
+ /// A request to remove a device or piece of media has been canceled.
+ /// </summary>
+ DeviceQueryRemoveFailed = 0x8002,
+ /// <summary>
+ /// A device or piece of media has been removed.
+ /// </summary>
+ DeviceRemoveComplete = 0x8004,
+ /// <summary>
+ /// A device or piece of media is about to be removed. Cannot be denied.
+ /// </summary>
+ DeviceRemovePending = 0x8003,
+ /// <summary>
+ /// A device-specific event has occurred.
+ /// </summary>
+ DeviceTypeSpecific = 0x8005
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/IDeviceNotifier.cs b/LibWinUsb/DeviceNotify/IDeviceNotifier.cs
new file mode 100644
index 00000000..02b59e37
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/IDeviceNotifier.cs
@@ -0,0 +1,52 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+
+namespace LibUsbDotNet.DeviceNotify
+{
+ /// <summary>
+ /// Notifies an application of a change to the hardware Configuration of a device or
+ /// the computer.
+ /// </summary>
+ /// <remarks>
+ /// For devices that offer software-controllable features, such as ejection and locking,
+ /// the system typically sends a <see cref="EventType.DeviceRemovePending"/> message to
+ /// let applications and device drivers end their use of the device gracefully. If the
+ /// system forcibly removes a device, it may not send a
+ /// <see cref="EventType.DeviceQueryRemove"/> message before doing so.
+ /// </remarks>
+ /// <example>
+ /// <code source="..\Test_DeviceNotify\fTestDeviceNotify.cs" lang="cs"/>
+ /// </example>
+ public interface IDeviceNotifier
+ {
+ ///<summary>
+ /// Enables/Disables notification events.
+ ///</summary>
+ bool Enabled { get; set; }
+
+ /// <summary>
+ /// Main Notify event for all device notifications.
+ /// </summary>
+ event EventHandler<DeviceNotifyEventArgs> OnDeviceNotify;
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Info/IPortNotifyInfo.cs b/LibWinUsb/DeviceNotify/Info/IPortNotifyInfo.cs
new file mode 100644
index 00000000..fdb17286
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Info/IPortNotifyInfo.cs
@@ -0,0 +1,43 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.DeviceNotify.Info
+{
+ /// <summary> Common interface describing a communication port arrival or removal notification.
+ /// </summary>
+ public interface IPortNotifyInfo
+ {
+ /// <summary>
+ /// Under windows, Gets the name of the port that caused the event.
+ /// Under windows, Gets the full path of the device caused the event.
+ /// </summary>
+ string Name { get; }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="PortNotifyInfo"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="PortNotifyInfo"/>.
+ ///</returns>
+ string ToString();
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Info/IUsbDeviceNotifyInfo.cs b/LibWinUsb/DeviceNotify/Info/IUsbDeviceNotifyInfo.cs
new file mode 100644
index 00000000..2228e3f9
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Info/IUsbDeviceNotifyInfo.cs
@@ -0,0 +1,70 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using LibUsbDotNet.Main;
+
+namespace LibUsbDotNet.DeviceNotify.Info
+{
+ /// <summary> Common inteface describing USB DEVICE INTERFACE arrival and removal events.
+ /// </summary>
+ public interface IUsbDeviceNotifyInfo
+ {
+ /// <summary>
+ /// The symbolc name class for this device. For more information, see <see cref="UsbSymbolicName"/>.
+ /// </summary>
+ UsbSymbolicName SymbolicName { get; }
+
+ /// <summary>
+ /// Gets the full name of the USB device that caused the notification.
+ /// </summary>
+ string Name { get; }
+
+ /// <summary>
+ /// Gets the Class Guid of the USB device that caused the notification.
+ /// </summary>
+ Guid ClassGuid { get; }
+
+ /// <summary>
+ /// Parses and returns the VID from the <see cref="Name"/> property.
+ /// </summary>
+ int IdVendor { get; }
+
+ /// <summary>
+ /// Parses and returns the PID from the <see cref="Name"/> property.
+ /// </summary>
+ int IdProduct { get; }
+
+ /// <summary>
+ /// Parses and returns the serial number from the <see cref="Name"/> property.
+ /// </summary>
+ string SerialNumber { get; }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbDeviceNotifyInfo"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="UsbDeviceNotifyInfo"/>.
+ ///</returns>
+ string ToString();
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Info/IVolumeNotifyInfo.cs b/LibWinUsb/DeviceNotify/Info/IVolumeNotifyInfo.cs
new file mode 100644
index 00000000..26a2c42b
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Info/IVolumeNotifyInfo.cs
@@ -0,0 +1,63 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.DeviceNotify.Info
+{
+ /// <summary> Common interface describing a storage volume arrival or removal notification.
+ /// </summary>
+ public interface IVolumeNotifyInfo
+ {
+ /// <summary>
+ /// Under windows, gets the letter representation of the unitmask.
+ /// Under linux, gets the full path of the device name.
+ /// </summary>
+ string Letter { get; }
+
+ ///<summary>
+ /// If true, change affects media in drive. If false, change affects physical device or drive.
+ ///</summary>
+ bool ChangeAffectsMediaInDrive { get; }
+
+ /// <summary>
+ /// If True, the indicated logical volume is a network volume
+ /// </summary>
+ bool IsNetworkVolume { get; }
+
+ /// <summary>
+ /// Raw DevBroadcastVolume flags.
+ /// </summary>
+ short Flags { get; }
+
+ /// <summary>
+ /// Gets the bit unit mask of the device. IE (bit 0 = A:, bit 1 = B:, etc..)
+ /// </summary>
+ int Unitmask { get; }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="VolumeNotifyInfo"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="VolumeNotifyInfo"/>.
+ ///</returns>
+ string ToString();
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Info/PortNotifyInfo.cs b/LibWinUsb/DeviceNotify/Info/PortNotifyInfo.cs
new file mode 100644
index 00000000..d7662fb5
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Info/PortNotifyInfo.cs
@@ -0,0 +1,63 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.DeviceNotify.Internal;
+
+namespace LibUsbDotNet.DeviceNotify.Info
+{
+ /// <summary> Notify information for a communication port
+ /// </summary>
+ public class PortNotifyInfo : IPortNotifyInfo
+ {
+ private readonly DevBroadcastPort mBaseHdr = new DevBroadcastPort();
+ private readonly string mName;
+
+ internal PortNotifyInfo(IntPtr lParam)
+ {
+ Marshal.PtrToStructure(lParam, mBaseHdr);
+ IntPtr pName = new IntPtr(lParam.ToInt64() + Marshal.OffsetOf(typeof (DevBroadcastPort), "mNameHolder").ToInt64());
+ mName = Marshal.PtrToStringAuto(pName);
+ }
+
+ #region IPortNotifyInfo Members
+
+ /// <summary>
+ /// Gets the name of the port that caused the event.
+ /// </summary>
+ public string Name
+ {
+ get { return mName; }
+ }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="PortNotifyInfo"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="PortNotifyInfo"/>.
+ ///</returns>
+ public override string ToString() { return string.Format("[Port Name:{0}] ", Name); }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Info/UsbDeviceNotifyInfo.cs b/LibWinUsb/DeviceNotify/Info/UsbDeviceNotifyInfo.cs
new file mode 100644
index 00000000..085e1dab
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Info/UsbDeviceNotifyInfo.cs
@@ -0,0 +1,112 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.DeviceNotify.Internal;
+using LibUsbDotNet.Main;
+
+namespace LibUsbDotNet.DeviceNotify.Info
+{
+ /// <summary> Describes the USB device that caused the notification.
+ /// See the <see cref="IUsbDeviceNotifyInfo"/> inteface for more information.
+ /// </summary>
+ public class UsbDeviceNotifyInfo : IUsbDeviceNotifyInfo
+ {
+ private readonly DevBroadcastDeviceinterface mBaseHdr = new DevBroadcastDeviceinterface();
+ private readonly string mName;
+ private UsbSymbolicName mSymbolicName;
+
+ internal UsbDeviceNotifyInfo(IntPtr lParam)
+ {
+ Marshal.PtrToStructure(lParam, mBaseHdr);
+ IntPtr pName = new IntPtr(lParam.ToInt64() + Marshal.OffsetOf(typeof (DevBroadcastDeviceinterface), "mNameHolder").ToInt64());
+ mName = Marshal.PtrToStringAuto(pName);
+ }
+
+ #region IUsbDeviceNotifyInfo Members
+
+ /// <summary>
+ /// The symbolc name class for this device. For more information, see <see cref="UsbSymbolicName"/>.
+ /// </summary>
+ public UsbSymbolicName SymbolicName
+ {
+ get
+ {
+ if (ReferenceEquals(mSymbolicName, null))
+ mSymbolicName = new UsbSymbolicName(mName);
+
+ return mSymbolicName;
+ }
+ }
+
+ /// <summary>
+ /// Gets the full name of the USB device that caused the notification.
+ /// </summary>
+ public string Name
+ {
+ get { return mName; }
+ }
+
+ /// <summary>
+ /// Gets the Class Guid of the USB device that caused the notification.
+ /// </summary>
+ public Guid ClassGuid
+ {
+ get { return SymbolicName.ClassGuid; }
+ }
+
+ /// <summary>
+ /// Parses and returns the VID from the <see cref="Name"/> property.
+ /// </summary>
+ public int IdVendor
+ {
+ get { return SymbolicName.Vid; }
+ }
+
+ /// <summary>
+ /// Parses and returns the PID from the <see cref="Name"/> property.
+ /// </summary>
+ public int IdProduct
+ {
+ get { return SymbolicName.Pid; }
+ }
+
+ /// <summary>
+ /// Parses and returns the serial number from the <see cref="Name"/> property.
+ /// </summary>
+ public string SerialNumber
+ {
+ get { return SymbolicName.SerialNumber; }
+ }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbDeviceNotifyInfo"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="UsbDeviceNotifyInfo"/>.
+ ///</returns>
+ public override string ToString() { return SymbolicName.ToString(); }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Info/VolumeNotifyInfo.cs b/LibWinUsb/DeviceNotify/Info/VolumeNotifyInfo.cs
new file mode 100644
index 00000000..d13268e9
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Info/VolumeNotifyInfo.cs
@@ -0,0 +1,114 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.DeviceNotify.Internal;
+
+namespace LibUsbDotNet.DeviceNotify.Info
+{
+ /// <summary> Describes the storage volume that caused the notification.
+ /// See <see cref="IVolumeNotifyInfo"/> for more information.
+ /// </summary>
+ public class VolumeNotifyInfo : IVolumeNotifyInfo
+ {
+ private const int DBTF_MEDIA = 0x0001;
+ private const int DBTF_NET = 0x0002;
+
+ private readonly DevBroadcastVolume mBaseHdr = new DevBroadcastVolume();
+
+ internal VolumeNotifyInfo(IntPtr lParam) { Marshal.PtrToStructure(lParam, mBaseHdr); }
+
+ #region IVolumeNotifyInfo Members
+
+ /// <summary>
+ /// Gets the letter representation of the unitmask.
+ /// </summary>
+ public string Letter
+ {
+ get
+ {
+ Int32 tempMask = Unitmask;
+ for (byte b = 65; b < (65 + 32); b++)
+ {
+ Byte bValue = b;
+ if (bValue > 90)
+ bValue -= 43;
+ if ((tempMask & 0x1) == 1)
+ return ((char) bValue).ToString();
+
+ tempMask >>= 1;
+ }
+
+ return ((char) 63).ToString();
+ }
+ }
+
+ ///<summary>
+ /// If true, change affects media in drive. If false, change affects physical device or drive.
+ ///</summary>
+ public bool ChangeAffectsMediaInDrive
+ {
+ get { return ((Flags & DBTF_MEDIA) == DBTF_MEDIA); }
+ }
+
+ /// <summary>
+ /// If True, the indicated logical volume is a network volume
+ /// </summary>
+ public bool IsNetworkVolume
+ {
+ get { return ((Flags & DBTF_NET) == DBTF_NET); }
+ }
+
+ /// <summary>
+ /// Raw DevBroadcastVolume flags.
+ /// </summary>
+ public short Flags
+ {
+ get { return mBaseHdr.Flags; }
+ }
+
+ /// <summary>
+ /// Gets the bit unit mask of the device. IE (bit 0 = A:, bit 1 = B:, etc..)
+ /// </summary>
+ public int Unitmask
+ {
+ get { return mBaseHdr.UnitMask; }
+ }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="VolumeNotifyInfo"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="VolumeNotifyInfo"/>.
+ ///</returns>
+ public override string ToString()
+ {
+ return string.Format("[Letter:{0}] [IsNetworkVolume:{1}] [ChangeAffectsMediaInDrive:{2}] ",
+ Letter,
+ IsNetworkVolume,
+ ChangeAffectsMediaInDrive);
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Internal/DevBroadcastDeviceinterface.cs b/LibWinUsb/DeviceNotify/Internal/DevBroadcastDeviceinterface.cs
new file mode 100644
index 00000000..148e063b
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Internal/DevBroadcastDeviceinterface.cs
@@ -0,0 +1,44 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+
+#pragma warning disable 169
+
+namespace LibUsbDotNet.DeviceNotify.Internal
+{
+ [StructLayout(LayoutKind.Sequential)]
+ internal class DevBroadcastDeviceinterface : DevBroadcastHdr
+ {
+ public Guid ClassGuid = Guid.Empty;
+ private char mNameHolder;
+
+ public DevBroadcastDeviceinterface()
+ {
+ Size = Marshal.SizeOf(this);
+ DeviceType = DeviceType.DeviceInterface;
+ }
+
+ public DevBroadcastDeviceinterface(Guid guid)
+ : this() { ClassGuid = guid; }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Internal/DevBroadcastHdr.cs b/LibWinUsb/DeviceNotify/Internal/DevBroadcastHdr.cs
new file mode 100644
index 00000000..5bc907c8
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Internal/DevBroadcastHdr.cs
@@ -0,0 +1,35 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System.Runtime.InteropServices;
+
+namespace LibUsbDotNet.DeviceNotify.Internal
+{
+ [StructLayout(LayoutKind.Sequential)]
+ internal class DevBroadcastHdr
+ {
+ public int Size;
+ public DeviceType DeviceType;
+ public int Rsrvd1;
+
+ internal DevBroadcastHdr() { Size = Marshal.SizeOf(this); }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Internal/DevBroadcastPort.cs b/LibWinUsb/DeviceNotify/Internal/DevBroadcastPort.cs
new file mode 100644
index 00000000..8d9b28f0
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Internal/DevBroadcastPort.cs
@@ -0,0 +1,39 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System.Runtime.InteropServices;
+
+#pragma warning disable 169
+
+namespace LibUsbDotNet.DeviceNotify.Internal
+{
+ [StructLayout(LayoutKind.Sequential)]
+ internal class DevBroadcastPort : DevBroadcastHdr
+ {
+ private char mNameHolder;
+
+ public DevBroadcastPort()
+ {
+ Size = Marshal.SizeOf(this);
+ DeviceType = DeviceType.Port;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Internal/DevBroadcastVolume.cs b/LibWinUsb/DeviceNotify/Internal/DevBroadcastVolume.cs
new file mode 100644
index 00000000..6f69572d
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Internal/DevBroadcastVolume.cs
@@ -0,0 +1,38 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System.Runtime.InteropServices;
+
+namespace LibUsbDotNet.DeviceNotify.Internal
+{
+ [StructLayout(LayoutKind.Sequential)]
+ internal class DevBroadcastVolume : DevBroadcastHdr
+ {
+ public int UnitMask;
+ public short Flags;
+
+ public DevBroadcastVolume()
+ {
+ Size = Marshal.SizeOf(this);
+ DeviceType = DeviceType.Volume;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Internal/DevNotifyNativeWindow.cs b/LibWinUsb/DeviceNotify/Internal/DevNotifyNativeWindow.cs
new file mode 100644
index 00000000..03a6d993
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Internal/DevNotifyNativeWindow.cs
@@ -0,0 +1,79 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Windows.Forms;
+
+namespace LibUsbDotNet.DeviceNotify.Internal
+{
+ internal sealed class DevNotifyNativeWindow : NativeWindow
+ {
+ private const string WINDOW_CAPTION = "{18662f14-0871-455c-bf99-eff135425e3a}";
+ private const int WM_DEVICECHANGE = 0x219;
+ private readonly OnDeviceChangeDelegate mDelDeviceChange;
+ private readonly OnHandleChangeDelegate mDelHandleChanged;
+
+ internal DevNotifyNativeWindow(OnHandleChangeDelegate delHandleChanged, OnDeviceChangeDelegate delDeviceChange)
+ {
+ mDelHandleChanged = delHandleChanged;
+ mDelDeviceChange = delDeviceChange;
+
+ CreateParams cp = new CreateParams();
+ cp.Caption = WINDOW_CAPTION;
+ cp.X = -100;
+ cp.Y = -100;
+ cp.Width = 50;
+ cp.Height = 50;
+ CreateHandle(cp);
+ }
+
+ protected override void OnHandleChange()
+ {
+ mDelHandleChanged(Handle);
+ base.OnHandleChange();
+ }
+
+ protected override void WndProc(ref Message m)
+ {
+ if (m.Msg == WM_DEVICECHANGE)
+ {
+ mDelDeviceChange(ref m);
+ }
+ base.WndProc(ref m);
+ }
+
+ #region Nested Types
+
+ #region Nested type: OnDeviceChangeDelegate
+
+ internal delegate void OnDeviceChangeDelegate(ref Message m);
+
+ #endregion
+
+ #region Nested type: OnHandleChangeDelegate
+
+ internal delegate void OnHandleChangeDelegate(IntPtr windowHandle);
+
+ #endregion
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Internal/SafeNotifyHandle.cs b/LibWinUsb/DeviceNotify/Internal/SafeNotifyHandle.cs
new file mode 100644
index 00000000..5960eaad
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Internal/SafeNotifyHandle.cs
@@ -0,0 +1,45 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using Microsoft.Win32.SafeHandles;
+
+namespace LibUsbDotNet.DeviceNotify.Internal
+{
+ internal class SafeNotifyHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ public SafeNotifyHandle()
+ : base(true) { }
+
+ public SafeNotifyHandle(IntPtr pHandle)
+ : base(true) { SetHandle(pHandle); }
+
+ protected override bool ReleaseHandle()
+ {
+ if (handle != IntPtr.Zero)
+ {
+ bool bSuccess = WindowsDeviceNotifier.UnregisterDeviceNotification(handle);
+ handle = IntPtr.Zero;
+ }
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Linux/LinuxDevItem.cs b/LibWinUsb/DeviceNotify/Linux/LinuxDevItem.cs
new file mode 100644
index 00000000..13e892b9
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Linux/LinuxDevItem.cs
@@ -0,0 +1,90 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Descriptors;
+using MonoLibUsb.Descriptors;
+
+namespace LibUsbDotNet.DeviceNotify.Linux
+{
+ internal class LinuxDevItem
+ {
+ public readonly byte BusNumber;
+ public readonly byte DeviceAddress;
+ public readonly UsbDeviceDescriptor DeviceDescriptor;
+ public readonly string DeviceFileName;
+
+ public LinuxDevItem(string deviceFileName, byte busNumber, byte deviceAddress, byte[] fileDescriptor)
+ {
+ DeviceFileName = deviceFileName;
+ BusNumber = busNumber;
+ DeviceAddress = deviceAddress;
+
+
+ DeviceDescriptor = new UsbDeviceDescriptor();
+ GCHandle gcFileDescriptor = GCHandle.Alloc(DeviceDescriptor, GCHandleType.Pinned);
+ Marshal.Copy(fileDescriptor, 0, gcFileDescriptor.AddrOfPinnedObject(), Marshal.SizeOf(DeviceDescriptor));
+
+ gcFileDescriptor.Free();
+ }
+
+ public LinuxDevItem(string deviceFileName, byte busNumber, byte deviceAddress, MonoUsbDeviceDescriptor monoUsbDeviceDescriptor)
+ {
+ DeviceFileName = deviceFileName;
+ BusNumber = busNumber;
+ DeviceAddress = deviceAddress;
+
+
+ DeviceDescriptor = new UsbDeviceDescriptor(monoUsbDeviceDescriptor);
+ }
+
+ public bool Equals(LinuxDevItem other)
+ {
+ if (ReferenceEquals(null, other)) return false;
+ if (ReferenceEquals(this, other)) return true;
+ return Equals(other.DeviceFileName, DeviceFileName) && other.BusNumber == BusNumber && other.DeviceAddress == DeviceAddress &&
+ Equals(other.DeviceDescriptor, DeviceDescriptor);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != typeof (LinuxDevItem)) return false;
+ return Equals((LinuxDevItem) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int result = (DeviceFileName != null ? DeviceFileName.GetHashCode() : 0);
+ result = (result*397) ^ BusNumber.GetHashCode();
+ result = (result*397) ^ DeviceAddress.GetHashCode();
+ result = (result*397) ^ (DeviceDescriptor != null ? DeviceDescriptor.GetHashCode() : 0);
+ return result;
+ }
+ }
+
+ public static bool operator ==(LinuxDevItem left, LinuxDevItem right) { return Equals(left, right); }
+ public static bool operator !=(LinuxDevItem left, LinuxDevItem right) { return !Equals(left, right); }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Linux/LinuxDevItemList.cs b/LibWinUsb/DeviceNotify/Linux/LinuxDevItemList.cs
new file mode 100644
index 00000000..e319aac3
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Linux/LinuxDevItemList.cs
@@ -0,0 +1,36 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System.Collections.Generic;
+
+namespace LibUsbDotNet.DeviceNotify.Linux
+{
+ internal class LinuxDevItemList : List<LinuxDevItem>
+ {
+ public LinuxDevItem FindByName(string deviceFileName)
+ {
+ foreach (LinuxDevItem item in this)
+ if (item.DeviceFileName == deviceFileName) return item;
+
+ return null;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifier.DevMonitor.cs b/LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifier.DevMonitor.cs
new file mode 100644
index 00000000..bbdab1f1
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifier.DevMonitor.cs
@@ -0,0 +1,187 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.IO;
+using System.Text.RegularExpressions;
+using LibUsbDotNet.Descriptors;
+
+namespace LibUsbDotNet.DeviceNotify.Linux
+{
+ public partial class LinuxDeviceNotifier
+ {
+ private static Regex _RegParseDeviceInterface;
+ private static string DeviceIntefaceMatchExpression = "usbdev(?<BusNumber>[0-9]+)\\.(?<DeviceAddress>[0-9]+)$";
+ private readonly string mDevDir;
+ private FileSystemWatcher mUsbFS;
+
+ private static Regex RegParseDeviceInterface
+ {
+ get
+ {
+ if (ReferenceEquals(_RegParseDeviceInterface, null))
+ {
+ _RegParseDeviceInterface = new Regex(DeviceIntefaceMatchExpression,
+ RegexOptions.Compiled | RegexOptions.ExplicitCapture | RegexOptions.CultureInvariant |
+ RegexOptions.Singleline);
+ }
+ return _RegParseDeviceInterface;
+ }
+ }
+
+
+ private static bool IsDeviceEnterface(string name, out byte busNumber, out byte deviceAddress)
+ {
+ busNumber = 0;
+ deviceAddress = 0;
+
+ Match match = RegParseDeviceInterface.Match(name);
+ if (match.Success)
+ {
+ try
+ {
+ busNumber = byte.Parse(match.Groups["BusNumber"].Value);
+ deviceAddress = byte.Parse(match.Groups["DeviceAddress"].Value);
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ return false;
+ }
+
+ private static bool ReadFileDescriptor(string fullPath, out byte[] deviceDescriptorBytes)
+ {
+ try
+ {
+ FileStream f = File.Open(fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
+ deviceDescriptorBytes = new byte[UsbDeviceDescriptor.Size];
+ int iRead = f.Read(deviceDescriptorBytes, 0, UsbDeviceDescriptor.Size);
+ f.Close();
+
+ return iRead == UsbDeviceDescriptor.Size;
+ }
+ catch
+ {
+ deviceDescriptorBytes = null;
+ return false;
+ }
+ }
+
+ private void StartDevDirectoryMonitor()
+ {
+ if (!ReferenceEquals(mUsbFS, null)) return;
+
+ BuildDevList();
+ mUsbFS = new FileSystemWatcher(mDevDir);
+ mUsbFS.IncludeSubdirectories = false;
+ mUsbFS.Created += FileAdded;
+ mUsbFS.Deleted += FileRemoved;
+ mUsbFS.EnableRaisingEvents = true;
+ }
+
+ private void BuildDevList()
+ {
+ mLinuxDevItemList.Clear();
+ string[] deviceInterfaceFiles = Directory.GetFiles(mDevDir, "usbdev*", SearchOption.TopDirectoryOnly);
+ foreach (string deviceInterfaceFile in deviceInterfaceFiles)
+ {
+ byte busNumber;
+ byte deviceAddress;
+ string deviceFileName = Path.GetFileName(deviceInterfaceFile);
+ if (IsDeviceEnterface(deviceFileName, out busNumber, out deviceAddress))
+ {
+ byte[] descriptorBytes;
+ if (ReadFileDescriptor(deviceInterfaceFile, out descriptorBytes))
+ {
+ LinuxDevItem addedItem = new LinuxDevItem(deviceFileName, busNumber, deviceAddress, descriptorBytes);
+ mLinuxDevItemList.Add(addedItem);
+ }
+ }
+ }
+ //Console.WriteLine("LinuxDeviceNotifier:BuildDevList Count:{0}",mLinuxDevItemList.Count);
+ }
+
+ private void FileRemoved(object sender, FileSystemEventArgs e)
+ {
+ byte busNumber;
+ byte deviceAddress;
+ if (IsDeviceEnterface(e.Name, out busNumber, out deviceAddress))
+ {
+ LinuxDevItem foundLinuxDevItem;
+ if ((foundLinuxDevItem = mLinuxDevItemList.FindByName(e.Name)) == null) throw new Exception("FileRemoved:Invalid LinuxDevItem");
+
+ //Console.WriteLine("Removed Vid:{0:X4} Pid:{1:X4}", foundLinuxDevItem.DeviceDescriptor.VendorID, foundLinuxDevItem.DeviceDescriptor.ProductID);
+ //////////////////////
+ // TODO:DEVICE REMOVAL
+ //////////////////////
+
+ mLinuxDevItemList.Remove(foundLinuxDevItem);
+ EventHandler<DeviceNotifyEventArgs> deviceNotify = OnDeviceNotify;
+ if (!ReferenceEquals(deviceNotify, null))
+ {
+ deviceNotify(this, new LinuxDeviceNotifyEventArgs(foundLinuxDevItem, DeviceType.DeviceInterface, EventType.DeviceRemoveComplete));
+ }
+ }
+ }
+
+ private void FileAdded(object sender, FileSystemEventArgs e)
+ {
+ byte busNumber;
+ byte deviceAddress;
+ if (IsDeviceEnterface(e.Name, out busNumber, out deviceAddress))
+ {
+ byte[] descriptorBytes;
+ if (ReadFileDescriptor(e.FullPath, out descriptorBytes))
+ {
+ LinuxDevItem addedItem = new LinuxDevItem(e.Name, busNumber, deviceAddress, descriptorBytes);
+ if (mLinuxDevItemList.FindByName(e.Name) != null) throw new Exception("FileAdded:Invalid LinuxDevItem");
+ mLinuxDevItemList.Add(addedItem);
+
+ //Console.WriteLine("Added Vid:{0:X4} Pid:{1:X4}", addedItem.DeviceDescriptor.VendorID, addedItem.DeviceDescriptor.ProductID);
+ //////////////////////
+ // TODO:DEVICE ARRIVAL
+ //////////////////////
+
+ EventHandler<DeviceNotifyEventArgs> deviceNotify = OnDeviceNotify;
+ if (!ReferenceEquals(deviceNotify, null))
+ {
+ deviceNotify(this, new LinuxDeviceNotifyEventArgs(addedItem, DeviceType.DeviceInterface, EventType.DeviceArrival));
+ }
+ }
+ }
+ }
+
+ private void StopDevDirectoryMonitor()
+ {
+ if (!ReferenceEquals(mUsbFS, null))
+ {
+ mUsbFS.EnableRaisingEvents = false;
+ mUsbFS.Created -= FileAdded;
+ mUsbFS.Deleted -= FileRemoved;
+ mUsbFS.Dispose();
+ mUsbFS = null;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifier.DeviceListPolling.cs b/LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifier.DeviceListPolling.cs
new file mode 100644
index 00000000..78173e0b
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifier.DeviceListPolling.cs
@@ -0,0 +1,99 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Timers;
+using LibUsbDotNet.LudnMonoLibUsb;
+using MonoLibUsb.Profile;
+
+namespace LibUsbDotNet.DeviceNotify.Linux
+{
+ public partial class LinuxDeviceNotifier
+ {
+ ///<summary>
+ /// The interval (milliseconds) in which the device list is queried for changes when using the <see cref="LinuxDeviceNotifierMode.PollDeviceList"/> mode.
+ ///</summary>
+ public static int PollingInterval = 750;
+
+ private Timer mDeviceListPollTimer;
+ private object PollTimerLock = new object();
+
+ private void StartDeviceListPolling()
+ {
+ lock (PollTimerLock)
+ {
+ if (mDeviceListPollTimer != null) return;
+
+ MonoUsbDevice.RefreshProfileList();
+
+ MonoUsbDevice.ProfileList.AddRemoveEvent += OnAddRemoveEvent;
+ mDeviceListPollTimer = new Timer(PollingInterval);
+ mDeviceListPollTimer.Elapsed += PollTimer_Elapsed;
+ mDeviceListPollTimer.Start();
+ }
+ }
+
+ private void PollTimer_Elapsed(object sender, ElapsedEventArgs e)
+ {
+ lock (PollTimerLock)
+ {
+ mDeviceListPollTimer.Stop();
+ MonoUsbDevice.RefreshProfileList();
+ mDeviceListPollTimer.Start();
+ }
+ }
+
+ private void StopDeviceListPolling()
+ {
+ lock (PollTimerLock)
+ {
+ if (mDeviceListPollTimer == null) return;
+ mDeviceListPollTimer.Stop();
+ mDeviceListPollTimer.Elapsed -= PollTimer_Elapsed;
+ mDeviceListPollTimer.Dispose();
+ MonoUsbDevice.ProfileList.AddRemoveEvent -= OnAddRemoveEvent;
+ mDeviceListPollTimer = null;
+ }
+ }
+
+
+ private void OnAddRemoveEvent(object sender, AddRemoveEventArgs e)
+ {
+ EventHandler<DeviceNotifyEventArgs> deviceNotify = OnDeviceNotify;
+ if (!ReferenceEquals(deviceNotify, null))
+ {
+ string deviceFileName = String.Format("usbdev{0}.{1}", e.MonoUSBProfile.BusNumber, e.MonoUSBProfile.DeviceAddress);
+
+ LinuxDevItem linuxDevItem = new LinuxDevItem(deviceFileName,
+ e.MonoUSBProfile.BusNumber,
+ e.MonoUSBProfile.DeviceAddress,
+ e.MonoUSBProfile.DeviceDescriptor);
+
+ deviceNotify(this,
+ new LinuxDeviceNotifyEventArgs(linuxDevItem,
+ DeviceType.DeviceInterface,
+ e.EventType == AddRemoveType.Added
+ ? EventType.DeviceArrival
+ : EventType.DeviceRemoveComplete));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifier.cs b/LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifier.cs
new file mode 100644
index 00000000..9c9b1c18
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifier.cs
@@ -0,0 +1,139 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+
+namespace LibUsbDotNet.DeviceNotify.Linux
+{
+ ///<summary>
+ /// Creates an instance of the <see cref="LinuxDeviceNotifier"/> class.
+ /// See the <see cref="IDeviceNotifier"/> interface or <see cref="DeviceNotifier.OpenDeviceNotifier"/> method for more information
+ ///</summary>
+ ///<remarks>
+ ///To make your code platform-independent use the <see cref="DeviceNotifier.OpenDeviceNotifier"/> method for creating instances.
+ ///</remarks>
+ public partial class LinuxDeviceNotifier : IDeviceNotifier
+ {
+ private readonly LinuxDevItemList mLinuxDevItemList = new LinuxDevItemList();
+ private readonly LinuxDeviceNotifierMode mMode = LinuxDeviceNotifierMode.None;
+
+ /// <summary>
+ /// Creates a new instance of the LinuxDeviceNotifier using 'devDir' as the root device path. (IE. '/dev').
+ /// </summary>
+ /// <param name="devDir">The directory to monitor; usually '/dev'.</param>
+ public LinuxDeviceNotifier(string devDir)
+ {
+ mDevDir = devDir;
+ try
+ {
+ StartDevDirectoryMonitor();
+ if (mLinuxDevItemList.Count == 0) throw new NotSupportedException("LinuxDeviceNotifier:Dev directory monitor not supported.");
+ mMode = LinuxDeviceNotifierMode.MonitorDevDirectory;
+ return;
+ }
+ catch
+ {
+ StopDevDirectoryMonitor();
+ }
+ mMode = LinuxDeviceNotifierMode.PollDeviceList;
+ StartDeviceListPolling();
+ }
+
+ /// <summary>
+ /// Creates a new instance of the LinuxDeviceNotifier using '/dev' as the root device path.
+ /// </summary>
+ public LinuxDeviceNotifier()
+ : this("/dev") { }
+
+ ///<summary>
+ /// Gets the mode being used to detect notification events.
+ ///</summary>
+ public LinuxDeviceNotifierMode Mode
+ {
+ get { return mMode; }
+ }
+
+ #region IDeviceNotifier Members
+
+ ///<summary>
+ /// Enables/Disables notification events.
+ ///</summary>
+ public bool Enabled
+ {
+ get
+ {
+ switch (mMode)
+ {
+ case LinuxDeviceNotifierMode.PollDeviceList:
+ return mDeviceListPollTimer != null;
+ case LinuxDeviceNotifierMode.MonitorDevDirectory:
+ return mUsbFS != null;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ set
+ {
+ if (value)
+ Start();
+ else
+ Stop();
+ }
+ }
+
+ /// <summary>
+ /// Main Notify event for all device notifications.
+ /// </summary>
+ public event EventHandler<DeviceNotifyEventArgs> OnDeviceNotify;
+
+ #endregion
+
+ private void Stop()
+ {
+ switch (mMode)
+ {
+ case LinuxDeviceNotifierMode.PollDeviceList:
+ StopDeviceListPolling();
+ break;
+ case LinuxDeviceNotifierMode.MonitorDevDirectory:
+ StopDevDirectoryMonitor();
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ private void Start()
+ {
+ switch (mMode)
+ {
+ case LinuxDeviceNotifierMode.PollDeviceList:
+ StartDeviceListPolling();
+ break;
+ case LinuxDeviceNotifierMode.MonitorDevDirectory:
+ StartDevDirectoryMonitor();
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifierMode.cs b/LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifierMode.cs
new file mode 100644
index 00000000..a7b9ec56
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifierMode.cs
@@ -0,0 +1,44 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System.IO;
+
+namespace LibUsbDotNet.DeviceNotify.Linux
+{
+ ///<summary>
+ /// Modes the linux device notifier can use to detect notification events.
+ ///</summary>
+ public enum LinuxDeviceNotifierMode
+ {
+ /// <summary>
+ /// The device notifier is unavailable on this platform.
+ /// </summary>
+ None,
+ /// <summary>
+ /// The device notifier is polling the device list every 750ms to detect usb add and removal events.
+ /// </summary>
+ PollDeviceList,
+ /// <summary>
+ /// The device notifier is using a <see cref="FileSystemWatcher"/> to monitor the "/dev" directory for file add and delete.
+ /// </summary>
+ MonitorDevDirectory
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifyEventArgs.cs b/LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifyEventArgs.cs
new file mode 100644
index 00000000..0a3c667d
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Linux/LinuxDeviceNotifyEventArgs.cs
@@ -0,0 +1,70 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+
+namespace LibUsbDotNet.DeviceNotify.Linux
+{
+ /// <summary>
+ /// Describes the device notify event
+ /// </summary>
+ public class LinuxDeviceNotifyEventArgs : DeviceNotifyEventArgs
+ {
+ internal LinuxDeviceNotifyEventArgs(LinuxDevItem linuxDevItem, DeviceType deviceType, EventType eventType)
+ {
+ mEventType = eventType;
+ mDeviceType = deviceType;
+ switch (mDeviceType)
+ {
+ case DeviceType.Volume:
+ throw new NotImplementedException(mDeviceType.ToString());
+ case DeviceType.Port:
+ throw new NotImplementedException(mDeviceType.ToString());
+ case DeviceType.DeviceInterface:
+ mDevice = new LinuxUsbDeviceNotifyInfo(linuxDevItem);
+ mObject = mDevice;
+ break;
+ }
+ }
+
+ //internal LinuxDeviceNotifyEventArgs(DevBroadcastHdr hdr, IntPtr ptrHdr, EventType eventType)
+ //{
+ // mBaseHdr = hdr;
+ // mEventType = eventType;
+ // mDeviceType = mBaseHdr.DeviceType;
+ // switch (mDeviceType)
+ // {
+ // case DeviceType.Volume:
+ // mVolume = new VolumeNotifyInfo(ptrHdr);
+ // mObject = mVolume;
+ // break;
+ // case DeviceType.Port:
+ // mPort = new PortNotifyInfo(ptrHdr);
+ // mObject = mPort;
+ // break;
+ // case DeviceType.DeviceInterface:
+ // mDevice = new UsbDeviceNotifyInfo(ptrHdr);
+ // mObject = mDevice;
+ // break;
+ // }
+ //}
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/Linux/LinuxUsbDeviceNotifyInfo.cs b/LibWinUsb/DeviceNotify/Linux/LinuxUsbDeviceNotifyInfo.cs
new file mode 100644
index 00000000..cbdc17f5
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/Linux/LinuxUsbDeviceNotifyInfo.cs
@@ -0,0 +1,127 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using LibUsbDotNet.Descriptors;
+using LibUsbDotNet.DeviceNotify.Info;
+using LibUsbDotNet.Main;
+
+namespace LibUsbDotNet.DeviceNotify.Linux
+{
+ /// <summary> Describes the USB device that caused the notification.
+ /// see the <see cref="IUsbDeviceNotifyInfo"/> inteface for more information.
+ /// </summary>
+ public class LinuxUsbDeviceNotifyInfo : IUsbDeviceNotifyInfo
+ {
+ private readonly LinuxDevItem mLinuxDevItem;
+
+ internal LinuxUsbDeviceNotifyInfo(LinuxDevItem linuxDevItem) { mLinuxDevItem = linuxDevItem; }
+
+ ///<summary>
+ /// Gets the <see cref="UsbDeviceDescriptor"/> for the device that caused the event.
+ ///</summary>
+ public UsbDeviceDescriptor DeviceDescriptor
+ {
+ get { return mLinuxDevItem.DeviceDescriptor; }
+ }
+
+ /// <summary>
+ /// Gets the bus number the device is connected to.
+ /// </summary>
+ public byte BusNumber
+ {
+ get { return mLinuxDevItem.BusNumber; }
+ }
+
+ /// <summary>
+ /// Get the device instance address.
+ /// </summary>
+ public byte DeviceAddress
+ {
+ get { return mLinuxDevItem.DeviceAddress; }
+ }
+
+ #region IUsbDeviceNotifyInfo Members
+
+ /// <summary>
+ /// Not supported. Always returns null.
+ /// </summary>
+ public UsbSymbolicName SymbolicName
+ {
+ get { return null; }
+ }
+
+ /// <summary>
+ /// Gets the name of the USB device file descriptor that caused the notification.
+ /// </summary>
+ public string Name
+ {
+ get { return mLinuxDevItem.DeviceFileName; }
+ }
+
+ /// <summary>
+ /// Not supported. Always returs Guid.Empty.
+ /// </summary>
+ public Guid ClassGuid
+ {
+ get { return Guid.Empty; }
+ }
+
+ /// <summary>
+ /// Parses and returns the VID from the <see cref="IUsbDeviceNotifyInfo.Name"/> property.
+ /// </summary>
+ public int IdVendor
+ {
+ get { return (int)((ushort)mLinuxDevItem.DeviceDescriptor.VendorID); }
+ }
+
+ /// <summary>
+ /// Parses and returns the PID from the <see cref="IUsbDeviceNotifyInfo.Name"/> property.
+ /// </summary>
+ public int IdProduct
+ {
+ get { return (int)((ushort)mLinuxDevItem.DeviceDescriptor.ProductID); }
+ }
+
+ /// <summary>
+ /// Not supported. Always returns String.Empty.
+ /// </summary>
+ public string SerialNumber
+ {
+ get { return string.Empty; }
+ }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbDeviceNotifyInfo"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="UsbDeviceNotifyInfo"/>.
+ ///</returns>
+ public override string ToString()
+ {
+ object[] values = new object[] {Name, BusNumber, DeviceAddress, DeviceDescriptor.ToString()};
+ return string.Format("Name:{0} BusNumber:{1} DeviceAddress:{2}\n{3}", values);
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/WindowsDeviceNotifier.cs b/LibWinUsb/DeviceNotify/WindowsDeviceNotifier.cs
new file mode 100644
index 00000000..275f0c2a
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/WindowsDeviceNotifier.cs
@@ -0,0 +1,146 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using LibUsbDotNet.DeviceNotify.Internal;
+
+namespace LibUsbDotNet.DeviceNotify
+{
+ /// <summary>
+ /// Notifies an application of a change to the hardware Configuration of a device or
+ /// the computer. See <see cref="IDeviceNotifier"/> or <see cref="DeviceNotifier.OpenDeviceNotifier"/> interface for more information
+ /// </summary>
+ /// <remarks>
+ /// This is the windows implementation of the device notifier.
+ /// </remarks>
+ public class WindowsDeviceNotifier : IDeviceNotifier
+ {
+ private readonly DevBroadcastDeviceinterface mDevInterface = new DevBroadcastDeviceinterface(new Guid("A5DCBF10-6530-11D2-901F-00C04FB951ED"));
+
+ private SafeNotifyHandle mDevInterfaceHandle;
+ private bool mEnabled = true;
+ private DevNotifyNativeWindow mNotifyWindow;
+
+ ///<summary>
+ /// Creates an instance of the <see cref="WindowsDeviceNotifier"/> class.
+ /// See the <see cref="IDeviceNotifier"/> interface or <see cref="DeviceNotifier.OpenDeviceNotifier"/> method for more information
+ ///</summary>
+ ///<remarks>
+ ///To make your code platform-independent use the <see cref="DeviceNotifier.OpenDeviceNotifier"/> method for creating instances.
+ ///</remarks>
+ public WindowsDeviceNotifier() { mNotifyWindow = new DevNotifyNativeWindow(OnHandleChange, OnDeviceChange); }
+
+ #region IDeviceNotifier Members
+
+ ///<summary>
+ /// Enables/Disables notification events.
+ ///</summary>
+ public bool Enabled
+ {
+ get { return mEnabled; }
+ set { mEnabled = value; }
+ }
+
+
+ /// <summary>
+ /// Main Notify event for all device notifications.
+ /// </summary>
+ public event EventHandler<DeviceNotifyEventArgs> OnDeviceNotify;
+
+ #endregion
+
+ [DllImport("user32.dll", SetLastError = true, EntryPoint = "RegisterDeviceNotificationA", CharSet = CharSet.Ansi)]
+ private static extern SafeNotifyHandle RegisterDeviceNotification(IntPtr hRecipient,
+ [MarshalAs(UnmanagedType.AsAny), In] object notificationFilter,
+ int flags);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ internal static extern bool UnregisterDeviceNotification(IntPtr handle);
+
+ ///<summary>
+ ///Releases the resources associated with this window.
+ ///</summary>
+ ///
+ ~WindowsDeviceNotifier()
+ {
+ if (mNotifyWindow != null) mNotifyWindow.DestroyHandle();
+ mNotifyWindow = null;
+
+ if (mDevInterfaceHandle != null) mDevInterfaceHandle.Dispose();
+ mDevInterfaceHandle = null;
+ }
+
+ internal bool RegisterDeviceInterface(IntPtr windowHandle)
+ {
+ if (mDevInterfaceHandle != null)
+ {
+ mDevInterfaceHandle.Dispose();
+ mDevInterfaceHandle = null;
+ }
+ if (windowHandle != IntPtr.Zero)
+ {
+ mDevInterfaceHandle = RegisterDeviceNotification(windowHandle, mDevInterface, 0);
+ if (mDevInterfaceHandle != null && !mDevInterfaceHandle.IsInvalid)
+ return true;
+ return false;
+ }
+ return false;
+ }
+
+
+ private void OnDeviceChange(ref Message m)
+ {
+ if (!mEnabled) return;
+ if (m.LParam.ToInt32() != 0)
+ {
+ EventHandler<DeviceNotifyEventArgs> temp = OnDeviceNotify;
+ if (!ReferenceEquals(temp, null))
+ {
+ DeviceNotifyEventArgs args;
+ DevBroadcastHdr hdr = new DevBroadcastHdr();
+ Marshal.PtrToStructure(m.LParam, hdr);
+ switch (hdr.DeviceType)
+ {
+ case DeviceType.Port:
+ case DeviceType.Volume:
+ case DeviceType.DeviceInterface:
+ args = new WindowsDeviceNotifyEventArgs(hdr, m.LParam, (EventType) m.WParam.ToInt32());
+ break;
+ default:
+ args = null;
+ break;
+ }
+
+ if (!ReferenceEquals(args, null)) temp(this, args);
+ }
+ }
+ }
+
+ private void OnHandleChange(IntPtr newWindowHandle)
+ {
+ bool bSuccess = RegisterDeviceInterface(newWindowHandle);
+ Debug.Print("RegisterDeviceInterface:" + bSuccess);
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/DeviceNotify/WindowsDeviceNotifyEventArgs.cs b/LibWinUsb/DeviceNotify/WindowsDeviceNotifyEventArgs.cs
new file mode 100644
index 00000000..b68246e9
--- /dev/null
+++ b/LibWinUsb/DeviceNotify/WindowsDeviceNotifyEventArgs.cs
@@ -0,0 +1,57 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using LibUsbDotNet.DeviceNotify.Info;
+using LibUsbDotNet.DeviceNotify.Internal;
+
+namespace LibUsbDotNet.DeviceNotify
+{
+ /// <summary>
+ /// Describes the device notify event
+ /// </summary>
+ public class WindowsDeviceNotifyEventArgs : DeviceNotifyEventArgs
+ {
+ private readonly DevBroadcastHdr mBaseHdr;
+
+ internal WindowsDeviceNotifyEventArgs(DevBroadcastHdr hdr, IntPtr ptrHdr, EventType eventType)
+ {
+ mBaseHdr = hdr;
+ mEventType = eventType;
+ mDeviceType = mBaseHdr.DeviceType;
+ switch (mDeviceType)
+ {
+ case DeviceType.Volume:
+ mVolume = new VolumeNotifyInfo(ptrHdr);
+ mObject = mVolume;
+ break;
+ case DeviceType.Port:
+ mPort = new PortNotifyInfo(ptrHdr);
+ mObject = mPort;
+ break;
+ case DeviceType.DeviceInterface:
+ mDevice = new UsbDeviceNotifyInfo(ptrHdr);
+ mObject = mDevice;
+ break;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/IUsbDevice.cs b/LibWinUsb/IUsbDevice.cs
new file mode 100644
index 00000000..d3339701
--- /dev/null
+++ b/LibWinUsb/IUsbDevice.cs
@@ -0,0 +1,100 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using LibUsbDotNet.LudnMonoLibUsb;
+using LibUsbDotNet.WinUsb;
+
+namespace LibUsbDotNet
+{
+ /// <summary>
+ /// The <see cref="IUsbDevice"/> interface contains members needed to configure a USB device for use.
+ /// </summary>
+ /// <remarks>
+ /// Only "whole" usb devices have a <see cref="IUsbDevice"/> interface such as a
+ /// <see cref="LibUsb.LibUsbDevice"/> or a <see cref="MonoUsbDevice"/>. This indicates
+ /// the USB device must be properly configured by the user before it can be used.
+ /// Partial or interfaces of devices such as a <see cref="WinUsbDevice"/> do not have an <see cref="IUsbDevice"/>
+ /// interface. This indicates that the driver is handling device configuration.
+ /// </remarks>
+ /// <example>
+ /// This example uses the <see cref="IUsbDevice"/> interface to select the desired configuration and interface
+ /// for usb devices that require it.
+ /// <code source="..\Examples\Read.Write\ReadWrite.cs" lang="cs"/>
+ /// </example>
+ public interface IUsbDevice : IUsbInterface
+ {
+ /// <summary>
+ /// Sets the USB devices active configuration value.
+ /// </summary>
+ /// <param name="config">The active configuration value. A zero value means the device is not configured and a non-zero value indicates the device is configured.</param>
+ /// <returns>True on success.</returns>
+ /// <remarks>
+ /// A USB device can have several different configurations, but only one active configuration.
+ /// </remarks>
+ bool SetConfiguration(byte config);
+
+ /// <summary>
+ /// Gets the USB devices active configuration value.
+ /// </summary>
+ /// <param name="config">The active configuration value. A zero value means the device is not configured and a non-zero value indicates the device is configured.</param>
+ /// <returns>True on success.</returns>
+ bool GetConfiguration(out byte config);
+
+ /// <summary>
+ /// Sets an alternate interface for the most recent claimed interface.
+ /// </summary>
+ /// <param name="alternateID">The alternate interface to select for the most recent claimed interface See <see cref="MonoUsbDevice.ClaimInterface"/>.</param>
+ /// <returns>True on success.</returns>
+ bool SetAltInterface(int alternateID);
+
+ /// <summary>
+ /// Gets the selected alternate interface of the specified interface.
+ /// </summary>
+ /// <param name="interfaceID">The interface settings number (index) to retrieve the selected alternate interface setting for.</param>
+ /// <param name="selectedAltInterfaceID">The alternate interface setting selected for use with the specified interface.</param>
+ /// <returns>True on success.</returns>
+ bool GetAltInterfaceSetting(byte interfaceID, out byte selectedAltInterfaceID);
+
+ /// <summary>
+ /// Claims the specified interface of the device.
+ /// </summary>
+ /// <param name="interfaceID">The interface to claim.</param>
+ /// <returns>True on success.</returns>
+ bool ClaimInterface(int interfaceID);
+
+ /// <summary>
+ /// Releases an interface that was previously claimed with <see cref="ClaimInterface"/>.
+ /// </summary>
+ /// <param name="interfaceID">The interface to release.</param>
+ /// <returns>True on success.</returns>
+ bool ReleaseInterface(int interfaceID);
+
+ /// <summary>
+ /// Sends a usb device reset command.
+ /// </summary>
+ /// <remarks>
+ /// After calling <see cref="ResetDevice"/>, the <see cref="UsbDevice"/> instance is disposed and
+ /// no longer usable. A new <see cref="UsbDevice"/> instance must be obtained from the device list.
+ /// </remarks>
+ /// <returns>True on success.</returns>
+ bool ResetDevice();
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/IUsbInterface.cs b/LibWinUsb/IUsbInterface.cs
new file mode 100644
index 00000000..a023f70f
--- /dev/null
+++ b/LibWinUsb/IUsbInterface.cs
@@ -0,0 +1,187 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.ObjectModel;
+using LibUsbDotNet.Descriptors;
+using LibUsbDotNet.Info;
+using LibUsbDotNet.Main;
+
+namespace LibUsbDotNet
+{
+ /// <summary>
+ /// The <see cref="IUsbInterface"/> interface contains members needed communicate with an
+ /// interface of a usb device.
+ /// </summary>
+ /// <remarks>
+ /// All USB device classes implement these members.
+ /// </remarks>
+ public interface IUsbInterface
+ {
+ /// <summary>
+ /// A list of endpoints that have beened opened by this <see cref="UsbDevice"/> class.
+ /// </summary>
+ UsbEndpointList ActiveEndpoints { get; }
+
+ ///<summary>
+ /// Gets the available configurations for this <see cref="UsbDevice"/>
+ ///</summary>
+ /// <remarks>
+ /// The first time this property is accessed it will query the <see cref="UsbDevice"/> for all configurations. Subsequent request will return a cached copy of all configurations.
+ /// </remarks>
+ ReadOnlyCollection<UsbConfigInfo> Configs { get; }
+
+ /// <summary>
+ /// Returns the DriverMode this USB device is using.
+ /// </summary>
+ UsbDevice.DriverModeType DriverMode { get; }
+
+ /// <summary>
+ /// Gets the actual device descriptor the the current <see cref="UsbDevice"/>.
+ /// </summary>
+ UsbDeviceInfo Info { get; }
+
+ /// <summary>
+ /// Gets a value indication if the device handle is valid.
+ /// </summary>
+ bool IsOpen { get; }
+
+ /// <summary>
+ /// Gets the <see cref="UsbRegistry"/> class that opened the device, or null if the device was not opened by the <see cref="UsbRegistry"/> class.
+ /// </summary>
+ UsbRegistry UsbRegistryInfo { get; }
+
+ /// <summary>
+ /// Closes and frees device resources. Once closed the device cannot be reopened. A new <see cref="UsbDevice"/> class must be obtained using the <see cref="UsbGlobals"/> class.
+ /// </summary>
+ /// <returns>True on success.</returns>
+ bool Close();
+
+ /// <summary>
+ /// Sends/Receives an IO control message to endpoint 0.
+ /// </summary>
+ /// <param name="setupPacket">Contains parameters for the control request. See section 9.3 USB Device Requests of the Universal Serial Bus Specification Revision 2.0 for more information. </param>
+ /// <param name="buffer">Data to be sent/received from the device.</param>
+ /// <param name="bufferLength">Length of the buffer param.</param>
+ /// <param name="lengthTransferred">Number of bytes sent or received (depends on the direction of the control transfer).</param>
+ /// <returns>True on success.</returns>
+ bool ControlTransfer(ref UsbSetupPacket setupPacket, IntPtr buffer, int bufferLength, out int lengthTransferred);
+
+ /// <summary>
+ /// Transmits io control message to endpoint 0.
+ /// </summary>
+ /// <param name="setupPacket">Contains parameters for the control request. See section 9.3 USB Device Requests of the Universal Serial Bus Specification Revision 2.0 for more information. </param>
+ /// <param name="buffer">Data to be sent/received from the device. Th</param>
+ /// <param name="bufferLength">Length of the buffer param.</param>
+ /// <param name="lengthTransferred">Number of bytes sent or received (depends on the direction of the control transfer).</param>
+ /// <returns>True on success.</returns>
+ bool ControlTransfer(ref UsbSetupPacket setupPacket, object buffer, int bufferLength, out int lengthTransferred);
+
+ /// <summary>
+ /// Gets a specific descriptor from the device. See <see cref="DescriptorType"/> for more information.
+ /// </summary>
+ /// <param name="descriptorType">The descriptor type ID to retrieve; this is usually one of the <see cref="DescriptorType"/> enumerations.</param>
+ /// <param name="index">Descriptor index.</param>
+ /// <param name="langId">Descriptor language id.</param>
+ /// <param name="buffer">Memory to store the returned descriptor in.</param>
+ /// <param name="bufferLength">Length of the buffer parameter in bytes.</param>
+ /// <param name="transferLength">The number of bytes transferred to buffer upon success.</param>
+ /// <returns>True on success.</returns>
+ bool GetDescriptor(byte descriptorType, byte index, short langId, IntPtr buffer, int bufferLength, out int transferLength);
+
+ /// <summary>
+ /// Gets a specific descriptor from the device. See <see cref="DescriptorType"/> for more information.
+ /// </summary>
+ /// <param name="descriptorType">The descriptor type ID to retrieve; this is usually one of the <see cref="DescriptorType"/> enumerations.</param>
+ /// <param name="index">Descriptor index.</param>
+ /// <param name="langId">Descriptor language id.</param>
+ /// <param name="buffer">Memory to store the returned descriptor in.</param>
+ /// <param name="bufferLength">Length of the buffer parameter in bytes.</param>
+ /// <param name="transferLength">The number of bytes transferred to buffer upon success.</param>
+ /// <returns>True on success.</returns>
+ bool GetDescriptor(byte descriptorType, byte index, short langId, object buffer, int bufferLength, out int transferLength);
+
+ /// <summary>
+ /// Asking for the zero'th index is special - it returns a string
+ /// descriptor that contains all the language IDs supported by the
+ /// device. Typically there aren't many - often only one. The
+ /// language IDs are 16 bit numbers, and they start at the third byte
+ /// in the descriptor. See USB 2.0 specification, section 9.6.7, for
+ /// more information on this.
+ /// </summary>
+ /// <returns>A collection of LCIDs that the current <see cref="UsbDevice"/> supports.</returns>
+ bool GetLangIDs(out short[] langIDs);
+
+ /// <summary>
+ /// Gets a string descriptor from the device.
+ /// </summary>
+ /// <param name="stringData">Buffer to store the returned string in upon success.</param>
+ /// <param name="langId">The language ID to retrieve the string in. (0x409 for english).</param>
+ /// <param name="stringIndex">The string index to retrieve.</param>
+ /// <returns>True on success.</returns>
+ bool GetString(out string stringData, short langId, byte stringIndex);
+
+ ///<summary>
+ /// Opens/re-opens this USB device instance for communication.
+ ///</summary>
+ ///<returns>True if the device is already opened or was opened successfully. False if the device does not exists or is no longer valid.</returns>
+ bool Open();
+
+ /// <summary>
+ /// Opens a <see cref="EndpointType.Bulk"/> endpoint for reading
+ /// </summary>
+ /// <param name="readEndpointID">Endpoint number for read operations.</param>
+ /// <param name="readBufferSize">Size of the read buffer allocated for the <see cref="UsbEndpointReader.DataReceived"/> event.</param>
+ /// <returns>A <see cref="UsbEndpointReader"/> class ready for reading. If the specified endpoint is already been opened, the original <see cref="UsbEndpointReader"/> class is returned.</returns>
+ UsbEndpointReader OpenEndpointReader(ReadEndpointID readEndpointID, int readBufferSize);
+
+ /// <summary>
+ /// Opens an endpoint for reading
+ /// </summary>
+ /// <param name="readEndpointID">Endpoint number for read operations.</param>
+ /// <param name="readBufferSize">Size of the read buffer allocated for the <see cref="UsbEndpointReader.DataReceived"/> event.</param>
+ /// <param name="endpointType">The type of endpoint to open.</param>
+ /// <returns>A <see cref="UsbEndpointReader"/> class ready for reading. If the specified endpoint is already been opened, the original <see cref="UsbEndpointReader"/> class is returned.</returns>
+ UsbEndpointReader OpenEndpointReader(ReadEndpointID readEndpointID, int readBufferSize, EndpointType endpointType);
+
+ /// <summary>
+ /// Opens a <see cref="EndpointType.Bulk"/> endpoint for reading
+ /// </summary>
+ /// <param name="readEndpointID">Endpoint number for read operations.</param>
+ /// <returns>A <see cref="UsbEndpointReader"/> class ready for reading. If the specified endpoint is already been opened, the original <see cref="UsbEndpointReader"/> class is returned.</returns>
+ UsbEndpointReader OpenEndpointReader(ReadEndpointID readEndpointID);
+
+ /// <summary>
+ /// Opens a <see cref="EndpointType.Bulk"/> endpoint for writing
+ /// </summary>
+ /// <param name="writeEndpointID">Endpoint number for read operations.</param>
+ /// <returns>A <see cref="UsbEndpointWriter"/> class ready for writing. If the specified endpoint is already been opened, the original <see cref="UsbEndpointWriter"/> class is returned.</returns>
+ UsbEndpointWriter OpenEndpointWriter(WriteEndpointID writeEndpointID);
+
+ /// <summary>
+ /// Opens an endpoint for writing
+ /// </summary>
+ /// <param name="writeEndpointID">Endpoint number for read operations.</param>
+ /// <param name="endpointType">The type of endpoint to open.</param>
+ /// <returns>A <see cref="UsbEndpointWriter"/> class ready for writing. If the specified endpoint is already been opened, the original <see cref="UsbEndpointWriter"/> class is returned.</returns>
+ UsbEndpointWriter OpenEndpointWriter(WriteEndpointID writeEndpointID, EndpointType endpointType);
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Info/UsbBaseInfo.cs b/LibWinUsb/Info/UsbBaseInfo.cs
new file mode 100644
index 00000000..9cd13fdd
--- /dev/null
+++ b/LibWinUsb/Info/UsbBaseInfo.cs
@@ -0,0 +1,44 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace LibUsbDotNet.Info
+{
+ /// <summary> Base class for all Usb descriptors.
+ /// <see cref="LibUsbDotNet.Info.UsbConfigInfo"/>, <see cref="T:LibUsbDotNet.Info.UsbEndpointInfo"/>, <see cref="T:LibUsbDotNet.Info.UsbInterfaceInfo"/></summary>
+ /// <remarks><p>LibUsbDotNet supports and parses all the basic usb descriptors.</p><p>
+ /// Unknown descriptors such as driver specific class descriptors are stored as byte arrays and are accessible from the <see cref="P:LibUsbDotNet.Info.UsbBaseInfo.CustomDescriptors"/> property.
+ /// </p></remarks>
+ public abstract class UsbBaseInfo
+ {
+ internal List<byte[]> mRawDescriptors = new List<byte[]>();
+
+ /// <summary>
+ /// Gets the device-specific custom descriptor lists.
+ /// </summary>
+ public ReadOnlyCollection<byte[]> CustomDescriptors
+ {
+ get { return mRawDescriptors.AsReadOnly(); }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Info/UsbConfigInfo.cs b/LibWinUsb/Info/UsbConfigInfo.cs
new file mode 100644
index 00000000..5e1aff63
--- /dev/null
+++ b/LibWinUsb/Info/UsbConfigInfo.cs
@@ -0,0 +1,158 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using LibUsbDotNet.Descriptors;
+using LibUsbDotNet.Main;
+using LibUsbDotNet.LudnMonoLibUsb;
+using MonoLibUsb.Descriptors;
+
+namespace LibUsbDotNet.Info
+{
+ /// <summary> Contains all Configuration information for the current <see cref="T:LibUsbDotNet.UsbDevice"/>.
+ /// </summary>
+ public class UsbConfigInfo : UsbBaseInfo
+ {
+ private readonly List<UsbInterfaceInfo> mInterfaceList = new List<UsbInterfaceInfo>();
+ internal readonly UsbConfigDescriptor mUsbConfigDescriptor;
+ private String mConfigString;
+ internal UsbDevice mUsbDevice;
+
+ internal UsbConfigInfo(UsbDevice usbDevice, UsbConfigDescriptor descriptor, ref List<byte[]> rawDescriptors)
+ {
+ mUsbDevice = usbDevice;
+ mUsbConfigDescriptor = descriptor;
+ mRawDescriptors = rawDescriptors;
+
+ UsbInterfaceInfo currentInterface = null;
+ for (int iRawDescriptor = 0; iRawDescriptor < rawDescriptors.Count; iRawDescriptor++)
+ {
+ byte[] bytesRawDescriptor = rawDescriptors[iRawDescriptor];
+
+ switch (bytesRawDescriptor[1])
+ {
+ case (byte) DescriptorType.Interface:
+ currentInterface = new UsbInterfaceInfo(usbDevice, bytesRawDescriptor);
+ mRawDescriptors.RemoveAt(iRawDescriptor);
+ mInterfaceList.Add(currentInterface);
+ iRawDescriptor--;
+ break;
+ case (byte) DescriptorType.Endpoint:
+ if (currentInterface == null)
+ throw new UsbException(this, "Recieved and endpoint descriptor before receiving an interface descriptor.");
+
+ currentInterface.mEndpointInfo.Add(new UsbEndpointInfo(bytesRawDescriptor));
+ mRawDescriptors.RemoveAt(iRawDescriptor);
+ iRawDescriptor--;
+ break;
+ default:
+ if (currentInterface != null)
+ {
+ currentInterface.mRawDescriptors.Add(bytesRawDescriptor);
+ mRawDescriptors.RemoveAt(iRawDescriptor);
+ iRawDescriptor--;
+ }
+ break;
+ }
+ }
+ }
+
+ internal UsbConfigInfo(MonoUsbDevice usbDevice, MonoUsbConfigDescriptor configDescriptor)
+ {
+ mUsbDevice = usbDevice;
+
+ mUsbConfigDescriptor = new UsbConfigDescriptor(configDescriptor);
+
+ List<MonoUsbInterface> monoUSBInterfaces = configDescriptor.InterfaceList;
+ foreach (MonoUsbInterface usbInterface in monoUSBInterfaces)
+ {
+ List<MonoUsbAltInterfaceDescriptor> monoUSBAltInterfaces = usbInterface.AltInterfaceList;
+ foreach (MonoUsbAltInterfaceDescriptor monoUSBAltInterface in monoUSBAltInterfaces)
+ {
+ UsbInterfaceInfo usbInterfaceInfo = new UsbInterfaceInfo(mUsbDevice, monoUSBAltInterface);
+ mInterfaceList.Add(usbInterfaceInfo);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the actual <see cref="UsbConfigDescriptor"/> for the current config.
+ /// </summary>
+ public UsbConfigDescriptor Descriptor
+ {
+ get { return mUsbConfigDescriptor; }
+ }
+
+ /// <summary>
+ /// Gets the string representation of the <see cref="UsbConfigDescriptor.StringIndex"/> string index.
+ /// </summary>
+ public String ConfigString
+ {
+ get
+ {
+ if (ReferenceEquals(mConfigString, null))
+ {
+ mConfigString = String.Empty;
+ if (Descriptor.StringIndex > 0)
+ {
+ mUsbDevice.GetString(out mConfigString, mUsbDevice.Info.CurrentCultureLangID, Descriptor.StringIndex);
+ }
+ }
+ return mConfigString;
+ }
+ }
+
+ /// <summary>
+ /// Gets the collection of USB device interfaces associated with this <see cref="UsbConfigInfo"/> instance.
+ /// </summary>
+ public ReadOnlyCollection<UsbInterfaceInfo> InterfaceInfoList
+ {
+ get { return mInterfaceList.AsReadOnly(); }
+ }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbConfigInfo"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="UsbConfigInfo"/>.
+ ///</returns>
+ public override string ToString() { return ToString("", UsbDescriptor.ToStringParamValueSeperator, UsbDescriptor.ToStringFieldSeperator); }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbConfigInfo"/>.
+ ///</summary>
+ ///
+ ///<param name="prefixSeperator">The field prefix string.</param>
+ ///<param name="entitySperator">The field/value seperator string.</param>
+ ///<param name="suffixSeperator">The value suffix string.</param>
+ ///<returns>A formatted representation of the <see cref="UsbConfigInfo"/>.</returns>
+ public string ToString(string prefixSeperator, string entitySperator, string suffixSeperator)
+ {
+ Object[] values = {ConfigString};
+ string[] names = {"ConfigString"};
+ return Descriptor.ToString(prefixSeperator, entitySperator, suffixSeperator) +
+ Helper.ToString(prefixSeperator, names, entitySperator, values, suffixSeperator);
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Info/UsbDeviceInfo.cs b/LibWinUsb/Info/UsbDeviceInfo.cs
new file mode 100644
index 00000000..173b5ef7
--- /dev/null
+++ b/LibWinUsb/Info/UsbDeviceInfo.cs
@@ -0,0 +1,215 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Globalization;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Descriptors;
+using LibUsbDotNet.Main;
+using MonoLibUsb.Descriptors;
+
+namespace LibUsbDotNet.Info
+{
+ /// <summary> Contains USB device descriptor information.
+ /// </summary>
+ public class UsbDeviceInfo
+ {
+ private const short NO_LANG = short.MaxValue;
+ private readonly UsbDeviceDescriptor mDeviceDescriptor;
+ private short mCurrentCultureLangID = NO_LANG;
+ private String mManufacturerString;
+ private String mProductString;
+ private String mSerialString;
+ internal UsbDevice mUsbDevice;
+
+ internal UsbDeviceInfo(UsbDevice usbDevice)
+ {
+ mUsbDevice = usbDevice;
+ GetDeviceDescriptor(mUsbDevice, out mDeviceDescriptor);
+ }
+
+ internal UsbDeviceInfo(UsbDevice usbDevice, MonoUsbDeviceDescriptor usbDeviceDescriptor)
+ {
+ mUsbDevice = usbDevice;
+
+ mDeviceDescriptor = new UsbDeviceDescriptor();
+ mDeviceDescriptor.BcdDevice = usbDeviceDescriptor.BcdDevice;
+ mDeviceDescriptor.BcdUsb = usbDeviceDescriptor.BcdUsb;
+ mDeviceDescriptor.Class = usbDeviceDescriptor.Class;
+ mDeviceDescriptor.ConfigurationCount = usbDeviceDescriptor.ConfigurationCount;
+ mDeviceDescriptor.DescriptorType = usbDeviceDescriptor.DescriptorType;
+ mDeviceDescriptor.Length = usbDeviceDescriptor.Length;
+ mDeviceDescriptor.ManufacturerStringIndex = usbDeviceDescriptor.ManufacturerStringIndex;
+ mDeviceDescriptor.MaxPacketSize0 = usbDeviceDescriptor.MaxPacketSize0;
+ mDeviceDescriptor.ProductID = usbDeviceDescriptor.ProductID;
+ mDeviceDescriptor.ProductStringIndex = usbDeviceDescriptor.ProductStringIndex;
+ mDeviceDescriptor.Protocol = usbDeviceDescriptor.Protocol;
+ mDeviceDescriptor.SerialStringIndex = usbDeviceDescriptor.SerialStringIndex;
+ mDeviceDescriptor.SubClass = usbDeviceDescriptor.SubClass;
+ mDeviceDescriptor.VendorID = usbDeviceDescriptor.VendorID;
+ }
+
+ /// <summary>
+ /// The raw <see cref="UsbDeviceDescriptor"/> for the current <see cref="UsbDevice"/>.
+ /// </summary>
+ public UsbDeviceDescriptor Descriptor
+ {
+ get { return mDeviceDescriptor; }
+ }
+
+ /// <summary>
+ /// Request all available languages from the USB device (string index 0) and return the most appropriate LCID given the current operating systems locale settings. See System.Globalization.CultureInfo.CurrentCulture.LCID.
+ /// </summary>
+ /// <remarks>
+ /// Once the USB devices CurrentCultureLangID has been retreived, subsequent request will return a cached copy of the LCID.
+ /// </remarks>
+ public short CurrentCultureLangID
+ {
+ get
+ {
+ if (mCurrentCultureLangID == NO_LANG)
+ {
+ short currentCultureLangID = (short) CultureInfo.CurrentCulture.LCID;
+ short[] deviceLangIDs;
+ if (mUsbDevice.GetLangIDs(out deviceLangIDs))
+ {
+ foreach (short deviceLangID in deviceLangIDs)
+ {
+ if (deviceLangID == currentCultureLangID)
+ {
+ mCurrentCultureLangID = deviceLangID;
+ return mCurrentCultureLangID;
+ }
+ }
+ }
+ mCurrentCultureLangID = deviceLangIDs.Length > 0 ? deviceLangIDs[0] : (short) 0;
+ }
+ return mCurrentCultureLangID;
+ }
+ }
+
+ /// <summary>
+ /// Gets the string representation of the <see cref="UsbDeviceDescriptor.ManufacturerStringIndex"/> string index.
+ /// </summary>
+ public String ManufacturerString
+ {
+ get
+ {
+ if (ReferenceEquals(mManufacturerString, null))
+ {
+ mManufacturerString = String.Empty;
+ if (Descriptor.ManufacturerStringIndex > 0)
+ {
+ mUsbDevice.GetString(out mManufacturerString, CurrentCultureLangID, Descriptor.ManufacturerStringIndex);
+ }
+ }
+ return mManufacturerString;
+ }
+ }
+
+ /// <summary>
+ /// Gets the string representation of the <see cref="UsbDeviceDescriptor.ProductStringIndex"/> string index.
+ /// </summary>
+ public String ProductString
+ {
+ get
+ {
+ if (ReferenceEquals(mProductString, null))
+ {
+ mProductString = String.Empty;
+ if (Descriptor.ProductStringIndex > 0)
+ {
+ mUsbDevice.GetString(out mProductString, CurrentCultureLangID, Descriptor.ProductStringIndex);
+ }
+ }
+ return mProductString;
+ }
+ }
+
+ /// <summary>
+ /// Gets the string representation of the <see cref="UsbDeviceDescriptor.SerialStringIndex"/> string index.
+ /// </summary>
+ public String SerialString
+ {
+ get
+ {
+ if (ReferenceEquals(mSerialString, null))
+ {
+ mSerialString = String.Empty;
+ if (Descriptor.SerialStringIndex > 0)
+ {
+ mUsbDevice.GetString(out mSerialString, 0x0409, Descriptor.SerialStringIndex);
+ }
+ }
+ return mSerialString;
+ }
+ }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbInterfaceInfo"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="UsbInterfaceInfo"/>.
+ ///</returns>
+ public override string ToString() { return ToString("", UsbDescriptor.ToStringParamValueSeperator, UsbDescriptor.ToStringFieldSeperator); }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbInterfaceInfo"/>.
+ ///</summary>
+ ///
+ ///<param name="prefixSeperator">The field prefix string.</param>
+ ///<param name="entitySperator">The field/value seperator string.</param>
+ ///<param name="suffixSeperator">The value suffix string.</param>
+ ///<returns>A formatted representation of the <see cref="UsbInterfaceInfo"/>.</returns>
+ public string ToString(string prefixSeperator, string entitySperator, string suffixSeperator)
+ {
+ string[] names = {"ManufacturerString", "ProductString", "SerialString"};
+ Object[] values = {ManufacturerString, ProductString, SerialString};
+ return Descriptor.ToString(prefixSeperator, entitySperator, suffixSeperator) +
+ Helper.ToString(prefixSeperator, names, entitySperator, values, suffixSeperator);
+ }
+
+ internal static bool GetDeviceDescriptor(UsbDevice usbDevice, out UsbDeviceDescriptor deviceDescriptor)
+ {
+ if (usbDevice.mCachedDeviceDescriptor!=null)
+ {
+ deviceDescriptor = usbDevice.mCachedDeviceDescriptor;
+ return true;
+ }
+ deviceDescriptor = new UsbDeviceDescriptor();
+
+ GCHandle gcDeviceDescriptor = GCHandle.Alloc(deviceDescriptor, GCHandleType.Pinned);
+ int ret;
+ bool bSuccess = usbDevice.GetDescriptor((byte) DescriptorType.Device,
+ 0,
+ 0,
+ gcDeviceDescriptor.AddrOfPinnedObject(),
+ UsbDeviceDescriptor.Size,
+ out ret);
+ gcDeviceDescriptor.Free();
+
+ if (bSuccess) return true;
+
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Info/UsbEndpointInfo.cs b/LibWinUsb/Info/UsbEndpointInfo.cs
new file mode 100644
index 00000000..30cc19f4
--- /dev/null
+++ b/LibWinUsb/Info/UsbEndpointInfo.cs
@@ -0,0 +1,70 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using LibUsbDotNet.Descriptors;
+using LibUsbDotNet.Main;
+using MonoLibUsb.Descriptors;
+
+namespace LibUsbDotNet.Info
+{
+ /// <summary> Contains Endpoint information for the current <see cref="T:LibUsbDotNet.Info.UsbConfigInfo"/>.
+ /// </summary>
+ public class UsbEndpointInfo : UsbBaseInfo
+ {
+ internal UsbEndpointDescriptor mUsbEndpointDescriptor;
+
+ internal UsbEndpointInfo(byte[] descriptor)
+ {
+ mUsbEndpointDescriptor = new UsbEndpointDescriptor();
+ Helper.BytesToObject(descriptor, 0, Math.Min(UsbEndpointDescriptor.Size, descriptor[0]), mUsbEndpointDescriptor);
+ }
+
+ internal UsbEndpointInfo(MonoUsbEndpointDescriptor monoUsbEndpointDescriptor) { mUsbEndpointDescriptor = new UsbEndpointDescriptor(monoUsbEndpointDescriptor); }
+
+ /// <summary>
+ /// Gets the <see cref="UsbEndpointDescriptor"/> information.
+ /// </summary>
+ public UsbEndpointDescriptor Descriptor
+ {
+ get { return mUsbEndpointDescriptor; }
+ }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbEndpointInfo"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="UsbEndpointInfo"/>.
+ ///</returns>
+ public override string ToString() { return Descriptor.ToString(); }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbEndpointInfo"/>.
+ ///</summary>
+ ///
+ ///<param name="prefixSeperator">The field prefix string.</param>
+ ///<param name="entitySperator">The field/value seperator string.</param>
+ ///<param name="suffixSeperator">The value suffix string.</param>
+ ///<returns>A formatted representation of the <see cref="UsbEndpointInfo"/>.</returns>
+ public string ToString(string prefixSeperator, string entitySperator, string suffixSeperator) { return Descriptor.ToString(prefixSeperator, entitySperator, suffixSeperator); }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Info/UsbInterfaceInfo.cs b/LibWinUsb/Info/UsbInterfaceInfo.cs
new file mode 100644
index 00000000..1791efad
--- /dev/null
+++ b/LibWinUsb/Info/UsbInterfaceInfo.cs
@@ -0,0 +1,120 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using LibUsbDotNet.Descriptors;
+using LibUsbDotNet.Main;
+using MonoLibUsb.Descriptors;
+
+namespace LibUsbDotNet.Info
+{
+ /// <summary> Describes a USB device interface.
+ /// </summary>
+ public class UsbInterfaceInfo : UsbBaseInfo
+ {
+ internal readonly UsbInterfaceDescriptor mUsbInterfaceDescriptor;
+ internal List<UsbEndpointInfo> mEndpointInfo = new List<UsbEndpointInfo>();
+ private String mInterfaceString;
+ internal UsbDevice mUsbDevice;
+
+ internal UsbInterfaceInfo(UsbDevice usbDevice, byte[] descriptor)
+ {
+ mUsbDevice = usbDevice;
+ mUsbInterfaceDescriptor = new UsbInterfaceDescriptor();
+ Helper.BytesToObject(descriptor, 0, Math.Min(UsbInterfaceDescriptor.Size, descriptor[0]), mUsbInterfaceDescriptor);
+ }
+
+ internal UsbInterfaceInfo(UsbDevice usbDevice, MonoUsbAltInterfaceDescriptor monoUSBAltInterfaceDescriptor)
+ {
+ mUsbDevice = usbDevice;
+
+ mUsbInterfaceDescriptor = new UsbInterfaceDescriptor(monoUSBAltInterfaceDescriptor);
+ List<MonoUsbEndpointDescriptor> monoUsbEndpoints = monoUSBAltInterfaceDescriptor.EndpointList;
+ foreach (MonoUsbEndpointDescriptor monoUSBEndpoint in monoUsbEndpoints)
+ {
+ mEndpointInfo.Add(new UsbEndpointInfo(monoUSBEndpoint));
+ }
+ }
+
+ /// <summary>
+ /// Gets the actual interface descriptor.
+ /// </summary>
+ public UsbInterfaceDescriptor Descriptor
+ {
+ get { return mUsbInterfaceDescriptor; }
+ }
+
+ /// <summary>
+ /// Gets the collection of endpoint descriptors associated with this interface.
+ /// </summary>
+ public ReadOnlyCollection<UsbEndpointInfo> EndpointInfoList
+ {
+ get { return mEndpointInfo.AsReadOnly(); }
+ }
+
+ /// <summary>
+ /// Gets the string representation of the <see cref="UsbInterfaceDescriptor.StringIndex"/> string index.
+ /// </summary>
+ public String InterfaceString
+ {
+ get
+ {
+ if (ReferenceEquals(mInterfaceString, null))
+ {
+ mInterfaceString = String.Empty;
+ if (Descriptor.StringIndex > 0)
+ {
+ mUsbDevice.GetString(out mInterfaceString, mUsbDevice.Info.CurrentCultureLangID, Descriptor.StringIndex);
+ }
+ }
+ return mInterfaceString;
+ }
+ }
+
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbInterfaceInfo"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="UsbInterfaceInfo"/>.
+ ///</returns>
+ public override string ToString() { return ToString("", UsbDescriptor.ToStringParamValueSeperator, UsbDescriptor.ToStringFieldSeperator); }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbInterfaceInfo"/>.
+ ///</summary>
+ ///
+ ///<param name="prefixSeperator">The field prefix string.</param>
+ ///<param name="entitySperator">The field/value seperator string.</param>
+ ///<param name="suffixSeperator">The value suffix string.</param>
+ ///<returns>A formatted representation of the <see cref="UsbInterfaceInfo"/>.</returns>
+ public string ToString(string prefixSeperator, string entitySperator, string suffixSeperator)
+ {
+ Object[] values = {InterfaceString};
+ string[] names = {"InterfaceString"};
+ return Descriptor.ToString(prefixSeperator, entitySperator, suffixSeperator) +
+ Helper.ToString(prefixSeperator, names, entitySperator, values, suffixSeperator);
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Internal/Kernel32.cs b/LibWinUsb/Internal/Kernel32.cs
new file mode 100644
index 00000000..10ef2965
--- /dev/null
+++ b/LibWinUsb/Internal/Kernel32.cs
@@ -0,0 +1,197 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Globalization;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Text;
+using Microsoft.Win32.SafeHandles;
+
+// ReSharper disable InconsistentNaming
+
+namespace LibUsbDotNet.Internal
+{
+ [SuppressUnmanagedCodeSecurity]
+ internal static class Kernel32
+ {
+ private const int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
+ private static readonly StringBuilder m_sbSysMsg = new StringBuilder(1024);
+
+ [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ public static extern SafeFileHandle CreateFile(string fileName,
+ [MarshalAs(UnmanagedType.U4)] NativeFileAccess fileAccess,
+ [MarshalAs(UnmanagedType.U4)] NativeFileShare fileShare,
+ IntPtr securityAttributes,
+ [MarshalAs(UnmanagedType.U4)] NativeFileMode creationDisposition,
+ NativeFileFlag flags,
+ IntPtr template);
+
+ [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ private static extern int FormatMessage(int dwFlags,
+ IntPtr lpSource,
+ int dwMessageId,
+ int dwLanguageId,
+ [Out] StringBuilder lpBuffer,
+ int nSize,
+ IntPtr lpArguments);
+
+ [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
+ public static extern bool GetOverlappedResult(SafeHandle hDevice, IntPtr lpOverlapped, out int lpNumberOfBytesTransferred, bool bWait);
+
+
+ public static string FormatSystemMessage(int dwMessageId)
+ {
+ lock (m_sbSysMsg)
+ {
+ int ret = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+ IntPtr.Zero,
+ dwMessageId,
+ CultureInfo.CurrentCulture.LCID,
+ m_sbSysMsg,
+ m_sbSysMsg.Capacity - 1,
+ IntPtr.Zero);
+
+ if (ret > 0) return m_sbSysMsg.ToString(0, ret);
+ return null;
+ }
+ }
+
+ #region DeviceIoControl
+
+ [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
+ public static extern bool DeviceIoControl(SafeHandle hDevice,
+ int IoControlCode,
+ [MarshalAs(UnmanagedType.AsAny), In] object InBuffer,
+ int nInBufferSize,
+ IntPtr OutBuffer,
+ int nOutBufferSize,
+ out int pBytesReturned,
+ IntPtr pOverlapped);
+
+ [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
+ public static extern bool DeviceIoControl(SafeHandle hDevice,
+ int IoControlCode,
+ [MarshalAs(UnmanagedType.AsAny), In] object InBuffer,
+ int nInBufferSize,
+ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 6), Out] byte[] OutBuffer,
+ int nOutBufferSize,
+ out int pBytesReturned,
+ IntPtr Overlapped);
+
+ [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
+ public static extern bool DeviceIoControl(SafeHandle hDevice,
+ int IoControlCode,
+ IntPtr InBuffer,
+ int nInBufferSize,
+ IntPtr OutBuffer,
+ int nOutBufferSize,
+ out int pBytesReturned,
+ IntPtr Overlapped);
+
+ [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi, EntryPoint = "DeviceIoControl")]
+ public static extern bool DeviceIoControlAsObject(SafeHandle hDevice,
+ int IoControlCode,
+ [MarshalAs(UnmanagedType.AsAny), In] object InBuffer,
+ int nInBufferSize,
+ IntPtr OutBuffer,
+ int nOutBufferSize,
+ ref int pBytesReturned,
+ IntPtr Overlapped);
+
+ #endregion
+ }
+
+ [Flags]
+ internal enum NativeFileAccess : uint
+ {
+ FILE_SPECIAL = 0,
+ FILE_APPEND_DATA = (0x0004), // file
+ FILE_READ_DATA = (0x0001), // file & pipe
+ FILE_WRITE_DATA = (0x0002), // file & pipe
+ FILE_READ_EA = (0x0008), // file & directory
+ FILE_WRITE_EA = (0x0010), // file & directory
+ FILE_READ_ATTRIBUTES = (0x0080), // all
+ FILE_WRITE_ATTRIBUTES = (0x0100), // all
+ DELETE = 0x00010000,
+ READ_CONTROL = (0x00020000),
+ WRITE_DAC = (0x00040000),
+ WRITE_OWNER = (0x00080000),
+ SYNCHRONIZE = (0x00100000),
+ STANDARD_RIGHTS_REQUIRED = (0x000F0000),
+ STANDARD_RIGHTS_READ = (READ_CONTROL),
+ STANDARD_RIGHTS_WRITE = (READ_CONTROL),
+ STANDARD_RIGHTS_EXECUTE = (READ_CONTROL),
+ STANDARD_RIGHTS_ALL = (0x001F0000),
+ SPECIFIC_RIGHTS_ALL = (0x0000FFFF),
+ FILE_GENERIC_READ = (STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE),
+ FILE_GENERIC_WRITE = (STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE),
+ SPECIAL = 0
+ }
+
+ internal enum NativeFileMode : uint
+ {
+ CREATE_NEW = 1,
+ CREATE_ALWAYS = 2,
+ OPEN_EXISTING = 3,
+ OPEN_ALWAYS = 4,
+ TRUNCATE_EXISTING = 5,
+ }
+
+ [Flags]
+ internal enum NativeFileShare : uint
+ {
+ NONE = 0,
+ FILE_SHARE_READ = 0x00000001,
+ FILE_SHARE_WRITE = 0x00000002,
+ FILE_SHARE_DEELETE = 0x00000004,
+ }
+
+ [Flags]
+ internal enum NativeFileFlag : uint
+ {
+ FILE_ATTRIBUTE_READONLY = 0x00000001,
+ FILE_ATTRIBUTE_HIDDEN = 0x00000002,
+ FILE_ATTRIBUTE_SYSTEM = 0x00000004,
+ FILE_ATTRIBUTE_DIRECTORY = 0x00000010,
+ FILE_ATTRIBUTE_ARCHIVE = 0x00000020,
+ FILE_ATTRIBUTE_DEVICE = 0x00000040,
+ FILE_ATTRIBUTE_NORMAL = 0x00000080,
+ FILE_ATTRIBUTE_TEMPORARY = 0x00000100,
+ FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200,
+ FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400,
+ FILE_ATTRIBUTE_COMPRESSED = 0x00000800,
+ FILE_ATTRIBUTE_OFFLINE = 0x00001000,
+ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000,
+ FILE_ATTRIBUTE_ENCRYPTED = 0x00004000,
+ FILE_FLAG_WRITE_THROUGH = 0x80000000,
+ FILE_FLAG_OVERLAPPED = 0x40000000,
+ FILE_FLAG_NO_BUFFERING = 0x20000000,
+ FILE_FLAG_RANDOM_ACCESS = 0x10000000,
+ FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000,
+ FILE_FLAG_DELETE_ON_CLOSE = 0x04000000,
+ FILE_FLAG_BACKUP_SEMANTICS = 0x02000000,
+ FILE_FLAG_POSIX_SEMANTICS = 0x01000000,
+ FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000,
+ FILE_FLAG_OPEN_NO_RECALL = 0x00100000,
+ FILE_FLAG_FIRST_PIPE_INSTANCE = 0x00080000,
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Internal/OverlappedTransferContext.cs b/LibWinUsb/Internal/OverlappedTransferContext.cs
new file mode 100644
index 00000000..bd9a0733
--- /dev/null
+++ b/LibWinUsb/Internal/OverlappedTransferContext.cs
@@ -0,0 +1,113 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+using LibUsbDotNet.Main;
+
+namespace LibUsbDotNet.Internal
+{
+ internal class OverlappedTransferContext : UsbTransfer
+ {
+ private readonly SafeOverlapped mOverlapped = new SafeOverlapped();
+
+ public OverlappedTransferContext(UsbEndpointBase endpointBase)
+ : base(endpointBase) { }
+
+ public SafeOverlapped Overlapped
+ {
+ get { return mOverlapped; }
+ }
+
+ public override ErrorCode Submit()
+ {
+ int iTransferred;
+ ErrorCode eReturn = ErrorCode.Success;
+
+ if (mTransferCancelEvent.WaitOne(0, false)) return ErrorCode.IoCancelled;
+ if (!mTransferCompleteEvent.WaitOne(0, UsbConstants.EXIT_CONTEXT)) return ErrorCode.ResourceBusy;
+
+ mHasWaitBeenCalled = false;
+ mTransferCompleteEvent.Reset();
+ Overlapped.ClearAndSetEvent(mTransferCompleteEvent.SafeWaitHandle.DangerousGetHandle());
+
+ int ret = EndpointBase.PipeTransferSubmit(NextBufPtr,
+ RequestCount,
+ out iTransferred,
+ mIsoPacketSize,
+ Overlapped.GlobalOverlapped);
+ if (ret != 0 && ret != (int) UsbStatusClodes.ErrorIoPending)
+ {
+ mTransferCompleteEvent.Set();
+ UsbError usbErr = UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "PipeTransferSubmit", EndpointBase);
+
+ eReturn = usbErr.ErrorCode;
+ }
+ return eReturn;
+ }
+
+ public override ErrorCode Wait(out int transferredCount, bool cancel)
+ {
+ if (mHasWaitBeenCalled) throw new UsbException(this, "Repeated calls to wait with a submit is not allowed.");
+
+ transferredCount = 0;
+ bool bSuccess;
+ // Temporarily release the transfer lock while we wait for something to happen.
+ int iWait = WaitHandle.WaitAny(new WaitHandle[] { mTransferCompleteEvent, mTransferCancelEvent }, mTimeout, UsbConstants.EXIT_CONTEXT);
+ if (iWait == WaitHandle.WaitTimeout && !cancel)
+ {
+ return ErrorCode.IoTimedOut;
+ }
+ mHasWaitBeenCalled = true;
+
+ if (iWait != 0)
+ {
+ bSuccess = EndpointBase.mUsbApi.AbortPipe(EndpointBase.Handle, EndpointBase.EpNum);
+ bool bTransferComplete = mTransferCompleteEvent.WaitOne(100, UsbConstants.EXIT_CONTEXT);
+ mTransferCompleteEvent.Set();
+ if (!bSuccess || !bTransferComplete)
+ {
+ ErrorCode ec = bSuccess ? ErrorCode.Win32Error : ErrorCode.CancelIoFailed;
+ UsbError.Error(ec, Marshal.GetLastWin32Error(), "Wait:AbortPipe Failed", this);
+ return ec;
+ }
+ if (iWait == WaitHandle.WaitTimeout) return ErrorCode.IoTimedOut;
+ return ErrorCode.IoCancelled;
+ }
+
+ try
+ {
+ bSuccess = EndpointBase.mUsbApi.GetOverlappedResult(EndpointBase.Handle, Overlapped.GlobalOverlapped, out transferredCount, true);
+ if (!bSuccess)
+ {
+ UsbError usbErr = UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "GetOverlappedResult", EndpointBase);
+ return usbErr.ErrorCode;
+ }
+ return ErrorCode.None;
+ }
+ catch
+ {
+ return ErrorCode.UnknownError;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Internal/SafeOverlapped.cs b/LibWinUsb/Internal/SafeOverlapped.cs
new file mode 100644
index 00000000..dae0f4e6
--- /dev/null
+++ b/LibWinUsb/Internal/SafeOverlapped.cs
@@ -0,0 +1,115 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+namespace LibUsbDotNet.Internal
+{
+ internal class SafeOverlapped : IDisposable
+ {
+ // Find the structural starting positions in the NativeOverlapped structure.
+ private static readonly int FieldOffsetEventHandle = Marshal.OffsetOf(typeof (NativeOverlapped), "EventHandle").ToInt32();
+ private static readonly int FieldOffsetInternalHigh = Marshal.OffsetOf(typeof (NativeOverlapped), "InternalHigh").ToInt32();
+ private static readonly int FieldOffsetInternalLow = Marshal.OffsetOf(typeof (NativeOverlapped), "InternalLow").ToInt32();
+ private static readonly int FieldOffsetOffsetHigh = Marshal.OffsetOf(typeof (NativeOverlapped), "OffsetHigh").ToInt32();
+ private static readonly int FieldOffsetOffsetLow = Marshal.OffsetOf(typeof (NativeOverlapped), "OffsetLow").ToInt32();
+ private IntPtr mPtrOverlapped = IntPtr.Zero;
+
+ public SafeOverlapped()
+ {
+ // Globally allocated the memory for the overlapped structure
+ mPtrOverlapped = Marshal.AllocHGlobal(Marshal.SizeOf(typeof (NativeOverlapped)));
+ }
+
+ public IntPtr InternalLow
+ {
+ get { return Marshal.ReadIntPtr(mPtrOverlapped, FieldOffsetInternalLow); }
+ set { Marshal.WriteIntPtr(mPtrOverlapped, FieldOffsetInternalLow, value); }
+ }
+
+ public IntPtr InternalHigh
+ {
+ get { return Marshal.ReadIntPtr(mPtrOverlapped, FieldOffsetInternalHigh); }
+ set { Marshal.WriteIntPtr(mPtrOverlapped, FieldOffsetInternalHigh, value); }
+ }
+
+ public int OffsetLow
+ {
+ get { return Marshal.ReadInt32(mPtrOverlapped, FieldOffsetOffsetLow); }
+ set { Marshal.WriteInt32(mPtrOverlapped, FieldOffsetOffsetLow, value); }
+ }
+
+ public int OffsetHigh
+ {
+ get { return Marshal.ReadInt32(mPtrOverlapped, FieldOffsetOffsetHigh); }
+ set { Marshal.WriteInt32(mPtrOverlapped, FieldOffsetOffsetHigh, value); }
+ }
+
+ /// <summary>
+ /// The overlapped event wait hande.
+ /// </summary>
+ public IntPtr EventHandle
+ {
+ get { return Marshal.ReadIntPtr(mPtrOverlapped, FieldOffsetEventHandle); }
+ set { Marshal.WriteIntPtr(mPtrOverlapped, FieldOffsetEventHandle, value); }
+ }
+
+ /// <summary>
+ /// Pass this into the DeviceIoControl and GetOverlappedResult APIs
+ /// </summary>
+ public IntPtr GlobalOverlapped
+ {
+ get { return mPtrOverlapped; }
+ }
+
+ #region IDisposable Members
+
+ public void Dispose()
+ {
+ if (mPtrOverlapped != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(mPtrOverlapped);
+ mPtrOverlapped = IntPtr.Zero;
+ }
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Set the overlapped wait handle and clear out the rest of the structure.
+ /// </summary>
+ /// <param name="hEventOverlapped"></param>
+ public void ClearAndSetEvent(IntPtr hEventOverlapped)
+ {
+ EventHandle = hEventOverlapped;
+ InternalLow = IntPtr.Zero;
+ InternalHigh = IntPtr.Zero;
+ OffsetLow = 0;
+ OffsetHigh = 0;
+ }
+
+
+ // Clean up the globally allocated memory.
+ ~SafeOverlapped() { Dispose(); }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Internal/SetupApi.cs b/LibWinUsb/Internal/SetupApi.cs
new file mode 100644
index 00000000..ced66c88
--- /dev/null
+++ b/LibWinUsb/Internal/SetupApi.cs
@@ -0,0 +1,670 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+using LibUsbDotNet.Main;
+using LibUsbDotNet.WinUsb;
+using Microsoft.Win32;
+
+// ReSharper disable InconsistentNaming
+// ReSharper disable ClassNeverInstantiated.Local
+// ReSharper disable UnusedMember.Local
+// ReSharper disable ConvertIfStatementToConditionalTernaryExpression
+// ReSharper disable UnusedParameter.Local
+
+namespace LibUsbDotNet.Internal
+{
+ internal class SetupApi
+ {
+ #region Delegates
+
+ public delegate bool ClassEnumeratorDelegate(
+ IntPtr DeviceInfoSet, int deviceIndex, ref SP_DEVINFO_DATA DeviceInfoData, object classEnumeratorCallbackParam1);
+
+ #endregion
+
+ #region Enumerations
+
+ #region CR enum
+
+ public enum CR
+ {
+ SUCCESS = (0x00000000),
+ DEFAULT = (0x00000001),
+ OUT_OF_MEMORY = (0x00000002),
+ INVALID_POINTER = (0x00000003),
+ INVALID_FLAG = (0x00000004),
+ INVALID_DEVNODE = (0x00000005),
+ INVALID_DEVINST = INVALID_DEVNODE,
+ INVALID_RES_DES = (0x00000006),
+ INVALID_LOG_CONF = (0x00000007),
+ INVALID_ARBITRATOR = (0x00000008),
+ INVALID_NODELIST = (0x00000009),
+ DEVNODE_HAS_REQS = (0x0000000A),
+ DEVINST_HAS_REQS = DEVNODE_HAS_REQS,
+ INVALID_RESOURCEID = (0x0000000B),
+ DLVXD_NOT_FOUND = (0x0000000C), // WIN 95 ONLY
+ NO_SUCH_DEVNODE = (0x0000000D),
+ NO_SUCH_DEVINST = NO_SUCH_DEVNODE,
+ NO_MORE_LOG_CONF = (0x0000000E),
+ NO_MORE_RES_DES = (0x0000000F),
+ ALREADY_SUCH_DEVNODE = (0x00000010),
+ ALREADY_SUCH_DEVINST = ALREADY_SUCH_DEVNODE,
+ INVALID_RANGE_LIST = (0x00000011),
+ INVALID_RANGE = (0x00000012),
+ FAILURE = (0x00000013),
+ NO_SUCH_LOGICAL_DEV = (0x00000014),
+ CREATE_BLOCKED = (0x00000015),
+ NOT_SYSTEM_VM = (0x00000016), // WIN 95 ONLY
+ REMOVE_VETOED = (0x00000017),
+ APM_VETOED = (0x00000018),
+ INVALID_LOAD_TYPE = (0x00000019),
+ BUFFER_SMALL = (0x0000001A),
+ NO_ARBITRATOR = (0x0000001B),
+ NO_REGISTRY_HANDLE = (0x0000001C),
+ REGISTRY_ERROR = (0x0000001D),
+ INVALID_DEVICE_ID = (0x0000001E),
+ INVALID_DATA = (0x0000001F),
+ INVALID_API = (0x00000020),
+ DEVLOADER_NOT_READY = (0x00000021),
+ NEED_RESTART = (0x00000022),
+ NO_MORE_HW_PROFILES = (0x00000023),
+ DEVICE_NOT_THERE = (0x00000024),
+ NO_SUCH_VALUE = (0x00000025),
+ WRONG_TYPE = (0x00000026),
+ INVALID_PRIORITY = (0x00000027),
+ NOT_DISABLEABLE = (0x00000028),
+ FREE_RESOURCES = (0x00000029),
+ QUERY_VETOED = (0x0000002A),
+ CANT_SHARE_IRQ = (0x0000002B),
+ NO_DEPENDENT = (0x0000002C),
+ SAME_RESOURCES = (0x0000002D),
+ NO_SUCH_REGISTRY_KEY = (0x0000002E),
+ INVALID_MACHINENAME = (0x0000002F), // NT ONLY
+ REMOTE_COMM_FAILURE = (0x00000030), // NT ONLY
+ MACHINE_UNAVAILABLE = (0x00000031), // NT ONLY
+ NO_CM_SERVICES = (0x00000032), // NT ONLY
+ ACCESS_DENIED = (0x00000033), // NT ONLY
+ CALL_NOT_IMPLEMENTED = (0x00000034),
+ INVALID_PROPERTY = (0x00000035),
+ DEVICE_INTERFACE_ACTIVE = (0x00000036),
+ NO_SUCH_DEVICE_INTERFACE = (0x00000037),
+ INVALID_REFERENCE_STRING = (0x00000038),
+ INVALID_CONFLICT_LIST = (0x00000039),
+ INVALID_INDEX = (0x0000003A),
+ INVALID_STRUCTURE_SIZE = (0x0000003B),
+ NUM_CR_RESULTS = (0x0000003C)
+ }
+
+ #endregion
+
+ #region DeviceInterfaceDataFlags enum
+
+ public enum DeviceInterfaceDataFlags : uint
+ {
+ Active = 0x00000001,
+ Default = 0x00000002,
+ Removed = 0x00000004
+ }
+
+ #endregion
+
+ #region DICFG enum
+
+ [Flags]
+ public enum DICFG
+ {
+ /// <summary>
+ /// Return only the device that is associated with the system default device interface, if one is set, for the specified device interface classes.
+ /// only valid with <see cref="DEVICEINTERFACE"/>.
+ /// </summary>
+ DEFAULT = 0x00000001,
+ /// <summary>
+ /// Return only devices that are currently present in a system.
+ /// </summary>
+ PRESENT = 0x00000002,
+ /// <summary>
+ /// Return a list of installed devices for all device setup classes or all device interface classes.
+ /// </summary>
+ ALLCLASSES = 0x00000004,
+ /// <summary>
+ /// Return only devices that are a part of the current hardware profile.
+ /// </summary>
+ PROFILE = 0x00000008,
+ /// <summary>
+ /// Return devices that support device interfaces for the specified device interface classes.
+ /// </summary>
+ DEVICEINTERFACE = 0x00000010,
+ }
+
+ #endregion
+
+ #region DICUSTOMDEVPROP enum
+
+ public enum DICUSTOMDEVPROP
+ {
+ NONE = 0,
+ MERGE_MULTISZ = 0x00000001,
+ }
+
+ #endregion
+
+ [Flags]
+ public enum DevKeyType
+ {
+ DEV = 0x00000001, // Open/Create/Delete device key
+ DRV = 0x00000002, // Open/Create/Delete driver key
+ BOTH = 0x00000004, // Delete both driver and Device key
+
+ }
+ #endregion
+
+ private const string STRUCT_END_MARK = "STRUCT_END_MARK";
+
+ public static readonly Guid GUID_DEVINTERFACE_USB_DEVICE = new Guid("f18a0e88-c30c-11d0-8815-00a0c906bed8");
+
+ public static bool Is64Bit
+ {
+ get { return (IntPtr.Size == 8); }
+ }
+
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="dnDevInst">Caller-supplied device instance handle that is bound to the local machine.</param>
+ /// <param name="Buffer">Address of a buffer to receive a device instance ID string. The required buffer size can be obtained by calling CM_Get_Device_ID_Size, then incrementing the received value to allow room for the string's terminating NULL. </param>
+ /// <param name="BufferLen">Caller-supplied length, in characters, of the buffer specified by Buffer. </param>
+ /// <param name="ulFlags">Not used. set to 0.</param>
+ /// <returns>If the operation succeeds, the function returns CR_SUCCESS. Otherwise, it returns one of the CR_-prefixed error codes defined in cfgmgr32.h.</returns>
+ [DllImport("setupapi.dll", CharSet = CharSet.Auto)]
+ public static extern CR CM_Get_Device_ID(IntPtr dnDevInst, IntPtr Buffer, int BufferLen, int ulFlags);
+
+
+ /// <summary>
+ /// The CM_Get_Parent function obtains a device instance handle to the parent node of a specified device node, in the local machine's device tree.
+ /// </summary>
+ /// <param name="pdnDevInst">Caller-supplied pointer to the device instance handle to the parent node that this function retrieves. The retrieved handle is bound to the local machine.</param>
+ /// <param name="dnDevInst">Caller-supplied device instance handle that is bound to the local machine. </param>
+ /// <param name="ulFlags">Not used. set to 0.</param>
+ /// <returns>If the operation succeeds, the function returns CR_SUCCESS. Otherwise, it returns one of the CR_-prefixed error codes defined in cfgmgr32.h.</returns>
+ [DllImport("setupapi.dll")]
+ public static extern CR CM_Get_Parent(out IntPtr pdnDevInst, IntPtr dnDevInst, int ulFlags);
+
+ [DllImport("setupapi.dll", CharSet = CharSet.Auto /*, SetLastError = true*/)]
+ public static extern bool SetupDiDestroyDeviceInfoList(IntPtr hDevInfo);
+
+ [DllImport("setupapi.dll", SetLastError = true)]
+ public static extern bool SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, int MemberIndex, ref SP_DEVINFO_DATA DeviceInfoData);
+
+ /// <summary>
+ /// The SetupDiEnumDeviceInterfaces function enumerates the device interfaces that are contained in a device information set.
+ /// </summary>
+ /// <param name="hDevInfo">A pointer to a device information set that contains the device interfaces for which to return information. This handle is typically returned by SetupDiGetClassDevs. </param>
+ /// <param name="devInfo">A pointer to an SP_DEVINFO_DATA structure that specifies a device information element in DeviceInfoSet. This parameter is optional and can be NULL. If this parameter is specified, SetupDiEnumDeviceInterfaces constrains the enumeration to the interfaces that are supported by the specified device. If this parameter is NULL, repeated calls to SetupDiEnumDeviceInterfaces return information about the interfaces that are associated with all the device information elements in DeviceInfoSet. This pointer is typically returned by SetupDiEnumDeviceInfo. </param>
+ /// <param name="interfaceClassGuid">A pointer to a GUID that specifies the device interface class for the requested interface. </param>
+ /// <param name="memberIndex">A zero-based index into the list of interfaces in the device information set. The caller should call this function first with MemberIndex set to zero to obtain the first interface. Then, repeatedly increment MemberIndex and retrieve an interface until this function fails and GetLastError returns ERROR_NO_MORE_ITEMS. If DeviceInfoData specifies a particular device, the MemberIndex is relative to only the interfaces exposed by that device.</param>
+ /// <param name="deviceInterfaceData">A pointer to a caller-allocated buffer that contains, on successful return, a completed SP_DEVICE_INTERFACE_DATA structure that identifies an interface that meets the search parameters. The caller must set DeviceInterfaceData.cbSize to sizeof(SP_DEVICE_INTERFACE_DATA) before calling this function. </param>
+ /// <returns></returns>
+ [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern Boolean SetupDiEnumDeviceInterfaces(IntPtr hDevInfo,
+ ref SP_DEVINFO_DATA devInfo,
+ ref Guid interfaceClassGuid,
+ int memberIndex,
+ ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData);
+
+ [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern Boolean SetupDiEnumDeviceInterfaces(IntPtr hDevInfo,
+ [MarshalAs(UnmanagedType.AsAny)] object devInfo,
+ ref Guid interfaceClassGuid,
+ int memberIndex,
+ ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData);
+
+ /// <summary>
+ /// The SetupDiGetClassDevs function returns a handle to a device information set that contains requested device information elements for a local machine.
+ /// </summary>
+ /// <param name="ClassGuid">A pointer to the GUID for a device setup class or a device interface class. This pointer is optional and can be NULL. For more information about how to set ClassGuid, see the following Comments section. </param>
+ /// <param name="Enumerator">A pointer to a NULL-terminated string that supplies the name of a Plug and Play (PnP) enumerator or a PnP device instance identifier. This pointer is optional and can be NULL. For more information about how to set the Enumerator value, see the following Comments section. </param>
+ /// <param name="hwndParent">A handle of the top-level window to be used for a user interface that is associated with installing a device instance in the device information set. This handle is optional and can be NULL. </param>
+ /// <param name="Flags">A variable of type DWORD that specifies control options that filter the device information elements that are added to the device information set. This parameter can be a bitwise OR of zero or more of the following flags.</param>
+ /// <returns></returns>
+ [DllImport("setupapi.dll", CharSet = CharSet.Ansi, EntryPoint = "SetupDiGetClassDevsA")]
+ public static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid,
+ [MarshalAs(UnmanagedType.LPTStr)] string Enumerator,
+ IntPtr hwndParent,
+ DICFG Flags);
+
+ [DllImport("setupapi.dll", CharSet = CharSet.Ansi, EntryPoint = "SetupDiGetClassDevsA")]
+ public static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, int Enumerator, IntPtr hwndParent, DICFG Flags);
+
+ [DllImport("setupapi.dll", CharSet = CharSet.Ansi, EntryPoint = "SetupDiGetClassDevsA")]
+ public static extern IntPtr SetupDiGetClassDevs(int ClassGuid, string Enumerator, IntPtr hwndParent, DICFG Flags);
+
+ [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern bool SetupDiGetCustomDeviceProperty(IntPtr DeviceInfoSet,
+ ref SP_DEVINFO_DATA DeviceInfoData,
+ string CustomPropertyName,
+ DICUSTOMDEVPROP Flags,
+ out RegistryValueKind PropertyRegDataType,
+ Byte[] PropertyBuffer,
+ int PropertyBufferSize,
+ out int RequiredSize);
+
+ /// <summary>
+ /// The SetupDiGetDeviceInstanceId function retrieves the device instance ID that is associated with a device information element.
+ /// </summary>
+ /// <param name="DeviceInfoSet">A handle to the device information set that contains the device information element that represents the device for which to retrieve a device instance ID. </param>
+ /// <param name="DeviceInfoData">A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet. </param>
+ /// <param name="DeviceInstanceId">A pointer to the character buffer that will receive the NULL-terminated device instance ID for the specified device information element. For information about device instance IDs, see Device Identification Strings.</param>
+ /// <param name="DeviceInstanceIdSize">The size, in characters, of the DeviceInstanceId buffer. </param>
+ /// <param name="RequiredSize">A pointer to the variable that receives the number of characters required to store the device instance ID.</param>
+ /// <returns>The function returns TRUE if it is successful. Otherwise, it returns FALSE and the logged error can be retrieved with a call to GetLastError.</returns>
+ [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Ansi, EntryPoint = "SetupDiGetDeviceInstanceIdA")]
+ public static extern bool SetupDiGetDeviceInstanceId(IntPtr DeviceInfoSet,
+ ref SP_DEVINFO_DATA DeviceInfoData,
+ StringBuilder DeviceInstanceId,
+ int DeviceInstanceIdSize,
+ out int RequiredSize);
+
+ [DllImport(@"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr hDevInfo,
+ ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
+ DEVICE_INTERFACE_DETAIL_HANDLE deviceInterfaceDetailData,
+ int deviceInterfaceDetailDataSize,
+ out int requiredSize,
+ [MarshalAs(UnmanagedType.AsAny)] object deviceInfoData);
+ [DllImport(@"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr hDevInfo,
+ ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
+ DEVICE_INTERFACE_DETAIL_HANDLE deviceInterfaceDetailData,
+ int deviceInterfaceDetailDataSize,
+ out int requiredSize,
+ ref SP_DEVINFO_DATA deviceInfoData);
+
+
+ [DllImport("setupapi.dll", CharSet = CharSet.Auto)]
+ public static extern bool SetupDiGetDeviceInterfacePropertyKeys(IntPtr DeviceInfoSet,
+ ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
+ byte[] propKeyBuffer,
+ int propKeyBufferElements,
+ out int RequiredPropertyKeyCount,
+ int Flags);
+
+ /// <summary>
+ /// The SetupDiGetDeviceRegistryProperty function retrieves the specified device property.
+ /// This handle is typically returned by the SetupDiGetClassDevs or SetupDiGetClassDevsEx function.
+ /// </summary>
+ /// <param Name="DeviceInfoSet">Handle to the device information set that contains the interface and its underlying device.</param>
+ /// <param Name="DeviceInfoData">Pointer to an SP_DEVINFO_DATA structure that defines the device instance.</param>
+ /// <param Name="Property">Device property to be retrieved. SEE MSDN</param>
+ /// <param Name="PropertyRegDataType">Pointer to a variable that receives the registry data Type. This parameter can be NULL.</param>
+ /// <param Name="PropertyBuffer">Pointer to a buffer that receives the requested device property.</param>
+ /// <param Name="PropertyBufferSize">Size of the buffer, in bytes.</param>
+ /// <param Name="RequiredSize">Pointer to a variable that receives the required buffer size, in bytes. This parameter can be NULL.</param>
+ /// <returns>If the function succeeds, the return value is nonzero.</returns>
+ [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern bool SetupDiGetDeviceRegistryProperty(IntPtr DeviceInfoSet,
+ ref SP_DEVINFO_DATA DeviceInfoData,
+ SPDRP Property,
+ out RegistryValueKind PropertyRegDataType,
+ byte[] PropertyBuffer,
+ int PropertyBufferSize,
+ out int RequiredSize);
+
+ [DllImport("setupapi.dll", CharSet = CharSet.Auto)]
+ public static extern CR CM_Get_Device_ID(uint dnDevInst, StringBuilder Buffer, int BufferLen, int ulFlags);
+
+ [DllImport("Setupapi", CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern IntPtr SetupDiOpenDevRegKey(IntPtr hDeviceInfoSet, ref SP_DEVINFO_DATA deviceInfoData, int scope, int hwProfile, DevKeyType keyType, RegistryKeyPermissionCheck samDesired);
+
+ [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ public static extern int RegEnumValue(IntPtr hKey, int index, StringBuilder lpValueName, ref int lpcValueName, IntPtr lpReserved, out RegistryValueKind lpType, byte[] data, ref int dataLength);
+
+ [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ public static extern int RegEnumValue(IntPtr hKey, int index, StringBuilder lpValueName, ref int lpcValueName, IntPtr lpReserved, out RegistryValueKind lpType, StringBuilder data, ref int dataLength);
+
+ [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ public static extern int RegCloseKey(IntPtr hKey);
+
+ public static bool EnumClassDevs(string enumerator,
+ DICFG flags,
+ ClassEnumeratorDelegate classEnumeratorCallback,
+ object classEnumeratorCallbackParam1)
+ {
+ SP_DEVINFO_DATA dev_info_data = SP_DEVINFO_DATA.Empty;
+
+ int dev_index = 0;
+
+ IntPtr dev_info = SetupDiGetClassDevs(0, enumerator, IntPtr.Zero, flags);
+
+ if (dev_info == IntPtr.Zero || dev_info.ToInt64() == -1) return false;
+ bool bSuccess = false;
+ while (SetupDiEnumDeviceInfo(dev_info, dev_index, ref dev_info_data))
+ {
+ if (classEnumeratorCallback(dev_info, dev_index, ref dev_info_data, classEnumeratorCallbackParam1))
+ {
+ bSuccess = true;
+ break;
+ }
+
+ dev_index++;
+ }
+
+ SetupDiDestroyDeviceInfoList(dev_info);
+
+ return bSuccess;
+ }
+
+ public static void getSPDRPProperties(IntPtr deviceInfoSet, ref SP_DEVINFO_DATA deviceInfoData, Dictionary<string, object> deviceProperties)
+ {
+ byte[] propBuffer = new byte[1024];
+ Dictionary<string, int> allProps = Helper.GetEnumData(typeof(SPDRP));
+ foreach (KeyValuePair<string, int> prop in allProps)
+ {
+ object oValue = String.Empty;
+ int iReturnBytes;
+ RegistryValueKind regPropType;
+ bool bSuccess = SetupDiGetDeviceRegistryProperty(deviceInfoSet,
+ ref deviceInfoData,
+ (SPDRP)prop.Value,
+ out regPropType,
+ propBuffer,
+ propBuffer.Length,
+ out iReturnBytes);
+ if (bSuccess)
+ {
+ switch ((SPDRP)prop.Value)
+ {
+ case SPDRP.PhysicalDeviceObjectName:
+ case SPDRP.LocationInformation:
+ case SPDRP.Class:
+ case SPDRP.Mfg:
+ case SPDRP.DeviceDesc:
+ case SPDRP.Driver:
+ case SPDRP.EnumeratorName:
+ case SPDRP.FriendlyName:
+ case SPDRP.ClassGuid:
+ oValue = UsbRegistry.GetAsString(propBuffer, iReturnBytes);
+ break;
+ case SPDRP.HardwareId:
+ case SPDRP.CompatibleIds:
+ case SPDRP.LocationPaths:
+ oValue = UsbRegistry.GetAsStringArray(propBuffer, iReturnBytes);
+ break;
+ case SPDRP.BusNumber:
+ case SPDRP.InstallState:
+ case SPDRP.LegacyBusType:
+ case SPDRP.RemovalPolicy:
+ case SPDRP.UiNumber:
+ case SPDRP.Address:
+ oValue = UsbRegistry.GetAsStringInt32(propBuffer, iReturnBytes);
+ break;
+ case SPDRP.BusTypeGuid:
+ oValue = UsbRegistry.GetAsGuid(propBuffer, iReturnBytes);
+ break;
+ }
+ }
+ else
+ oValue = String.Empty;
+
+ deviceProperties.Add(prop.Key, oValue);
+ }
+ }
+
+ public static bool SetupDiGetDeviceInterfaceDetailLength(IntPtr hDevInfo,
+ ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
+ out int requiredLength)
+ {
+ DEVICE_INTERFACE_DETAIL_HANDLE tmp = new DEVICE_INTERFACE_DETAIL_HANDLE();
+ return SetupDiGetDeviceInterfaceDetail(hDevInfo, ref deviceInterfaceData, tmp, 0, out requiredLength, null);
+ }
+
+ public static bool SetupDiGetDeviceRegistryProperty(out byte[] regBytes,
+ IntPtr DeviceInfoSet,
+ ref SP_DEVINFO_DATA DeviceInfoData,
+ SPDRP Property)
+ {
+ regBytes = null;
+ byte[] tmp = new byte[1024];
+ int iReqSize;
+ RegistryValueKind regValueType;
+ if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet, ref DeviceInfoData, Property, out regValueType, tmp, tmp.Length, out iReqSize))
+ {
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "SetupDiGetDeviceRegistryProperty", typeof(SetupApi));
+ return false;
+ }
+ regBytes = new byte[iReqSize];
+ Array.Copy(tmp, regBytes, regBytes.Length);
+ return true;
+ }
+
+ public static bool SetupDiGetDeviceRegistryProperty(out string regSZ, IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, SPDRP Property)
+ {
+ regSZ = null;
+ byte[] tmp;
+ if (SetupDiGetDeviceRegistryProperty(out tmp, DeviceInfoSet, ref DeviceInfoData, Property))
+ {
+ regSZ = Encoding.Unicode.GetString(tmp).TrimEnd(new char[] {'\0'});
+ return true;
+ }
+ return false;
+ }
+
+ public static bool SetupDiGetDeviceRegistryProperty(out string[] regMultiSZ,
+ IntPtr DeviceInfoSet,
+ ref SP_DEVINFO_DATA DeviceInfoData,
+ SPDRP Property)
+ {
+ regMultiSZ = null;
+ string tmp;
+ if (SetupDiGetDeviceRegistryProperty(out tmp, DeviceInfoSet, ref DeviceInfoData, Property))
+ {
+ regMultiSZ = tmp.Split(new char[] {'\0'}, StringSplitOptions.RemoveEmptyEntries);
+ return true;
+ }
+ return false;
+ }
+
+ private static bool cbHasDeviceInterfaceGUID(IntPtr DeviceInfoSet,
+ int deviceIndex,
+ ref SP_DEVINFO_DATA DeviceInfoData,
+ object devInterfaceGuid)
+ {
+ RegistryValueKind propertyType;
+ byte[] propBuffer = new byte[256];
+ int requiredSize;
+ bool bSuccess = SetupDiGetCustomDeviceProperty(DeviceInfoSet,
+ ref DeviceInfoData,
+ "DeviceInterfaceGuids",
+ DICUSTOMDEVPROP.NONE,
+ out propertyType,
+ propBuffer,
+ propBuffer.Length,
+ out requiredSize);
+ if (bSuccess)
+ {
+ Guid devGuid = (Guid) devInterfaceGuid;
+ string[] stemp = Encoding.Unicode.GetString(propBuffer, 0, requiredSize).Split(new char[] {'\0'},
+ StringSplitOptions.RemoveEmptyEntries);
+ Guid findGuid = new Guid(stemp[0]);
+ return (devGuid == findGuid);
+ }
+ return false;
+ }
+
+ #region Nested Types
+
+ #region Nested type: DEVICE_INTERFACE_DETAIL_HANDLE
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct DEVICE_INTERFACE_DETAIL_HANDLE
+ {
+ private IntPtr mPtr;
+
+ internal DEVICE_INTERFACE_DETAIL_HANDLE(IntPtr ptrInit) { mPtr = ptrInit; }
+ }
+
+ #endregion
+
+ #region Nested type: DeviceInterfaceDetailHelper
+
+ public class DeviceInterfaceDetailHelper
+ {
+ public static readonly int SIZE = Is64Bit ? 8 : 6;
+ private IntPtr mpDevicePath;
+ private IntPtr mpStructure;
+
+ public DeviceInterfaceDetailHelper(int maximumLength)
+ {
+ mpStructure = Marshal.AllocHGlobal(maximumLength);
+ mpDevicePath = new IntPtr(mpStructure.ToInt64() + Marshal.SizeOf(typeof (int)));
+ }
+
+ public DEVICE_INTERFACE_DETAIL_HANDLE Handle
+ {
+ get
+ {
+ Marshal.WriteInt32(mpStructure, SIZE);
+ return new DEVICE_INTERFACE_DETAIL_HANDLE(mpStructure);
+ }
+ }
+
+ public string DevicePath
+ {
+ get { return Marshal.PtrToStringAuto(mpDevicePath); }
+ }
+
+
+ public void Free()
+ {
+ if (mpStructure != IntPtr.Zero)
+ Marshal.FreeHGlobal(mpStructure);
+
+ mpDevicePath = IntPtr.Zero;
+ mpStructure = IntPtr.Zero;
+ }
+
+
+ ~DeviceInterfaceDetailHelper() { Free(); }
+ }
+
+ #endregion
+
+ #region Nested type: MaxStructSizes
+
+ private class MaxStructSizes
+ {
+ public const int SP_DEVINFO_DATA = 40;
+ }
+
+ #endregion
+
+ #region Nested type: SP_DEVICE_INTERFACE_DATA
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct SP_DEVICE_INTERFACE_DATA
+ {
+ public static readonly SP_DEVICE_INTERFACE_DATA Empty = new SP_DEVICE_INTERFACE_DATA(Marshal.SizeOf(typeof (SP_DEVICE_INTERFACE_DATA)));
+
+ public UInt32 cbSize;
+ public Guid interfaceClassGuid;
+ public UInt32 flags;
+ private UIntPtr reserved;
+
+ private SP_DEVICE_INTERFACE_DATA(int size)
+ {
+ cbSize = (uint) size;
+ reserved = UIntPtr.Zero;
+ flags = 0;
+ interfaceClassGuid = Guid.Empty;
+ }
+ }
+
+ #endregion
+
+ //[StructLayout(LayoutKind.Sequential, Pack = 1)]
+ //public struct SP_DEVICE_INTERFACE_DATA
+ //{
+ // public static readonly SP_DEVICE_INTERFACE_DATA Empty = new SP_DEVICE_INTERFACE_DATA(GetSetupApiSize(typeof (SP_DEVICE_INTERFACE_DATA)));
+
+ // public readonly uint cbSize;
+ // public Guid interfaceClassGuid;
+ // public DeviceInterfaceDataFlags flags;
+ // private IntPtr reserved;
+
+ // private SP_DEVICE_INTERFACE_DATA(int size)
+ // {
+ // reserved = new IntPtr();
+ // flags = 0;
+ // interfaceClassGuid = Guid.Empty;
+ // cbSize = size;
+ // }
+ //}
+
+ #region Nested type: SP_DEVINFO_DATA
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct SP_DEVINFO_DATA
+ {
+ public static readonly SP_DEVINFO_DATA Empty = new SP_DEVINFO_DATA(Marshal.SizeOf(typeof (SP_DEVINFO_DATA)));
+
+ public UInt32 cbSize;
+ public Guid ClassGuid;
+ public UInt32 DevInst;
+ public IntPtr Reserved;
+
+ private SP_DEVINFO_DATA(int size)
+ {
+ cbSize = (uint) size;
+ ClassGuid = Guid.Empty;
+ DevInst = 0;
+ Reserved = IntPtr.Zero;
+ }
+ }
+
+ #endregion
+
+ //[StructLayout(LayoutKind.Sequential, Pack = IntPtr.Size==8?8:1, Size = MaxStructSizes.SP_DEVINFO_DATA)]
+ //public struct SP_DEVINFO_DATA
+ //{
+ // public static readonly SP_DEVINFO_DATA Empty = new SP_DEVINFO_DATA(Marshal.SizeOf(typeof(SP_DEVINFO_DATA)));
+
+ // public readonly int cbSize;
+ // public Guid ClassGuid;
+ // public IntPtr DevInst;
+ // public IntPtr Reserved;
+ // private SP_DEVINFO_DATA(int size)
+ // {
+ // cbSize = size;
+ // ClassGuid = Guid.Empty;
+ // DevInst = IntPtr.Zero;
+ // Reserved = IntPtr.Zero;
+
+ // STRUCT_END_MARK = 0;
+ // }
+ //}
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Internal/TransferContextBase.cs b/LibWinUsb/Internal/TransferContextBase.cs
new file mode 100644
index 00000000..e5156fc9
--- /dev/null
+++ b/LibWinUsb/Internal/TransferContextBase.cs
@@ -0,0 +1,195 @@
+// Copyright © 2006-2009 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Threading;
+using LibUsbDotNet.Main;
+using Microsoft.Win32.SafeHandles;
+
+namespace LibUsbDotNet.Internal
+{
+ public abstract class TransferContextBase : IDisposable
+ {
+ private readonly UsbEndpointBase mEndpointBase;
+
+ private IntPtr mBuffer;
+ private int mCurrentOffset;
+ private int mCurrentRemaining;
+ private int mCurrentTransmitted;
+
+ private int mFailRetries;
+ protected int mOriginalCount;
+ protected int mOriginalOffset;
+ private PinnedHandle mPinnedHandle;
+
+ protected int mTimeout;
+
+ protected bool mHasWaitBeenCalled = true;
+
+ protected ManualResetEvent mTransferCancelEvent = new ManualResetEvent(false);
+ protected internal ManualResetEvent mTransferCompleteEvent = new ManualResetEvent(true);
+
+ protected TransferContextBase(UsbEndpointBase endpointBase) { mEndpointBase = endpointBase; }
+
+ public UsbEndpointBase EndpointBase
+ {
+ get { return mEndpointBase; }
+ }
+
+ protected int RequestCount
+ {
+ get { return (mCurrentRemaining > UsbEndpointBase.MaxReadWrite ? UsbEndpointBase.MaxReadWrite : mCurrentRemaining); }
+ }
+
+ protected int FailRetries
+ {
+ get { return mFailRetries; }
+ }
+
+ protected IntPtr NextBufPtr
+ {
+ get { return new IntPtr(mBuffer.ToInt64() + mCurrentOffset); }
+ }
+
+ public bool IsCancelled
+ {
+ get { return mTransferCancelEvent.WaitOne(0, UsbConstants.EXIT_CONTEXT); }
+ }
+
+ public bool IsComplete
+ {
+ get { return mTransferCompleteEvent.WaitOne(0, UsbConstants.EXIT_CONTEXT); }
+ }
+
+ public SafeWaitHandle CancelWaitHandle
+ {
+ get { return mTransferCancelEvent.SafeWaitHandle; }
+ }
+
+ public SafeWaitHandle CompleteWaitHandle
+ {
+ get { return mTransferCompleteEvent.SafeWaitHandle; }
+ }
+
+ #region IDisposable Members
+
+ public virtual void Dispose()
+ {
+ if (!IsCancelled) Cancel();
+
+ int dummy;
+ if (!mHasWaitBeenCalled) Wait(out dummy);
+ }
+
+ #endregion
+
+ public virtual ErrorCode Cancel()
+ {
+ mTransferCancelEvent.Set();
+ return ErrorCode.Success;
+ }
+
+ public abstract ErrorCode Submit();
+
+ public abstract ErrorCode Wait(out int transferredCount);
+
+
+ public virtual void Fill(object buffer, int offset, int count, int timeout)
+ {
+ if (mPinnedHandle != null) mPinnedHandle.Dispose();
+ mPinnedHandle = new PinnedHandle(buffer);
+ Fill(mPinnedHandle.Handle, offset, count, timeout);
+ }
+
+ public virtual void Fill(IntPtr buffer, int offset, int count, int timeout)
+ {
+ mBuffer = buffer;
+
+ mOriginalOffset = offset;
+ mOriginalCount = count;
+ mTimeout = timeout;
+ Reset();
+ }
+
+ internal static ErrorCode SyncTransfer(TransferContextBase transferContext,
+ IntPtr buffer,
+ int offset,
+ int length,
+ int timeout,
+ out int transferLength)
+ {
+ if (ReferenceEquals(transferContext, null)) throw new NullReferenceException("Invalid transfer context.");
+ if (offset < 0) throw new ArgumentException("must be >=0", "offset");
+
+ lock (transferContext)
+ {
+ transferLength = 0;
+
+ int transferred;
+ ErrorCode ec;
+
+ transferContext.Fill(buffer, offset, length, timeout);
+
+ while (true)
+ {
+ ec = transferContext.Submit();
+ if (ec == ErrorCode.IoEndpointGlobalCancelRedo) continue;
+ if (ec != ErrorCode.Success) return ec;
+
+ ec = transferContext.Wait(out transferred);
+ if (ec == ErrorCode.IoEndpointGlobalCancelRedo) continue;
+ if (ec != ErrorCode.Success) return ec;
+
+ transferLength += transferred;
+
+ if ((ec != ErrorCode.None || transferred != UsbEndpointBase.MaxReadWrite) ||
+ !transferContext.IncrementTransfer(transferred))
+ break;
+ }
+
+ return ec;
+ }
+ }
+
+ public bool IncrementTransfer(int amount)
+ {
+ mCurrentTransmitted += amount;
+ mCurrentOffset += amount;
+ mCurrentRemaining -= amount;
+
+ if (mCurrentRemaining <= 0) return false;
+
+ return true;
+ }
+
+ protected void IncFailRetries() { mFailRetries++; }
+
+ public void Reset()
+ {
+ mCurrentOffset = mOriginalOffset;
+ mCurrentRemaining = mOriginalCount;
+ mCurrentTransmitted = 0;
+ mFailRetries = 0;
+
+ mTransferCancelEvent.Reset();
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Internal/UsbApiBase.cs b/LibWinUsb/Internal/UsbApiBase.cs
new file mode 100644
index 00000000..3d6e37f2
--- /dev/null
+++ b/LibWinUsb/Internal/UsbApiBase.cs
@@ -0,0 +1,81 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Main;
+
+namespace LibUsbDotNet.Internal
+{
+ internal abstract class UsbApiBase
+ {
+ public abstract bool AbortPipe(SafeHandle interfaceHandle, byte pipeID);
+
+ public abstract bool ControlTransfer(SafeHandle interfaceHandle,
+ UsbSetupPacket setupPacket,
+ IntPtr buffer,
+ int bufferLength,
+ out int lengthTransferred);
+
+ public abstract bool FlushPipe(SafeHandle interfaceHandle, byte pipeID);
+
+ public abstract bool GetDescriptor(SafeHandle interfaceHandle,
+ byte descriptorType,
+ byte index,
+ ushort languageID,
+ IntPtr buffer,
+ int bufferLength,
+ out int lengthTransferred);
+
+
+ public abstract bool GetOverlappedResult(SafeHandle interfaceHandle, IntPtr pOverlapped, out int numberOfBytesTransferred, bool wait);
+
+ //public abstract bool ReadPipe(UsbEndpointBase endPointBase,
+ // Byte[] buffer,
+ // int bufferLength,
+ // out int lengthTransferred,
+ // int isoPacketSize,
+ // IntPtr pOverlapped);
+
+ public abstract bool ReadPipe(UsbEndpointBase endPointBase,
+ IntPtr pBuffer,
+ int bufferLength,
+ out int lengthTransferred,
+ int isoPacketSize,
+ IntPtr pOverlapped);
+
+ public abstract bool ResetPipe(SafeHandle interfaceHandle, byte pipeID);
+
+ //public abstract bool WritePipe(UsbEndpointBase endPointBase,
+ // Byte[] buffer,
+ // int bufferLength,
+ // out int lengthTransferred,
+ // int isoPacketSize,
+ // IntPtr pOverlapped);
+
+ public abstract bool WritePipe(UsbEndpointBase endPointBase,
+ IntPtr pBuffer,
+ int bufferLength,
+ out int lengthTransferred,
+ int isoPacketSize,
+ IntPtr pOverlapped);
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Internal/UsbRegex/BaseRegSymbolicName.cs b/LibWinUsb/Internal/UsbRegex/BaseRegSymbolicName.cs
new file mode 100644
index 00000000..af9b1f34
--- /dev/null
+++ b/LibWinUsb/Internal/UsbRegex/BaseRegSymbolicName.cs
@@ -0,0 +1,37 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System.Text.RegularExpressions;
+
+namespace LibUsbDotNet.Internal.UsbRegex
+{
+ internal class BaseRegSymbolicName : Regex
+ {
+ private const RegexOptions OPTIONS =
+ RegexOptions.CultureInvariant | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.Compiled |
+ RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase;
+
+ private const string PATTERN =
+ @"((&){0,1}Vid_(?<Vid>[0-9A-Fa-f]{1,4})(&){0,1}Pid_(?<Pid>[0-9A-Fa-f]{1,4})((&){0,1}Rev_(?<Rev>[0-9A-Fa-f]{1,4})){0,1})((\x23{0,1}\{(?<ClassGuid>([0-9A-Fa-f]+)-([0-9A-Fa-f]+)-([0-9A-Fa-f]+)-([0-9A-Fa-f]+)-([0-9A-Fa-f]+))})|(\x23(?<String>[\x20-\x22\x24-\x2b\x2d-\x7f]+?)(?=\x23|$)))*";
+
+ public BaseRegSymbolicName() : base(PATTERN, OPTIONS) { }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Internal/UsbRegex/NamedGroup.cs b/LibWinUsb/Internal/UsbRegex/NamedGroup.cs
new file mode 100644
index 00000000..dbd9c97d
--- /dev/null
+++ b/LibWinUsb/Internal/UsbRegex/NamedGroup.cs
@@ -0,0 +1,35 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.Internal.UsbRegex
+{
+ internal struct NamedGroup
+ {
+ public readonly string GroupName;
+ public readonly int GroupNumber;
+
+ public NamedGroup(int GroupNumber, string GroupName)
+ {
+ this.GroupNumber = GroupNumber;
+ this.GroupName = GroupName;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Internal/UsbRegex/RegHardwareID.cs b/LibWinUsb/Internal/UsbRegex/RegHardwareID.cs
new file mode 100644
index 00000000..253e9777
--- /dev/null
+++ b/LibWinUsb/Internal/UsbRegex/RegHardwareID.cs
@@ -0,0 +1,105 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Text.RegularExpressions;
+
+namespace LibUsbDotNet.Internal.UsbRegex
+{
+ /// <summary>
+ /// Regular expression class for quick parsing of usb hardware ids.
+ /// </summary>
+ internal class RegHardwareID : Regex
+ {
+ #region Enumerations
+
+ public enum ENamedGroups
+ {
+ Vid = 1,
+ Pid = 2,
+ Rev = 3,
+ MI= 4
+ }
+
+ #endregion
+
+ private const RegexOptions OPTIONS =
+ RegexOptions.CultureInvariant | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.Compiled |
+ RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase;
+
+ private const string PATTERN = "(Vid_(?<Vid>[0-9A-F]{1,4}))|(Pid_(?<Pid>[0-9A-F]{1,4}))|(Rev_(?<Rev>[0-9]{1,4}))|(MI_(?<MI>[0-9A-F]{1,2}))";
+
+ public static readonly NamedGroup[] NAMED_GROUPS = new NamedGroup[]
+ {
+ new NamedGroup(1, "Vid"), new NamedGroup(2, "Pid"), new NamedGroup(3, "Rev"),
+ new NamedGroup(4, "MI")
+ };
+
+ public RegHardwareID() : base(PATTERN, OPTIONS) { }
+
+ private static RegHardwareID __globalInstance;
+ public static RegHardwareID GlobalInstance
+ {
+ get
+ {
+ if (ReferenceEquals(__globalInstance,null))
+ __globalInstance=new RegHardwareID();
+ return __globalInstance;
+ }
+ }
+
+ public new string[] GetGroupNames() { return new string[] {"Vid", "Pid", "Rev", "MI"}; }
+
+ public new int[] GetGroupNumbers() { return new int[] {1, 2, 3, 4}; }
+
+ public new string GroupNameFromNumber(int GroupNumber)
+ {
+ switch (GroupNumber)
+ {
+ case 1:
+ return "Vid";
+ case 2:
+ return "Pid";
+ case 3:
+ return "Rev";
+ case 4:
+ return "MI";
+ }
+ return "";
+ }
+
+ public new int GroupNumberFromName(string GroupName)
+ {
+ switch (GroupName)
+ {
+ case "Vid":
+ return 1;
+ case "Pid":
+ return 2;
+ case "Rev":
+ return 3;
+ case "MI":
+ return 4;
+ }
+ return -1;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Internal/UsbRegex/RegSymbolicName.cs b/LibWinUsb/Internal/UsbRegex/RegSymbolicName.cs
new file mode 100644
index 00000000..44cd56a4
--- /dev/null
+++ b/LibWinUsb/Internal/UsbRegex/RegSymbolicName.cs
@@ -0,0 +1,95 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.Internal.UsbRegex
+{
+ /// <summary>
+ /// Regular expression class for parsing USB symbolic names and hardware ids.
+ /// </summary>
+ internal class RegSymbolicName : BaseRegSymbolicName
+ {
+ public static readonly NamedGroup[] NamedGroups = new NamedGroup[]
+ {
+ new NamedGroup(1, "Vid"),
+ new NamedGroup(2, "Pid"),
+ new NamedGroup(3, "Rev"),
+ new NamedGroup(4, "ClassGuid"),
+ new NamedGroup(5, "String"),
+ };
+
+ public new string[] GetGroupNames() { return new string[] {"Vid", "Pid", "Rev", "ClassGuid", "String"}; }
+
+ public new int[] GetGroupNumbers() { return new int[] {1, 2, 3, 4, 5}; }
+
+ public new string GroupNameFromNumber(int groupNumber)
+ {
+ switch (groupNumber)
+ {
+ case 1:
+ return "Vid";
+
+ case 2:
+ return "Pid";
+
+ case 3:
+ return "Rev";
+
+ case 4:
+ return "ClassGuid";
+
+ case 5:
+ return "String";
+ }
+ return "";
+ }
+
+ public new int GroupNumberFromName(string groupName)
+ {
+ switch (groupName.ToLower())
+ {
+ case "vid":
+ return 1;
+
+ case "pid":
+ return 2;
+
+ case "rev":
+ return 3;
+
+ case "classguid":
+ return 4;
+
+ case "string":
+ return 5;
+ }
+ return -1;
+ }
+ }
+
+ internal enum NamedGroupType
+ {
+ Vid = 1,
+ Pid = 2,
+ Rev = 3,
+ ClassGuid = 4,
+ String = 5,
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/LibUsb/Internal/LibUsbAPI.cs b/LibWinUsb/LibUsb/Internal/LibUsbAPI.cs
new file mode 100644
index 00000000..ce557af4
--- /dev/null
+++ b/LibWinUsb/LibUsb/Internal/LibUsbAPI.cs
@@ -0,0 +1,151 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Main;
+
+namespace LibUsbDotNet.Internal.LibUsb
+{
+ internal class LibUsbAPI : UsbApiBase
+ {
+ public override bool AbortPipe(SafeHandle interfaceHandle, byte pipeID)
+ {
+ LibUsbRequest req = new LibUsbRequest();
+
+ int ret;
+ req.Endpoint.ID = pipeID;
+ req.Timeout = UsbConstants.DEFAULT_TIMEOUT;
+ return LibUsbDriverIO.UsbIOSync(interfaceHandle, LibUsbIoCtl.ABORT_ENDPOINT, req, LibUsbRequest.Size, IntPtr.Zero, 0, out ret);
+ }
+
+ public bool ResetDevice(SafeHandle interfaceHandle)
+ {
+ LibUsbRequest req = new LibUsbRequest();
+
+ int ret;
+ req.Timeout = UsbConstants.DEFAULT_TIMEOUT;
+ return LibUsbDriverIO.UsbIOSync(interfaceHandle, LibUsbIoCtl.RESET_DEVICE, req, LibUsbRequest.Size, IntPtr.Zero, 0, out ret);
+ }
+
+ public override bool ControlTransfer(SafeHandle interfaceHandle,
+ UsbSetupPacket setupPacket,
+ IntPtr buffer,
+ int bufferLength,
+ out int lengthTransferred)
+ {
+ return LibUsbDriverIO.ControlTransfer(interfaceHandle,
+ setupPacket,
+ buffer,
+ bufferLength,
+ out lengthTransferred,
+ UsbConstants.DEFAULT_TIMEOUT);
+ }
+
+ public override bool FlushPipe(SafeHandle interfaceHandle, byte pipeID) { return true; }
+
+
+ public override bool GetDescriptor(SafeHandle interfaceHandle,
+ byte descriptorType,
+ byte index,
+ ushort languageID,
+ IntPtr buffer,
+ int bufferLength,
+ out int lengthTransferred)
+ {
+ LibUsbRequest req = new LibUsbRequest();
+ req.Descriptor.Index = index;
+ req.Descriptor.LangID = languageID;
+ req.Descriptor.Recipient = (byte) UsbEndpointDirection.EndpointIn & 0x1F;
+ req.Descriptor.Type = descriptorType;
+ return LibUsbDriverIO.UsbIOSync(interfaceHandle,
+ LibUsbIoCtl.GET_DESCRIPTOR,
+ req,
+ LibUsbRequest.Size,
+ buffer,
+ bufferLength,
+ out lengthTransferred);
+ }
+
+
+ public override bool GetOverlappedResult(SafeHandle interfaceHandle, IntPtr pOverlapped, out int numberOfBytesTransferred, bool wait) { return Kernel32.GetOverlappedResult(interfaceHandle, pOverlapped, out numberOfBytesTransferred, wait); }
+
+
+ public override bool ReadPipe(UsbEndpointBase endPointBase,
+ IntPtr buffer,
+ int bufferLength,
+ out int lengthTransferred,
+ int isoPacketSize,
+ IntPtr pOverlapped)
+ {
+ LibUsbRequest req = new LibUsbRequest();
+ req.Endpoint.ID = endPointBase.EpNum;
+ req.Endpoint.PacketSize = isoPacketSize;
+ req.Timeout = UsbConstants.DEFAULT_TIMEOUT;
+
+ int cltCode = endPointBase.Type == EndpointType.Isochronous ? LibUsbIoCtl.ISOCHRONOUS_READ : LibUsbIoCtl.INTERRUPT_OR_BULK_READ;
+
+
+ return Kernel32.DeviceIoControl(endPointBase.Device.Handle,
+ cltCode,
+ req,
+ LibUsbRequest.Size,
+ buffer,
+ bufferLength,
+ out lengthTransferred,
+ pOverlapped);
+ }
+
+ public override bool ResetPipe(SafeHandle interfaceHandle, byte pipeID)
+ {
+ LibUsbRequest req = new LibUsbRequest();
+
+ int ret;
+ req.Endpoint.ID = pipeID;
+ req.Timeout = UsbConstants.DEFAULT_TIMEOUT;
+ return LibUsbDriverIO.UsbIOSync(interfaceHandle, LibUsbIoCtl.RESET_ENDPOINT, req, LibUsbRequest.Size, IntPtr.Zero, 0, out ret);
+ }
+
+
+ public override bool WritePipe(UsbEndpointBase endPointBase,
+ IntPtr buffer,
+ int bufferLength,
+ out int lengthTransferred,
+ int isoPacketSize,
+ IntPtr pOverlapped)
+ {
+ LibUsbRequest req = new LibUsbRequest();
+ req.Endpoint.ID = endPointBase.EpNum;
+ req.Endpoint.PacketSize = isoPacketSize;
+ req.Timeout = UsbConstants.DEFAULT_TIMEOUT;
+ int cltCode = endPointBase.Type == EndpointType.Isochronous ? LibUsbIoCtl.ISOCHRONOUS_WRITE : LibUsbIoCtl.INTERRUPT_OR_BULK_WRITE;
+
+ return Kernel32.DeviceIoControl(endPointBase.Handle,
+ cltCode,
+ req,
+ LibUsbRequest.Size,
+ buffer,
+ bufferLength,
+ out lengthTransferred,
+ pOverlapped);
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/LibUsb/Internal/LibUsbDriverIO.cs b/LibWinUsb/LibUsb/Internal/LibUsbDriverIO.cs
new file mode 100644
index 00000000..a87fd6ab
--- /dev/null
+++ b/LibWinUsb/LibUsb/Internal/LibUsbDriverIO.cs
@@ -0,0 +1,100 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+using LibUsbDotNet.Main;
+using Microsoft.Win32.SafeHandles;
+
+namespace LibUsbDotNet.Internal.LibUsb
+{
+ internal partial class LibUsbDriverIO
+ {
+ public const int ERROR_IO_PENDING = 997;
+ public const int FALSE = 0;
+ public const int FILE_FLAG_OVERLAPPED = 0x40000000;
+ internal const string LIBUSB_DEVICE_NAME = "\\\\.\\libusb0-";
+ public const int TRUE = 1;
+
+ private static byte[] _tempCfgBuf;
+
+ internal static byte[] GlobalTempCfgBuffer
+ {
+ get
+ {
+ if (ReferenceEquals(null, _tempCfgBuf))
+ _tempCfgBuf = new byte[4096];
+
+ return _tempCfgBuf;
+ }
+ }
+
+
+ internal static string GetDeviceNameString(int index) { return String.Format("{0}{1}", LIBUSB_DEVICE_NAME, index.ToString("0000")); }
+
+ internal static SafeFileHandle OpenDevice(String deviceFileName)
+ {
+ return Kernel32.CreateFile(deviceFileName,
+ NativeFileAccess.SPECIAL,
+ NativeFileShare.NONE,
+ IntPtr.Zero,
+ NativeFileMode.OPEN_EXISTING,
+ NativeFileFlag.FILE_FLAG_OVERLAPPED,
+ IntPtr.Zero);
+ }
+
+
+ internal static bool UsbIOSync(SafeHandle dev, int code, Object inBuffer, int inSize, IntPtr outBuffer, int outSize, out int ret)
+ {
+ SafeOverlapped deviceIoOverlapped = new SafeOverlapped();
+ ManualResetEvent hEvent = new ManualResetEvent(false);
+ deviceIoOverlapped.ClearAndSetEvent(hEvent.SafeWaitHandle.DangerousGetHandle());
+ ret = 0;
+
+ if (!Kernel32.DeviceIoControlAsObject(dev, code, inBuffer, inSize, outBuffer, outSize, ref ret, deviceIoOverlapped.GlobalOverlapped))
+ {
+ int iError = Marshal.GetLastWin32Error();
+ if (iError != ERROR_IO_PENDING)
+ {
+ // Don't log errors for these control codes.
+ do
+ {
+ if (code == LibUsbIoCtl.GET_REG_PROPERTY) break;
+ if (code == LibUsbIoCtl.GET_CUSTOM_REG_PROPERTY) break;
+ UsbError.Error(ErrorCode.Win32Error, iError, String.Format("DeviceIoControl code {0:X8} failed:{1}", code, Kernel32.FormatSystemMessage(iError)), typeof(LibUsbDriverIO));
+ } while (false);
+
+ hEvent.Close();
+ return false;
+ }
+ }
+ if (Kernel32.GetOverlappedResult(dev, deviceIoOverlapped.GlobalOverlapped, out ret, true))
+ {
+ hEvent.Close();
+ return true;
+ }
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "GetOverlappedResult failed.\nIoCtlCode:" + code, typeof(LibUsbDriverIO));
+ hEvent.Close();
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/LibUsb/Internal/LibUsbDriverIO_IOControlMessage.cs b/LibWinUsb/LibUsb/Internal/LibUsbDriverIO_IOControlMessage.cs
new file mode 100644
index 00000000..80187073
--- /dev/null
+++ b/LibWinUsb/LibUsb/Internal/LibUsbDriverIO_IOControlMessage.cs
@@ -0,0 +1,199 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Main;
+
+namespace LibUsbDotNet.Internal.LibUsb
+{
+ internal partial class LibUsbDriverIO
+ {
+ public const int EINVAL = 22;
+
+ internal static bool ControlTransferEx(SafeHandle interfaceHandle,
+ UsbSetupPacket setupPacket,
+ IntPtr buffer,
+ int bufferLength,
+ out int lengthTransferred,
+ int timeout)
+ {
+ lengthTransferred = 0;
+ LibUsbRequest req = new LibUsbRequest();
+
+ req.Timeout = timeout;
+ req.Control.RequestType = (byte) setupPacket.RequestType;
+ req.Control.Request = (byte) setupPacket.Request;
+ req.Control.Value = (ushort) setupPacket.Value;
+ req.Control.Index = (ushort) setupPacket.Index;
+ req.Control.Length = (ushort) setupPacket.Length;
+
+ /* in request? */
+ Byte[] reqBytes = req.Bytes;
+ Byte[] inBytes = reqBytes;
+ if ((setupPacket.RequestType & (byte) UsbEndpointDirection.EndpointIn) == 0)
+ {
+ inBytes = new byte[LibUsbRequest.Size + bufferLength];
+ reqBytes.CopyTo(inBytes, 0);
+ if (buffer != IntPtr.Zero) Marshal.Copy(buffer, inBytes, LibUsbRequest.Size, bufferLength);
+
+ buffer = IntPtr.Zero;
+ bufferLength = 0;
+ }
+
+ if (UsbIOSync(interfaceHandle, LibUsbIoCtl.CONTROL_TRANSFER, inBytes, inBytes.Length, buffer, bufferLength, out lengthTransferred))
+ {
+ /* in request? */
+ if ((setupPacket.RequestType & (byte)UsbEndpointDirection.EndpointIn) == 0)
+ lengthTransferred = (inBytes.Length - reqBytes.Length);
+
+ return true;
+ }
+ return false;
+ }
+
+ internal static bool ControlTransfer(SafeHandle interfaceHandle,
+ UsbSetupPacket setupPacket,
+ IntPtr buffer,
+ int bufferLength,
+ out int lengthTransferred,
+ int timeout)
+ {
+ lengthTransferred = 0;
+ LibUsbRequest req = new LibUsbRequest();
+ int code;
+
+ req.Timeout = timeout;
+
+ switch ((UsbRequestType)(setupPacket.RequestType & (0x03 << 5)))
+ {
+ case UsbRequestType.TypeStandard:
+ switch ((UsbStandardRequest)setupPacket.Request)
+ {
+ case UsbStandardRequest.GetStatus:
+ req.Status.Recipient = (int) setupPacket.RequestType & 0x1F;
+ req.Status.Index = setupPacket.Index;
+ code = LibUsbIoCtl.GET_STATUS;
+ break;
+
+ case UsbStandardRequest.ClearFeature:
+ req.Feature.Recipient = (int) setupPacket.RequestType & 0x1F;
+ req.Feature.ID = setupPacket.Value;
+ req.Feature.Index = setupPacket.Index;
+ code = LibUsbIoCtl.CLEAR_FEATURE;
+ break;
+
+ case UsbStandardRequest.SetFeature:
+ req.Feature.Recipient = (int) setupPacket.RequestType & 0x1F;
+ req.Feature.ID = setupPacket.Value;
+ req.Feature.Index = setupPacket.Index;
+ code = LibUsbIoCtl.SET_FEATURE;
+ break;
+
+ case UsbStandardRequest.GetDescriptor:
+ req.Descriptor.Recipient = (int) setupPacket.RequestType & 0x1F;
+ req.Descriptor.Type = (setupPacket.Value >> 8) & 0xFF;
+ req.Descriptor.Index = setupPacket.Value & 0xFF;
+ req.Descriptor.LangID = setupPacket.Index;
+ code = LibUsbIoCtl.GET_DESCRIPTOR;
+ break;
+
+ case UsbStandardRequest.SetDescriptor:
+ req.Descriptor.Recipient = (int) setupPacket.RequestType & 0x1F;
+ req.Descriptor.Type = (setupPacket.Value >> 8) & 0xFF;
+ req.Descriptor.Index = setupPacket.Value & 0xFF;
+ req.Descriptor.LangID = setupPacket.Index;
+ code = LibUsbIoCtl.SET_DESCRIPTOR;
+ break;
+
+ case UsbStandardRequest.GetConfiguration:
+ code = LibUsbIoCtl.GET_CONFIGURATION;
+ break;
+
+ case UsbStandardRequest.SetConfiguration:
+ req.Config.ID = setupPacket.Value;
+ code = LibUsbIoCtl.SET_CONFIGURATION;
+ break;
+
+ case UsbStandardRequest.GetInterface:
+ req.Iface.ID = setupPacket.Index;
+ code = LibUsbIoCtl.GET_INTERFACE;
+ break;
+
+ case UsbStandardRequest.SetInterface:
+ req.Iface.ID = setupPacket.Index;
+ req.Iface.AlternateID = setupPacket.Value;
+ code = LibUsbIoCtl.SET_INTERFACE;
+ break;
+
+ default:
+ UsbError.Error(ErrorCode.IoControlMessage,0,
+ String.Format("Invalid request: 0x{0:X8}", setupPacket.Request),
+ typeof(LibUsbDriverIO));
+ return false;
+ }
+ break;
+
+ case UsbRequestType.TypeVendor:
+ case UsbRequestType.TypeClass:
+
+ req.Vendor.Type = ((byte) setupPacket.RequestType >> 5) & 0x03;
+ req.Vendor.Recipient = (int) setupPacket.RequestType & 0x1F;
+ req.Vendor.Request = (int) setupPacket.Request;
+ req.Vendor.ID = setupPacket.Value;
+ req.Vendor.Index = setupPacket.Index;
+
+ code = ((byte) setupPacket.RequestType & 0x80) > 0 ? LibUsbIoCtl.VENDOR_READ : LibUsbIoCtl.VENDOR_WRITE;
+ break;
+
+ case UsbRequestType.TypeReserved:
+ default:
+ UsbError.Error(ErrorCode.IoControlMessage,0,
+ String.Format("invalid or unsupported request type: 0x{0:X8}", setupPacket.RequestType),
+ typeof(LibUsbDriverIO));
+ return false;
+ }
+
+ /* in request? */
+ Byte[] reqBytes = req.Bytes;
+ Byte[] inBytes = reqBytes;
+ if ((setupPacket.RequestType & (byte)UsbEndpointDirection.EndpointIn) == 0)
+ {
+ inBytes = new byte[LibUsbRequest.Size + bufferLength];
+ reqBytes.CopyTo(inBytes, 0);
+ if (buffer != IntPtr.Zero) Marshal.Copy(buffer, inBytes, LibUsbRequest.Size, bufferLength);
+
+ buffer = IntPtr.Zero;
+ bufferLength = 0;
+ }
+
+ if (UsbIOSync(interfaceHandle, code, inBytes, inBytes.Length, buffer, bufferLength, out lengthTransferred))
+ {
+ /* in request? */
+ if ((setupPacket.RequestType & (byte)UsbEndpointDirection.EndpointIn) == 0)
+ lengthTransferred = (inBytes.Length - reqBytes.Length);
+
+ return true;
+ }
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/LibUsb/Internal/LibUsbIoCtl.cs b/LibWinUsb/LibUsb/Internal/LibUsbIoCtl.cs
new file mode 100644
index 00000000..f0707aff
--- /dev/null
+++ b/LibWinUsb/LibUsb/Internal/LibUsbIoCtl.cs
@@ -0,0 +1,65 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.Internal.LibUsb
+{
+ internal static class LibUsbIoCtl
+ {
+ private const int FILE_ANY_ACCESS = 0;
+ private const int FILE_DEVICE_UNKNOWN = 0x00000022;
+
+ private const int METHOD_BUFFERED = 0;
+ private const int METHOD_IN_DIRECT = 1;
+ private const int METHOD_NEITHER = 3;
+ private const int METHOD_OUT_DIRECT = 2;
+
+ public static readonly int ABORT_ENDPOINT = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80F, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ public static readonly int CLAIM_INTERFACE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x815, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ public static readonly int CLEAR_FEATURE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ public static readonly int CONTROL_TRANSFER = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x903, METHOD_BUFFERED, FILE_ANY_ACCESS);
+
+
+ public static readonly int GET_CONFIGURATION = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ public static readonly int GET_CUSTOM_REG_PROPERTY = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ public static readonly int GET_DESCRIPTOR = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x809, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ public static readonly int GET_INTERFACE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ public static readonly int GET_STATUS = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x807, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ public static readonly int GET_VERSION = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x812, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ public static readonly int GET_REG_PROPERTY = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ public static readonly int INTERRUPT_OR_BULK_READ = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80B, METHOD_OUT_DIRECT, FILE_ANY_ACCESS);
+ public static readonly int INTERRUPT_OR_BULK_WRITE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80A, METHOD_IN_DIRECT, FILE_ANY_ACCESS);
+ public static readonly int ISOCHRONOUS_READ = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x814, METHOD_OUT_DIRECT, FILE_ANY_ACCESS);
+ public static readonly int ISOCHRONOUS_WRITE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x813, METHOD_IN_DIRECT, FILE_ANY_ACCESS);
+ public static readonly int RELEASE_INTERFACE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x816, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ public static readonly int RESET_DEVICE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x810, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ public static readonly int RESET_ENDPOINT = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80E, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ public static readonly int SET_CONFIGURATION = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ public static readonly int SET_DEBUG_LEVEL = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x811, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ public static readonly int SET_DESCRIPTOR = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x808, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ public static readonly int SET_FEATURE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ public static readonly int SET_INTERFACE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ public static readonly int VENDOR_READ = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80D, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ public static readonly int VENDOR_WRITE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80C, METHOD_BUFFERED, FILE_ANY_ACCESS);
+
+
+ private static int CTL_CODE(int DeviceType, int Function, int Method, int Access) { return ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method); }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/LibUsb/Internal/LibUsbRequest.cs b/LibWinUsb/LibUsb/Internal/LibUsbRequest.cs
new file mode 100644
index 00000000..fe151ef9
--- /dev/null
+++ b/LibWinUsb/LibUsb/Internal/LibUsbRequest.cs
@@ -0,0 +1,195 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Descriptors;
+using LibUsbDotNet.Main;
+
+namespace LibUsbDotNet.Internal.LibUsb
+{
+ [StructLayout(LayoutKind.Explicit, Pack = 1, Size = sizeof (int)*6)]
+ internal class LibUsbRequest
+ {
+ public static int Size = Marshal.SizeOf(typeof (LibUsbRequest));
+ [FieldOffset(0)] public int Timeout = UsbConstants.DEFAULT_TIMEOUT;
+
+ #region Union Struct
+
+ [FieldOffset(sizeof (int))] public Control Control;
+
+ [FieldOffset(sizeof (int))] public Config Config;
+
+ [FieldOffset(sizeof (int))] public Debug Debug;
+
+ [FieldOffset(sizeof (int))] public Descriptor Descriptor;
+
+ [FieldOffset(sizeof (int))] public Endpoint Endpoint;
+
+ [FieldOffset(sizeof (int))] public Feature Feature;
+
+ [FieldOffset(sizeof (int))] public Iface Iface;
+
+ [FieldOffset(sizeof (int))] public Status Status;
+
+ [FieldOffset(sizeof (int))] public Vendor Vendor;
+
+ [FieldOffset(sizeof (int))] public UsbKernelVersion Version;
+
+ [FieldOffset(sizeof (int))] public DeviceProperty DeviceProperty;
+
+ [FieldOffset(sizeof (int))] public DeviceRegKey DeviceRegKey;
+
+ [FieldOffset(sizeof (int))] public BusQueryID BusQueryID;
+ #endregion
+
+ public Byte[] Bytes
+ {
+ get
+ {
+ Byte[] rtn = new byte[Size];
+
+ for (int i = 0; i < Size; i++)
+ rtn[i] = Marshal.ReadByte(this, i);
+
+ return rtn;
+ }
+ }
+
+
+ public void RequestConfigDescriptor(int index)
+ {
+ Timeout = UsbConstants.DEFAULT_TIMEOUT;
+
+ int value = ((int) DescriptorType.Configuration << 8) + index;
+
+ Descriptor.Recipient = (byte)UsbEndpointDirection.EndpointIn & 0x1F;
+ Descriptor.Type = (value >> 8) & 0xFF;
+ Descriptor.Index = value & 0xFF;
+ Descriptor.LangID = 0;
+ }
+
+ public void RequestStringDescriptor(int index, short langid)
+ {
+ Timeout = UsbConstants.DEFAULT_TIMEOUT;
+
+ int value = ((int) DescriptorType.String << 8) + index;
+
+ Descriptor.Recipient = (byte)UsbEndpointDirection.EndpointIn & 0x1F;
+ Descriptor.Type = value >> 8 & 0xFF;
+ Descriptor.Index = value & 0xFF;
+ Descriptor.LangID = langid;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct Descriptor
+ {
+ public int Type;
+ public int Index;
+ public int LangID;
+ public int Recipient;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct Config
+ {
+ public int ID;
+ } ;
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct Control
+ {
+ public byte RequestType;
+ public byte Request;
+ public ushort Value;
+ public ushort Index;
+ public ushort Length;
+ } ;
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct DeviceProperty
+ {
+ public int ID;
+ } ;
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct Iface
+ {
+ public int ID;
+ public int AlternateID;
+ } ;
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct Endpoint
+ {
+ public int ID;
+ public int PacketSize;
+ } ;
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct Vendor
+ {
+ public int Type;
+ public int Recipient;
+ public int Request;
+ public int ID;
+ public int Index;
+ } ;
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct Feature
+ {
+ public int Recipient;
+ public int ID;
+ public int Index;
+ } ;
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct Status
+ {
+ public int Recipient;
+ public int Index;
+ public int ID;
+ } ;
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct Debug
+ {
+ public int Level;
+ } ;
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct DeviceRegKey
+ {
+ public int KeyType;
+ public int NameOffset;
+ public int ValueOffset;
+ public int ValueLength;
+ } ;
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct BusQueryID
+ {
+ public ushort IDType;
+ } ;
+
+} \ No newline at end of file
diff --git a/LibWinUsb/LibUsb/LibUsbDevice.cs b/LibWinUsb/LibUsb/LibUsbDevice.cs
new file mode 100644
index 00000000..f154ef34
--- /dev/null
+++ b/LibWinUsb/LibUsb/LibUsbDevice.cs
@@ -0,0 +1,320 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Info;
+using LibUsbDotNet.Internal;
+using LibUsbDotNet.Internal.LibUsb;
+using LibUsbDotNet.Main;
+using Microsoft.Win32.SafeHandles;
+
+namespace LibUsbDotNet.LibUsb
+{
+ /// <summary> Contains members that are specific to the LibUsb-Win32 driver.
+ /// </summary>
+ /// <remarks> Use the <see cref="T:LibUsbDotNet.UsbDevice"/> class instead to allow your code to work with either LibUsb or WinUsb.
+ /// </remarks>
+ public class LibUsbDevice : UsbDevice, IUsbDevice
+ {
+ private readonly List<int> mClaimedInterfaces = new List<int>();
+ private readonly string mDeviceFilename;
+
+
+ internal LibUsbDevice(UsbApiBase api, SafeHandle usbHandle, string deviceFilename)
+ : base(api, usbHandle) { mDeviceFilename = deviceFilename; }
+
+ /// <summary>
+ /// Gets a list of libusb devices directly from the kernel; bypassing the windows registry.
+ /// This function is intended for users that do not use the native kernel driver.
+ /// If using the native kernel (sys) driver supplied with LibUsbDotNet see the <see cref="UsbDevice.AllDevices"/>.
+ /// <seealso cref="UsbGlobals"/>
+ /// <seealso cref="UsbDevice.AllLibUsbDevices"/>
+ /// <seealso cref="UsbDevice.AllWinUsbDevices"/>
+ /// <seealso cref="UsbDevice.OpenUsbDevice(LibUsbDotNet.Main.UsbDeviceFinder)"/>
+ /// </summary>
+ public static List<LibUsbDevice> LegacyLibUsbDeviceList
+ {
+ get
+ {
+ List<LibUsbDevice> deviceList = new List<LibUsbDevice>();
+ for (int i = 1; i < UsbConstants.MAX_DEVICES; i++)
+ {
+ LibUsbDevice newLibUsbDevice;
+ string deviceFileName = LibUsbDriverIO.GetDeviceNameString(i);
+ if (!Open(deviceFileName, out newLibUsbDevice)) continue;
+
+ newLibUsbDevice.mDeviceInfo = new UsbDeviceInfo(newLibUsbDevice);
+ newLibUsbDevice.Close();
+ deviceList.Add(newLibUsbDevice);
+ }
+
+ return deviceList;
+ }
+ }
+
+
+ /// <summary>
+ /// Gets the Device filename for this device.
+ /// </summary>
+ public string DeviceFilename
+ {
+ get { return mDeviceFilename; }
+ }
+
+ #region IUsbDevice Members
+
+ ///<summary>
+ /// Opens the USB device handle.
+ ///</summary>
+ ///<returns>
+ ///True if the device is already opened or was opened successfully.
+ ///False if the device does not exists or is no longer valid.
+ ///</returns>
+ public override bool Open()
+ {
+ if (IsOpen) return true;
+
+ mUsbHandle = LibUsbDriverIO.OpenDevice(mDeviceFilename);
+ if (!IsOpen)
+ {
+ UsbError.Error(ErrorCode.Win32Error,Marshal.GetLastWin32Error(), "LibUsbDevice.Open Failed", this);
+ return false;
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Claims the specified interface of the device.
+ /// </summary>
+ /// <param name="interfaceID">The interface to claim.</param>
+ /// <returns>True on success.</returns>
+ public bool ClaimInterface(int interfaceID)
+ {
+ if (mClaimedInterfaces.Contains(interfaceID)) return true;
+
+ LibUsbRequest req = new LibUsbRequest();
+ req.Iface.ID = interfaceID;
+ req.Timeout = UsbConstants.DEFAULT_TIMEOUT;
+
+ int ret;
+ bool bSuccess = UsbIoSync(LibUsbIoCtl.CLAIM_INTERFACE, req, LibUsbRequest.Size, IntPtr.Zero, 0, out ret);
+ if (bSuccess)
+ mClaimedInterfaces.Add(interfaceID);
+
+ return bSuccess;
+ }
+
+ /// <summary>
+ /// Returns the DriverMode this USB device is using.
+ /// </summary>
+ public override DriverModeType DriverMode
+ {
+ get { return DriverModeType.LibUsb; }
+ }
+
+ /// <summary>
+ /// Closes the <see cref="UsbDevice"/> and disposes any <see cref="UsbDevice.ActiveEndpoints"/>.
+ /// </summary>
+ /// <returns>True on success.</returns>
+ public override bool Close()
+ {
+ if (IsOpen)
+ {
+ ReleaseAllInterfaces();
+ ActiveEndpoints.Clear();
+ mUsbHandle.Close();
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Releases an interface that was previously claimed with <see cref="ClaimInterface"/>.
+ /// </summary>
+ /// <param name="interfaceID">The interface to release.</param>
+ /// <returns>True on success.</returns>
+ public bool ReleaseInterface(int interfaceID)
+ {
+ LibUsbRequest req = new LibUsbRequest();
+ req.Iface.ID = interfaceID;
+ if (!mClaimedInterfaces.Remove(interfaceID)) return true;
+
+ req.Timeout = UsbConstants.DEFAULT_TIMEOUT;
+
+ int ret;
+ // NOTE: A claimed interface is ALWAYS removed from the internal list.
+ bool bSuccess = UsbIoSync(LibUsbIoCtl.RELEASE_INTERFACE, req, LibUsbRequest.Size, IntPtr.Zero, 0, out ret);
+
+ return bSuccess;
+ }
+
+
+ /// <summary>
+ /// Sets an alternate interface for the most recent claimed interface.
+ /// </summary>
+ /// <param name="alternateID">The alternate interface to select for the most recent claimed interface See <see cref="ClaimInterface"/>.</param>
+ /// <returns>True on success.</returns>
+ public bool SetAltInterface(int alternateID)
+ {
+ if (mClaimedInterfaces.Count == 0) throw new UsbException(this, "You must claim an interface before setting an alternate interface.");
+ return SetAltInterface(mClaimedInterfaces[mClaimedInterfaces.Count - 1], alternateID);
+ }
+
+ /// <summary>
+ /// Sets the USB devices active configuration value.
+ /// </summary>
+ /// <param name="config">The active configuration value. A zero value means the device is not configured and a non-zero value indicates the device is configured.</param>
+ /// <returns>True on success.</returns>
+ /// <remarks>
+ /// A USB device can have several different configurations, but only one active configuration.
+ /// </remarks>
+ public bool SetConfiguration(byte config)
+ {
+ int uTransferLength;
+
+ UsbSetupPacket setupPkt = new UsbSetupPacket();
+ setupPkt.RequestType = (byte)UsbEndpointDirection.EndpointOut | (byte)UsbRequestType.TypeStandard | (byte)UsbRequestRecipient.RecipDevice;
+ setupPkt.Request = (byte)UsbStandardRequest.SetConfiguration;
+ setupPkt.Value = config;
+ setupPkt.Index = 0;
+ setupPkt.Length = 0;
+
+ bool bSuccess = ControlTransfer(ref setupPkt, null, 0, out uTransferLength);
+ if (bSuccess)
+ mCurrentConfigValue = config;
+ else
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "SetConfiguration", this);
+
+ return bSuccess;
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Opens the USB device for communucation.
+ /// </summary>
+ /// <param name="deviceFilename">The LibUsb device filename to open.</param>
+ /// <param name="usbDevice">The newly created UsbDevice.</param>
+ /// <returns>True on success.</returns>
+ public static bool Open(string deviceFilename, out LibUsbDevice usbDevice)
+ {
+ usbDevice = null;
+ SafeFileHandle sfh = LibUsbDriverIO.OpenDevice(deviceFilename);
+ if (!sfh.IsClosed && !sfh.IsInvalid)
+ {
+ usbDevice = new LibUsbDevice(LibUsbApi, sfh, deviceFilename);
+ return true;
+ }
+ else
+ {
+// UsbDevice.Error(ErrorCode.DeviceNotFound, "The device is no longer attached or failed to open.", typeof(LibUsbDevice));
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Releases all interface claimed by <see cref="ClaimInterface"/>.
+ /// </summary>
+ /// <returns>True on success.</returns>
+ public int ReleaseAllInterfaces()
+ {
+ int claimedInterfaces = 0;
+ while (mClaimedInterfaces.Count > 0)
+ {
+ claimedInterfaces++;
+ ReleaseInterface(mClaimedInterfaces[mClaimedInterfaces.Count - claimedInterfaces]);
+ }
+
+ return claimedInterfaces;
+ }
+
+ /// <summary>
+ /// Releases the last interface claimed by <see cref="ClaimInterface"/>.
+ /// </summary>
+ /// <returns>True on success.</returns>
+ public bool ReleaseInterface()
+ {
+ //throw new UsbException(this, "You must claim an interface before releasing an interface.");
+ if (mClaimedInterfaces.Count == 0) return true;
+ return ReleaseInterface(mClaimedInterfaces[mClaimedInterfaces.Count - 1]);
+ }
+
+ /// <summary>
+ /// Sets an alternate interface for the specified interface.
+ /// </summary>
+ /// <param name="interfaceID">The interface index to specify an alternate setting for.</param>
+ /// <param name="alternateID">The alternate interface setting.</param>
+ /// <returns>True on success.</returns>
+ public bool SetAltInterface(int interfaceID, int alternateID)
+ {
+ if (!mClaimedInterfaces.Contains(interfaceID))
+ throw new UsbException(this, String.Format("You must claim interface {0} before setting an alternate interface.", interfaceID));
+ LibUsbRequest req = new LibUsbRequest();
+ req.Iface.ID = interfaceID;
+ req.Iface.AlternateID = alternateID;
+ req.Timeout = UsbConstants.DEFAULT_TIMEOUT;
+
+ int ret;
+ return UsbIoSync(LibUsbIoCtl.SET_INTERFACE, req, LibUsbRequest.Size, IntPtr.Zero, 0, out ret);
+ }
+
+ /// <summary>
+ /// Sends a usb device reset command.
+ /// </summary>
+ /// <remarks>
+ /// After calling <see cref="ResetDevice"/>, the <see cref="LibUsbDevice"/> instance is disposed and
+ /// no longer usable. A new <see cref="LibUsbDevice"/> instance must be obtained from the device list.
+ /// </remarks>
+ /// <returns>True on success.</returns>
+ public bool ResetDevice()
+ {
+ bool bSuccess;
+ if (!IsOpen) throw new UsbException(this, "Device is not opened.");
+ ActiveEndpoints.Clear();
+
+ if ((bSuccess = LibUsbApi.ResetDevice(mUsbHandle))!=true)
+ {
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "ResetDevice Failed", this);
+ }
+ else
+ {
+ Close();
+ }
+
+ return bSuccess;
+ }
+
+ internal bool ControlTransferEx(UsbSetupPacket setupPacket,
+ IntPtr buffer,
+ int bufferLength,
+ out int lengthTransferred,
+ int timeout)
+ {
+ bool bSuccess = LibUsbDriverIO.ControlTransferEx(mUsbHandle, setupPacket, buffer, bufferLength, out lengthTransferred, timeout);
+
+
+ return bSuccess;
+ }
+
+ internal bool UsbIoSync(int controlCode, Object inBuffer, int inSize, IntPtr outBuffer, int outSize, out int ret) { return LibUsbDriverIO.UsbIOSync(mUsbHandle, controlCode, inBuffer, inSize, outBuffer, outSize, out ret); }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/LibUsb/LibUsbDeviceRegistryKeyRequest.cs b/LibWinUsb/LibUsb/LibUsbDeviceRegistryKeyRequest.cs
new file mode 100644
index 00000000..e5ee0071
--- /dev/null
+++ b/LibWinUsb/LibUsb/LibUsbDeviceRegistryKeyRequest.cs
@@ -0,0 +1,116 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Text;
+using LibUsbDotNet.Internal.LibUsb;
+using LibUsbDotNet.Main;
+
+namespace LibUsbDotNet.LibUsb
+{
+ internal static class LibUsbDeviceRegistryKeyRequest
+ {
+ public static byte[] RegGetRequest(string name, int valueBufferSize)
+ {
+ if (valueBufferSize < 1 || name.Trim().Length == 0) throw new UsbException("Global", "Invalid DeviceRegistry het parameter.");
+
+ LibUsbRequest req = new LibUsbRequest();
+ int uOffset = LibUsbRequest.Size;
+ req.DeviceRegKey.KeyType = (int) KeyType.RegBinary;
+
+ byte[] bytesName = Encoding.Unicode.GetBytes(name + "\0");
+
+ req.DeviceRegKey.NameOffset = uOffset;
+ uOffset += bytesName.Length;
+ req.DeviceRegKey.ValueOffset = uOffset;
+ req.DeviceRegKey.ValueLength = (valueBufferSize);
+
+ uOffset += Math.Max(uOffset + 1, valueBufferSize - (LibUsbRequest.Size + bytesName.Length));
+ byte[] buffer = new byte[uOffset];
+ byte[] regBytes = req.Bytes;
+
+ Array.Copy(regBytes, buffer, regBytes.Length);
+ Array.Copy(bytesName, 0, buffer, req.DeviceRegKey.NameOffset, bytesName.Length);
+
+ return buffer;
+ }
+
+ public static byte[] RegSetBinaryRequest(string name, byte[] value)
+ {
+ LibUsbRequest req = new LibUsbRequest();
+ int uOffset = LibUsbRequest.Size;
+ req.DeviceRegKey.KeyType = (int) KeyType.RegBinary;
+
+ byte[] bytesName = Encoding.Unicode.GetBytes(name + "\0");
+ byte[] bytesValue = value;
+
+ req.DeviceRegKey.NameOffset = uOffset;
+ uOffset += bytesName.Length;
+ req.DeviceRegKey.ValueOffset = uOffset;
+ req.DeviceRegKey.ValueLength = bytesValue.Length;
+
+ uOffset += bytesValue.Length;
+ byte[] buffer = new byte[uOffset];
+ byte[] regBytes = req.Bytes;
+
+ Array.Copy(regBytes, buffer, regBytes.Length);
+ Array.Copy(bytesName, 0, buffer, req.DeviceRegKey.NameOffset, bytesName.Length);
+ Array.Copy(bytesValue, 0, buffer, req.DeviceRegKey.ValueOffset, bytesValue.Length);
+
+ return buffer;
+ }
+
+ public static byte[] RegSetStringRequest(string name, string value)
+ {
+ LibUsbRequest req = new LibUsbRequest();
+ int uOffset = LibUsbRequest.Size;
+ req.DeviceRegKey.KeyType = (int) KeyType.RegSz;
+
+ byte[] bytesName = Encoding.Unicode.GetBytes(name + "\0");
+ byte[] bytesValue = Encoding.Unicode.GetBytes(value + "\0");
+
+ req.DeviceRegKey.NameOffset = uOffset;
+ uOffset += bytesName.Length;
+ req.DeviceRegKey.ValueOffset = uOffset;
+ req.DeviceRegKey.ValueLength = bytesValue.Length;
+
+ uOffset += bytesValue.Length;
+ byte[] buffer = new byte[uOffset];
+ byte[] regBytes = req.Bytes;
+
+ Array.Copy(regBytes, buffer, regBytes.Length);
+ Array.Copy(bytesName, 0, buffer, req.DeviceRegKey.NameOffset, bytesName.Length);
+ Array.Copy(bytesValue, 0, buffer, req.DeviceRegKey.ValueOffset, bytesValue.Length);
+
+ return buffer;
+ }
+
+ #region Nested Types
+
+ private enum KeyType
+ {
+ RegSz = 1, // Unicode nul terminated string
+ RegBinary = 3, // Free form binary
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/LibUsb/LibUsbKernelType.cs b/LibWinUsb/LibUsb/LibUsbKernelType.cs
new file mode 100644
index 00000000..5a486b28
--- /dev/null
+++ b/LibWinUsb/LibUsb/LibUsbKernelType.cs
@@ -0,0 +1,46 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.LibUsb
+{
+ /// <summary>
+ /// Kernel types supported by LibUsbDotNet. See <see cref="UsbDevice.KernelType"/> for more details.
+ /// </summary>
+ public enum LibUsbKernelType
+ {
+ /// <summary>
+ /// LibUsb support us unavailable.
+ /// </summary>
+ Unknown,
+ /// <summary>
+ /// LibUsbDotNet native kernel driver detected.
+ /// </summary>
+ NativeLibUsb,
+ /// <summary>
+ /// Original libusb-win32 kernel driver detected.
+ /// </summary>
+ LegacyLibUsb,
+ /// <summary>
+ /// mono-linux libusb 1.x driver detected.
+ /// </summary>
+ MonoLibUsb
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/LibUsb/LibUsbRegistry.cs b/LibWinUsb/LibUsb/LibUsbRegistry.cs
new file mode 100644
index 00000000..5204fd1c
--- /dev/null
+++ b/LibWinUsb/LibUsb/LibUsbRegistry.cs
@@ -0,0 +1,321 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+using LibUsbDotNet.Internal.LibUsb;
+using LibUsbDotNet.Main;
+using Microsoft.Win32.SafeHandles;
+using Debug=System.Diagnostics.Debug;
+
+namespace LibUsbDotNet.LibUsb
+{
+ /// <summary> LibUsb specific members for device registry settings.
+ /// </summary>
+ public class LibUsbRegistry : UsbRegistry
+ {
+ private readonly string mDeviceFilename;
+ private readonly int mDeviceIndex;
+
+ private LibUsbRegistry(SafeFileHandle usbHandle, string deviceFileName, int deviceIndex)
+ {
+ mDeviceFilename = deviceFileName;
+ mDeviceIndex = deviceIndex;
+ GetPropertiesSPDRP(usbHandle);
+ string symbolicName;
+
+ if (GetCustomDeviceKeyValue(usbHandle, SYMBOLIC_NAME_KEY, out symbolicName, 512) == ErrorCode.None)
+ {
+ mDeviceProperties.Add(SYMBOLIC_NAME_KEY, symbolicName);
+ }
+
+ // If the SymbolicName key does not exists, use the first HardwareID string.
+ if (!mDeviceProperties.ContainsKey(SYMBOLIC_NAME_KEY) || String.IsNullOrEmpty(symbolicName))
+ {
+ string[] hwIDs = mDeviceProperties[SPDRP.HardwareId.ToString()] as string[];
+
+ if ((hwIDs == null) || hwIDs.Length==0)
+ {
+ LibUsbDevice usbDevice = new LibUsbDevice(UsbDevice.LibUsbApi, usbHandle, deviceFileName);
+ LegacyUsbRegistry.GetPropertiesSPDRP(usbDevice, mDeviceProperties);
+ return;
+ }
+
+ if (hwIDs.Length > 0)
+ {
+ mDeviceProperties.Add(SYMBOLIC_NAME_KEY, hwIDs[0]);
+ }
+ }
+
+ string deviceInterfaceGuids;
+ if (GetCustomDeviceKeyValue(usbHandle, LIBUSB_INTERFACE_GUIDS, out deviceInterfaceGuids, 512) == ErrorCode.None)
+ {
+ string[] deviceInterfaceGuidsArray = deviceInterfaceGuids.Split(new char[] {'\0'}, StringSplitOptions.RemoveEmptyEntries);
+
+ mDeviceProperties.Add(LIBUSB_INTERFACE_GUIDS, deviceInterfaceGuidsArray);
+ }
+ }
+
+ /// <summary>
+ /// Gets the 0 based index of this libusb device
+ /// </summary>
+ public int DeviceIndex
+ {
+ get { return mDeviceIndex; }
+ }
+
+ /// <summary>
+ /// Gets a list of available LibUsb devices.
+ /// </summary>
+ public static List<LibUsbRegistry> DeviceList
+ {
+ get
+ {
+ List<LibUsbRegistry> deviceList = new List<LibUsbRegistry>();
+ for (int i = 1; i < UsbConstants.MAX_DEVICES; i++)
+ {
+ string deviceFileName = LibUsbDriverIO.GetDeviceNameString(i);
+
+ SafeFileHandle deviceHandle = LibUsbDriverIO.OpenDevice(deviceFileName);
+ if (deviceHandle != null && !deviceHandle.IsInvalid && !deviceHandle.IsClosed)
+ {
+ try
+ {
+ LibUsbRegistry regInfo = new LibUsbRegistry(deviceHandle, deviceFileName, i);
+ //System.Diagnostics.Debug.Print("Address:{0}, Index:{1}, {2}", regInfo[SPDRP.Address], i, regInfo[SPDRP.DeviceDesc]);
+ deviceList.Add(regInfo);
+ }
+ catch (Exception ex)
+ {
+ Debug.Print(ex.Message);
+ }
+ }
+ if (deviceHandle != null && !deviceHandle.IsClosed) deviceHandle.Close();
+ }
+
+ return deviceList;
+ }
+ }
+
+ /// <summary>
+ /// Check this value to determine if the usb device is still connected to the bus and ready to open.
+ /// </summary>
+ public override bool IsAlive
+ {
+ get
+ {
+ if (String.IsNullOrEmpty(SymbolicName)) throw new UsbException(this, "A symbolic name is required for this property.");
+ List<LibUsbRegistry> deviceList = DeviceList;
+ foreach (LibUsbRegistry registry in deviceList)
+ {
+ if (String.IsNullOrEmpty(registry.SymbolicName)) continue;
+
+ if (registry.SymbolicName == SymbolicName)
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Opens the USB device for communucation.
+ /// </summary>
+ /// <returns>Return a new instance of the <see cref="UsbDevice"/> class.
+ /// If the device fails to open a null refrence is return. For extended error
+ /// information use the <see cref="UsbDevice.UsbErrorEvent"/>.
+ /// </returns>
+ public override UsbDevice Device
+ {
+ get
+ {
+ LibUsbDevice libUsbDevice;
+ Open(out libUsbDevice);
+ return libUsbDevice;
+ }
+ }
+
+ /// <summary>
+ /// Gets the DeviceInterfaceGuids for the WinUsb device.
+ /// </summary>
+ public override Guid[] DeviceInterfaceGuids
+ {
+ get
+ {
+ if (ReferenceEquals(mDeviceInterfaceGuids, null))
+ {
+ if (!mDeviceProperties.ContainsKey(LIBUSB_INTERFACE_GUIDS)) return new Guid[0];
+
+ string[] saDeviceInterfaceGuids = mDeviceProperties[LIBUSB_INTERFACE_GUIDS] as string[];
+ if (ReferenceEquals(saDeviceInterfaceGuids, null)) return new Guid[0];
+
+ mDeviceInterfaceGuids = new Guid[saDeviceInterfaceGuids.Length];
+
+ for (int i = 0; i < saDeviceInterfaceGuids.Length; i++)
+ {
+ string sGuid = saDeviceInterfaceGuids[i].Trim(new char[] {' ', '{', '}', '[', ']', '\0'});
+ mDeviceInterfaceGuids[i] = new Guid(sGuid);
+ }
+ }
+ return mDeviceInterfaceGuids;
+ }
+ }
+
+ /// <summary>
+ /// Opens the USB device for communucation.
+ /// </summary>
+ /// <param name="usbDevice">The newly created UsbDevice.</param>
+ /// <returns>True on success.</returns>
+ public bool Open(out LibUsbDevice usbDevice)
+ {
+ bool bSuccess = LibUsbDevice.Open(mDeviceFilename, out usbDevice);
+ if (bSuccess)
+ {
+ usbDevice.mUsbRegistry = this;
+ }
+
+ return bSuccess;
+ }
+
+ /// <summary>
+ /// Opens the USB device for communucation.
+ /// </summary>
+ /// <param name="usbDevice">The newly created UsbDevice.</param>
+ /// <returns>True on success.</returns>
+ public override bool Open(out UsbDevice usbDevice)
+ {
+ usbDevice = null;
+ LibUsbDevice libUsbDevice;
+ bool bSuccess = Open(out libUsbDevice);
+ if (bSuccess)
+ usbDevice = libUsbDevice;
+ return bSuccess;
+ }
+
+ internal ErrorCode GetCustomDeviceKeyValue(SafeFileHandle usbHandle, string key, out string propData, int maxDataLength)
+ {
+ byte[] propDataBytes;
+ ErrorCode eReturn = GetCustomDeviceKeyValue(usbHandle, key, out propDataBytes, maxDataLength);
+ if (eReturn == ErrorCode.None)
+ {
+ propData = Encoding.Unicode.GetString(propDataBytes);
+ propData.TrimEnd(new char[] {'\0'});
+ }
+ else
+ {
+ propData = null;
+ }
+
+ return eReturn;
+ }
+
+ internal ErrorCode GetCustomDeviceKeyValue(SafeFileHandle usbHandle, string key, out byte[] propData, int maxDataLength)
+ {
+ ErrorCode eReturn = ErrorCode.None;
+ int iReturnBytes;
+ propData = null;
+ byte[] bytesReq = LibUsbDeviceRegistryKeyRequest.RegGetRequest(key, maxDataLength);
+ GCHandle gcbytesReq = GCHandle.Alloc(bytesReq, GCHandleType.Pinned);
+
+ bool bSuccess = LibUsbDriverIO.UsbIOSync(usbHandle,
+ LibUsbIoCtl.GET_CUSTOM_REG_PROPERTY,
+ bytesReq,
+ bytesReq.Length,
+ gcbytesReq.AddrOfPinnedObject(),
+ bytesReq.Length,
+ out iReturnBytes);
+ gcbytesReq.Free();
+ if (bSuccess)
+ {
+ propData = new byte[iReturnBytes];
+ Array.Copy(bytesReq, propData, iReturnBytes);
+ }
+ else
+ {
+ eReturn = ErrorCode.GetDeviceKeyValueFailed;
+ // dont log this as an error;
+ //UsbError.Error(eReturn,0, "Failed getting device registry Key:" + key, this);
+ }
+ return eReturn;
+ }
+
+ private void GetPropertiesSPDRP(SafeHandle usbHandle)
+ {
+ byte[] propBuffer = new byte[1024];
+ GCHandle gcPropBuffer = GCHandle.Alloc(propBuffer, GCHandleType.Pinned);
+
+ LibUsbRequest req = new LibUsbRequest();
+ Dictionary<string, int> allProps = Helper.GetEnumData(typeof (DevicePropertyType));
+ foreach (KeyValuePair<string, int> prop in allProps)
+ {
+ object oValue = String.Empty;
+
+ req.DeviceProperty.ID = prop.Value;
+ int iReturnBytes;
+ bool bSuccess = LibUsbDriverIO.UsbIOSync(usbHandle,
+ LibUsbIoCtl.GET_REG_PROPERTY,
+ req,
+ LibUsbRequest.Size,
+ gcPropBuffer.AddrOfPinnedObject(),
+ propBuffer.Length,
+ out iReturnBytes);
+ if (bSuccess)
+ {
+ switch ((DevicePropertyType) prop.Value)
+ {
+ case DevicePropertyType.PhysicalDeviceObjectName:
+ case DevicePropertyType.LocationInformation:
+ case DevicePropertyType.Class:
+ case DevicePropertyType.Mfg:
+ case DevicePropertyType.DeviceDesc:
+ case DevicePropertyType.Driver:
+ case DevicePropertyType.EnumeratorName:
+ case DevicePropertyType.FriendlyName:
+ case DevicePropertyType.ClassGuid:
+ oValue = GetAsString(propBuffer, iReturnBytes);
+ break;
+ case DevicePropertyType.HardwareId:
+ case DevicePropertyType.CompatibleIds:
+ oValue = GetAsStringArray(propBuffer, iReturnBytes);
+ break;
+ case DevicePropertyType.BusNumber:
+ case DevicePropertyType.InstallState:
+ case DevicePropertyType.LegacyBusType:
+ case DevicePropertyType.RemovalPolicy:
+ case DevicePropertyType.UiNumber:
+ case DevicePropertyType.Address:
+ oValue = GetAsStringInt32(propBuffer, iReturnBytes);
+ break;
+ case DevicePropertyType.BusTypeGuid:
+ oValue = GetAsGuid(propBuffer, iReturnBytes);
+ break;
+ }
+ }
+ else
+ oValue = String.Empty;
+
+ mDeviceProperties.Add(prop.Key, oValue);
+ }
+ gcPropBuffer.Free();
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/ControlEpLockType.cs b/LibWinUsb/Main/ControlEpLockType.cs
new file mode 100644
index 00000000..e1081329
--- /dev/null
+++ b/LibWinUsb/Main/ControlEpLockType.cs
@@ -0,0 +1,54 @@
+// Copyright © 2006-2009 Travis Robinson. All rights reserved.
+//
+// website: sourceforge.net/projects/libusbdotnet/
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.Main
+{
+ /// <summary> The locking strategy for endpoint 0 operations in regards to any pending endpoint data operations.
+ /// </summary>
+ /// <remarks> Some USB devices have problems handling endpoint 0 control messages when other endpoints on the device have pending IO operations.
+ /// Must be combined with <see cref="LibUsbDotNet.Main.DeviceLockType.Locked"/>.
+ /// </remarks>
+ public enum ControlEpLockType
+ {
+ /// <summary>
+ /// Endpoint 0 transfers do not interfere with data endpoint transfers in any way. This is the default.
+ /// </summary>
+ None,
+ /// <summary>
+ /// If data endpoints for the device remain busy for longer than <see cref="UsbDevice.DeviceLockTimeout"/>, then force an IO cancel operation for the busy endpoints.
+ /// </summary>
+ /// <remarks>
+ /// There is a potential for loss of data when using this option.
+ /// This will immediately cancel pending I/O transfers on all data endpoints when a enpoint 0 control transfer is initiated.
+ /// </remarks>
+ CancelIoOnLockTimeout,
+ /// <summary>
+ /// If data endpoints for the device remain busy for longer than <see cref="UsbDevice.DeviceLockTimeout"/>, then consider the remaining endpoints with IO pending operation as idle and continue with operation.
+ /// This option is the same as ErrorOnLockTimeout only instead of returning with an error after the lock timeout period, an attempt is made to transfer data anyways. (Ignoring the lock)
+ /// </summary>
+ ContinueOnLockTimeout,
+ /// <summary>
+ /// If data endpoints for the device remain busy for longer than <see cref="UsbDevice.DeviceLockTimeout"/>, then return a LockTimeout error code.
+ /// Setting this value will lock ALL the devices data endpoints (1-15) before transfering data to the control enpoint 0.
+ /// </summary>
+ ErrorOnLockTimeout
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/DataEpLockType.cs b/LibWinUsb/Main/DataEpLockType.cs
new file mode 100644
index 00000000..4b667db8
--- /dev/null
+++ b/LibWinUsb/Main/DataEpLockType.cs
@@ -0,0 +1,44 @@
+// Copyright © 2006-2009 Travis Robinson. All rights reserved.
+//
+// website: sourceforge.net/projects/libusbdotnet/
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary> Data endpoint locking strategy.
+ /// </summary>
+ [Flags]
+ public enum DataEpLockType
+ {
+ /// <summary>
+ /// Don't lock the device IO functions.
+ /// </summary>
+ /// <remarks>
+ /// This option is not thread/proccess safe.
+ /// </remarks>
+ None,
+ /// <summary>
+ /// Use a semapore to lock data endpoint IO operations. This prevents multiple threads/proccesses from accessing
+ /// the same <see cref="UsbEndpointBase.EpNum"/> at the same time.
+ /// </summary>
+ Locked,
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/DataReceivedEnabledChangedEventArgs.cs b/LibWinUsb/Main/DataReceivedEnabledChangedEventArgs.cs
new file mode 100644
index 00000000..11aa7bc6
--- /dev/null
+++ b/LibWinUsb/Main/DataReceivedEnabledChangedEventArgs.cs
@@ -0,0 +1,59 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary>
+ /// Event arguments that are passed when <see cref="UsbEndpointReader.DataReceivedEnabled"/> is changes state.
+ /// </summary>
+ public class DataReceivedEnabledChangedEventArgs : EventArgs
+ {
+ private readonly bool mEnabled;
+ private readonly ErrorCode mErrorCode = ErrorCode.Success;
+
+ internal DataReceivedEnabledChangedEventArgs(bool enabled, ErrorCode errorCode)
+ {
+ mEnabled = enabled;
+ mErrorCode = errorCode;
+ }
+
+ internal DataReceivedEnabledChangedEventArgs(bool enabled)
+ : this(enabled, ErrorCode.Success) { }
+
+ /// <summary>
+ /// The <see cref="Main.ErrorCode"/> that caused the <see cref="UsbEndpointReader.DataReceived"/> event to terminate.
+ /// </summary>
+ public ErrorCode ErrorCode
+ {
+ get { return mErrorCode; }
+ }
+
+ /// <summary>
+ /// <c>True</c> if <see cref="UsbEndpointReader.DataReceivedEnabled"/> changes from <c>True</c> to <c>False</c>.
+ /// </summary>
+ public bool Enabled
+ {
+ get { return mEnabled; }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/DeviceLockType.cs b/LibWinUsb/Main/DeviceLockType.cs
new file mode 100644
index 00000000..56fa76c5
--- /dev/null
+++ b/LibWinUsb/Main/DeviceLockType.cs
@@ -0,0 +1,48 @@
+// Copyright © 2006-2009 Travis Robinson. All rights reserved.
+//
+// website: sourceforge.net/projects/libusbdotnet/
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary> The locking strategy for endpoint 0 operations per proccess/thread
+ /// </summary>
+ [Flags]
+ public enum DeviceLockType
+ {
+ /// <summary>
+ /// Don't lock the device IO functions.
+ /// </summary>
+ /// <remarks>
+ /// This option is not thread/proccess safe.
+ /// </remarks>
+ None,
+ /// <summary>
+ /// Use a global semapore to lock endpoint I/O operations. This prevents multiple threads/proccesses from accessing
+ /// the <see cref="UsbDevice"/> IO functions (IE <see cref="UsbDevice.ControlTransfer(ref UsbSetupPacket,object,int,out int)"/><see cref="UsbDevice.GetString"/>, etc..) at the same time.
+ /// </summary>
+ /// <remarks>
+ /// Using this option will allow your LibUsbDotNet applications to comunicate cooperatively with the same USB device.
+ /// NOTE: Usb devices using the WinUsb.dll driver can't be shared by multiple processes.
+ /// </remarks>
+ Locked,
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/DevicePropertyType.cs b/LibWinUsb/Main/DevicePropertyType.cs
new file mode 100644
index 00000000..026ff32e
--- /dev/null
+++ b/LibWinUsb/Main/DevicePropertyType.cs
@@ -0,0 +1,101 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.Main
+{
+ /// <summary> Standard Windows registry properties for USB devices and other hardware.
+ /// </summary>
+ public enum DevicePropertyType
+ {
+ /// <summary>
+ /// Requests a string describing the device, such as "Microsoft PS/2 Port Mouse", typically defined by the manufacturer.
+ /// </summary>
+ DeviceDesc = 0,
+ /// <summary>
+ /// Requests the hardware IDs provided by the device that identify the device.
+ /// </summary>
+ HardwareId = 1,
+ /// <summary>
+ /// Requests the compatible IDs reported by the device.
+ /// </summary>
+ CompatibleIds = 2,
+ /// <summary>
+ /// Requests the name of the device's setup class, in text format.
+ /// </summary>
+ Class = 5,
+ /// <summary>
+ /// Requests the GUID for the device's setup class.
+ /// </summary>
+ ClassGuid = 6,
+ /// <summary>
+ /// Requests the name of the driver-specific registry key.
+ /// </summary>
+ Driver = 7,
+ /// <summary>
+ /// Requests a string identifying the manufacturer of the device.
+ /// </summary>
+ Mfg = 8,
+ /// <summary>
+ /// Requests a string that can be used to distinguish between two similar devices, typically defined by the class installer.
+ /// </summary>
+ FriendlyName = 9,
+ /// <summary>
+ /// Requests information about the device's location on the bus; the interpretation of this information is bus-specific.
+ /// </summary>
+ LocationInformation = 10,
+ /// <summary>
+ /// Requests the name of the PDO for this device.
+ /// </summary>
+ PhysicalDeviceObjectName = 11,
+ /// <summary>
+ /// Requests the GUID for the bus that the device is connected to.
+ /// </summary>
+ BusTypeGuid = 12,
+ /// <summary>
+ /// Requests the bus type, such as PCIBus or PCMCIABus.
+ /// </summary>
+ LegacyBusType = 13,
+ /// <summary>
+ /// Requests the legacy bus number of the bus the device is connected to.
+ /// </summary>
+ BusNumber = 14,
+ /// <summary>
+ /// Requests the name of the enumerator for the device, such as "USB".
+ /// </summary>
+ EnumeratorName = 15,
+ /// <summary>
+ /// Requests the address of the device on the bus.
+ /// </summary>
+ Address = 16,
+ /// <summary>
+ /// Requests a number associated with the device that can be displayed in the user interface.
+ /// </summary>
+ UiNumber = 17,
+ /// <summary>
+ /// Windows XP and later.) Requests the device's installation state.
+ /// </summary>
+ InstallState = 18,
+ /// <summary>
+ /// (Windows XP and later.) Requests the device's current removal policy. The operating system uses this value as a hint to determine how the device is normally removed.
+ /// </summary>
+ RemovalPolicy = 19
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/EndpointDataEventArgs.cs b/LibWinUsb/Main/EndpointDataEventArgs.cs
new file mode 100644
index 00000000..28135a03
--- /dev/null
+++ b/LibWinUsb/Main/EndpointDataEventArgs.cs
@@ -0,0 +1,58 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary> Endpoint data received arguments returned by the <see cref="E:LibUsbDotNet.UsbEndpointReader.DataReceived"/> event.
+ /// </summary>
+ public class EndpointDataEventArgs : EventArgs
+ {
+ private readonly byte[] mBytesReceived;
+ private readonly int mCount;
+
+ internal EndpointDataEventArgs(byte[] bytes, int size)
+ {
+ mBytesReceived = bytes;
+ mCount = size;
+ }
+
+ /// <summary>
+ /// Gets the buffer of the received data.
+ /// </summary>
+ /// <remarks>
+ /// Use the <see cref="EndpointDataEventArgs.Count"/> property to determine the number of bytes actually received.
+ /// </remarks>
+ public byte[] Buffer
+ {
+ get { return mBytesReceived; }
+ }
+
+ /// <summary>
+ /// Gets the number of bytes received.
+ /// </summary>
+ public int Count
+ {
+ get { return mCount; }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/EndpointType.cs b/LibWinUsb/Main/EndpointType.cs
new file mode 100644
index 00000000..8a341fbf
--- /dev/null
+++ b/LibWinUsb/Main/EndpointType.cs
@@ -0,0 +1,48 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary> All possible USB endpoint types.
+ /// </summary>
+ [Flags]
+ public enum EndpointType : byte
+ {
+ /// <summary>
+ /// Control endpoint type.
+ /// </summary>
+ Control,
+ /// <summary>
+ /// Isochronous endpoint type.
+ /// </summary>
+ Isochronous,
+ /// <summary>
+ /// Bulk endpoint type.
+ /// </summary>
+ Bulk,
+ /// <summary>
+ /// Interrupt endpoint type.
+ /// </summary>
+ Interrupt
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/ErrorCode.cs b/LibWinUsb/Main/ErrorCode.cs
new file mode 100644
index 00000000..651c3b64
--- /dev/null
+++ b/LibWinUsb/Main/ErrorCode.cs
@@ -0,0 +1,184 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+
+using MonoLibUsb;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary>
+ /// General area in which the failure occurred. See the <see cref="UsbError"/> class.
+ /// </summary>
+ public enum ErrorCode
+ {
+ /// <summary>
+ /// No error. (None, Success, and Ok)
+ /// </summary>
+ None = 0,
+ /// <summary>
+ /// No error.
+ /// </summary>
+ Success = 0,
+ /// <summary>
+ /// No error.
+ /// </summary>
+ Ok = 0,
+ /// <summary>
+ /// The USB device has errors in its Configuration descriptor.
+ /// </summary>
+ InvalidConfig = -16384,
+ /// <summary>
+ /// A synchronous device IO operation failed.
+ /// </summary>
+ IoSyncFailed,
+ /// <summary>
+ /// A request for a string failed.
+ /// </summary>
+ GetString,
+ /// <summary>
+ /// A specified endpoint is invalid for the operation.
+ /// </summary>
+ InvalidEndpoint,
+ /// <summary>
+ /// A request to cancel IO operation failed.
+ /// </summary>
+ AbortEndpoint,
+ /// <summary>
+ /// A call to the core Win32 API DeviceIOControl failed.
+ /// </summary>
+ DeviceIoControl,
+ /// <summary>
+ /// A call to the core Win32 API GetOverlappedResult failed.
+ /// </summary>
+ GetOverlappedResult,
+ /// <summary>
+ /// An Endpoints receive thread was dangerously terminated.
+ /// </summary>
+ ReceiveThreadTerminated,
+ /// <summary>
+ /// A write operation failed.
+ /// </summary>
+ WriteFailed,
+ /// <summary>
+ /// A read operation failed.
+ /// </summary>
+ ReadFailed,
+ /// <summary>
+ /// An endpoint 0 IO control message failed.
+ /// </summary>
+ IoControlMessage,
+ /// <summary>
+ /// The action of cancelling the IO operation failed.
+ /// </summary>
+ CancelIoFailed,
+ /// <summary>
+ /// An IO operation was cancelled by the user before it completed.
+ /// </summary>
+ /// <remarks>
+ /// IoCancelled errors may occur as normal operation; for this reason they are not logged as a <see cref="UsbError"/>.
+ /// </remarks>
+ IoCancelled,
+ /// <summary>
+ /// An IO operation timed out before it completed.
+ /// </summary>
+ /// <remarks>
+ /// IoTimedOut errors may occur as normal operation; for this reason they are not logged as a <see cref="UsbError"/>.
+ /// </remarks>
+ IoTimedOut,
+ /// <summary>
+ /// An IO operation was cancelled and will be re-submiited when ready.
+ /// </summary>
+ /// <remarks>
+ /// IoEndpointGlobalCancelRedo errors may occur as normal operation; for this reason they are not logged as a <see cref="UsbError"/>.
+ /// </remarks>
+ IoEndpointGlobalCancelRedo,
+ /// <summary>
+ /// Failed retrieving a custom USB device key value.
+ /// </summary>
+ GetDeviceKeyValueFailed,
+ /// <summary>
+ /// Failed setting a custom USB device key value.
+ /// </summary>
+ SetDeviceKeyValueFailed,
+ /// <summary>
+ /// The error is a standard windows error.
+ /// </summary>
+ Win32Error,
+ /// <summary>
+ /// An attempt was made to lock a device that is already locked.
+ /// </summary>
+ DeviceAllreadyLocked,
+ /// <summary>
+ /// An attempt was made to lock an endpoint that is already locked.
+ /// </summary>
+ EndpointAllreadyLocked,
+ /// <summary>
+ /// The USB device request failed because the USB device was not found.
+ /// </summary>
+ DeviceNotFound,
+ /// <summary>
+ /// Operation was intentionally cancelled by the user or application.
+ /// </summary>
+ UserAborted,
+ /// <summary>
+ /// Invalid parameter.
+ /// </summary>
+ InvalidParam,
+
+ /// <summary>
+ /// Access denied (insufficient permissions).
+ /// </summary>
+ AccessDenied,
+ /// <summary>
+ /// Resource Busy.
+ /// </summary>
+ ResourceBusy,
+ /// <summary>
+ /// Overflow.
+ /// </summary>
+ Overflow,
+ /// <summary>
+ /// Pipe error or endpoint halted.
+ /// </summary>
+ PipeError,
+ /// <summary>
+ /// System call interrupted (perhaps due to signal).
+ /// </summary>
+ Interrupted,
+
+ /// <summary>
+ /// Insufficient memory.
+ /// </summary>
+ InsufficientMemory,
+ /// <summary>
+ /// Operation not supported or unimplemented on this platform.
+ /// </summary>
+ NotSupported,
+ /// <summary>
+ /// Unknown or other error.
+ /// </summary>
+ UnknownError,
+ /// <summary>
+ /// The error is one of the <see cref="MonoUsbError"/>
+ /// </summary>
+ MonoApiError
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/Helper.cs b/LibWinUsb/Main/Helper.cs
new file mode 100644
index 00000000..9b3ee539
--- /dev/null
+++ b/LibWinUsb/Main/Helper.cs
@@ -0,0 +1,283 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary>
+ /// General utilities class used by LudnLite and exposed publicly for your convience.
+ /// </summary>
+ public static class Helper
+ {
+ private static object mIsLinux;
+ private static OperatingSystem mOs;
+
+ /// <summary>
+ /// Gets the <see cref="OperatingSystem"/> class.
+ /// </summary>
+ public static OperatingSystem OSVersion
+ {
+ get
+ {
+ if (ReferenceEquals(mOs, null))
+ mOs = Environment.OSVersion;
+
+ return mOs;
+ }
+ }
+
+ /// <summary>
+ /// True if running on a unix-like operating system.
+ /// False if using the Libusb-1.0 windows backend driver.
+ /// </summary>
+ public static bool IsLinux
+ {
+ get
+ {
+ if (ReferenceEquals(mIsLinux, null))
+ {
+ switch (OSVersion.Platform.ToString())
+ {
+ case "Win32S":
+ case "Win32Windows":
+ case "Win32NT":
+ case "WinCE":
+ case "Xbox":
+ mIsLinux = false;
+ break;
+ case "Unix":
+ case "MacOSX":
+ mIsLinux = true;
+ break;
+ default:
+ throw new NotSupportedException(string.Format("Operating System:{0} not supported.", OSVersion));
+ }
+ }
+ return (bool)mIsLinux;
+ }
+ }
+
+ /// <summary>
+ /// Copies bytes to a blittable object.
+ /// </summary>
+ /// <param name="sourceBytes">bytes to copy</param>
+ /// <param name="iStartIndex">Start index</param>
+ /// <param name="iLength">number of bytes to copy</param>
+ /// <param name="destObject">blittable destination object</param>
+ public static void BytesToObject(byte[] sourceBytes, int iStartIndex, int iLength, object destObject)
+ {
+ GCHandle gch = GCHandle.Alloc(destObject, GCHandleType.Pinned);
+
+ IntPtr ptrDestObject = gch.AddrOfPinnedObject();
+ Marshal.Copy(sourceBytes, iStartIndex, ptrDestObject, iLength);
+
+ gch.Free();
+ }
+
+ /// <summary>
+ /// Returns a dictionary object of enumeration names and values.
+ /// </summary>
+ /// <param name="type">They <see cref="Type"/> of enumeration.</param>
+ /// <returns>A <see cref="Dictionary{TKey,TValue}"/> enumeration of names and values.</returns>
+ public static Dictionary<string, int> GetEnumData(Type type)
+ {
+ Dictionary<string, int> dictEnum = new Dictionary<string, int>();
+ FieldInfo[] enumFields = type.GetFields();
+ for (int iField = 1; iField < enumFields.Length; iField++)
+ {
+ object oValue = enumFields[iField].GetRawConstantValue();
+ dictEnum.Add(enumFields[iField].Name, Convert.ToInt32(oValue));
+ }
+
+ return dictEnum;
+ }
+
+
+ /// <summary>
+ /// Swaps low and high bytes on big endian systems. Has no effect on little endian systems.
+ /// </summary>
+ /// <param name="swapValue">The value to convert.</param>
+ /// <returns>a swapped value an big endian system, the same value on little endian systems</returns>
+ public static short HostEndianToLE16(short swapValue)
+ {
+ HostEndian16BitValue rtn = new HostEndian16BitValue(swapValue);
+ return (short)rtn.U16;
+ }
+
+ /// <summary>
+ /// Converts standard values to decorated hex string values.
+ /// </summary>
+ /// <param name="standardValue">The value to convert.</param>
+ /// <returns>A string representing <paramref name="standardValue"/> in hex display format.</returns>
+ public static string ShowAsHex(object standardValue)
+ {
+ if (standardValue == null) return "";
+ if (standardValue is Int64) return "0x" + ((Int64)standardValue).ToString("X16");
+ if (standardValue is UInt32) return "0x" + ((UInt32)standardValue).ToString("X8");
+ if (standardValue is Int32) return "0x" + ((Int32)standardValue).ToString("X8");
+ if (standardValue is UInt16) return "0x" + ((UInt16)standardValue).ToString("X4");
+ if (standardValue is Int16) return "0x" + ((Int16)standardValue).ToString("X4");
+ if (standardValue is Byte) return "0x" + ((Byte)standardValue).ToString("X2");
+ if (standardValue is String) return HexString(standardValue as byte[], "", " ");
+
+ return "";
+ }
+
+ /// <summary>
+ /// Builds a delimited string of names and values.
+ /// </summary>
+ /// <param name="sep0">Inserted and the begining of the entity.</param>
+ /// <param name="names">The list of names for the object values.</param>
+ /// <param name="sep1">Inserted between the name and value.</param>
+ /// <param name="values">The values for the names.</param>
+ /// <param name="sep2">Inserted and the end of the entity.</param>
+ /// <returns>The formatted string.</returns>
+ public static string ToString(string sep0, string[] names, string sep1, object[] values, string sep2)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ for (int i = 0; i < names.Length; i++)
+ sb.Append(sep0 + names[i] + sep1 + values[i] + sep2);
+
+ return sb.ToString();
+ }
+
+ #region Nested Types
+
+ [StructLayout(LayoutKind.Explicit, Pack = 1)]
+ internal struct HostEndian16BitValue
+ {
+ public HostEndian16BitValue(short x)
+ {
+ U16 = 0;
+ B1 = (byte)(x >> 8);
+ B0 = (byte)(x & 0xff);
+ }
+
+ [FieldOffset(0)]
+ public readonly ushort U16;
+
+ [FieldOffset(0)]
+ public readonly byte B0;
+
+ [FieldOffset(1)]
+ public readonly byte B1;
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Builds a formatted hexidecimal string from an array of bytes.
+ /// </summary>
+ /// <param name="data">the byte array</param>
+ /// <param name="prefix">string to place before each byte</param>
+ /// <param name="suffix">string to place after each byte</param>
+ /// <returns>a formatted hex string</returns>
+ public static string HexString(byte[] data, string prefix, string suffix)
+ {
+ if (prefix == null) prefix = String.Empty;
+ if (suffix == null) suffix = String.Empty;
+
+ StringBuilder sb = new StringBuilder((data.Length * 2) + (data.Length * prefix.Length) + (data.Length * suffix.Length));
+ foreach (byte b in data)
+ sb.Append(prefix + b.ToString("X2") + suffix);
+
+ return sb.ToString();
+ }
+
+ }
+ /// <summary>
+ /// Used for allocating a <see cref="GCHandle"/> to access the underlying pointer of an object.
+ /// </summary>
+ public class PinnedHandle : IDisposable
+ {
+ private readonly IntPtr mPtr = IntPtr.Zero;
+ private bool mFreeGcBuffer;
+ private GCHandle mGcObject;
+
+
+ /// <summary>
+ /// Creates a pinned object.
+ /// </summary>
+ /// <param name="objectToPin">
+ /// The object can be any blittable class, or array. If a <see cref="GCHandle"/> is passed it will be used "as-is" and no pinning will take place.
+ /// </param>
+ public PinnedHandle(object objectToPin)
+ {
+ if (!ReferenceEquals(objectToPin, null))
+ {
+ mFreeGcBuffer = GetPinnedObjectHandle(objectToPin, out mGcObject);
+ mPtr = mGcObject.AddrOfPinnedObject();
+ }
+ }
+
+ /// <summary>
+ /// The raw pointer in memory of the pinned object.
+ /// </summary>
+ public IntPtr Handle
+ {
+ get { return mPtr; }
+ }
+
+ #region IDisposable Members
+
+ /// <summary>
+ /// Frees and disposes the <see cref="GCHandle"/> for this pinned object.
+ /// </summary>
+ /// <filterpriority>2</filterpriority>
+ public void Dispose()
+ {
+ if ((mFreeGcBuffer) && mGcObject.IsAllocated)
+ {
+ mFreeGcBuffer = false;
+ mGcObject.Free();
+ }
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Disposes the gchande for the object if ibe is allocated.
+ /// </summary>
+ ~PinnedHandle() { Dispose(); }
+
+ private static bool GetPinnedObjectHandle(object objectToPin, out GCHandle pinnedObject)
+ {
+ bool bFreeGcBuffer = false;
+
+ if (objectToPin is GCHandle)
+ pinnedObject = (GCHandle)objectToPin;
+ else
+ {
+ pinnedObject = GCHandle.Alloc(objectToPin, GCHandleType.Pinned);
+ bFreeGcBuffer = true;
+ }
+
+ return bFreeGcBuffer;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/LegacyUsbRegistry.cs b/LibWinUsb/Main/LegacyUsbRegistry.cs
new file mode 100644
index 00000000..37c7f674
--- /dev/null
+++ b/LibWinUsb/Main/LegacyUsbRegistry.cs
@@ -0,0 +1,245 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using LibUsbDotNet.Internal.LibUsb;
+using LibUsbDotNet.LibUsb;
+using LibUsbDotNet.LudnMonoLibUsb;
+using Microsoft.Win32.SafeHandles;
+using Debug=System.Diagnostics.Debug;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary>
+ /// LibUsb specific members for device registry settings.
+ /// This legacy class does not actually query the windows registry as the other Registry classes do.
+ /// Instead, it wraps a <see cref="LibUsbDevice"/> and queries descriptors directly from the device
+ /// using usb IO control messages.
+ /// </summary>
+ public class LegacyUsbRegistry : UsbRegistry
+ {
+
+ private readonly UsbDevice mUSBDevice;
+ internal LegacyUsbRegistry(UsbDevice usbDevice)
+ {
+ mUSBDevice = usbDevice;
+ GetPropertiesSPDRP(mUSBDevice, mDeviceProperties);
+ }
+
+ /// <summary>
+ /// Opens the USB device for communucation.
+ /// </summary>
+ /// <returns>Return a new instance of the <see cref="UsbDevice"/> class.
+ /// If the device fails to open a null refrence is return. For extended error
+ /// information use the <see cref="UsbDevice.UsbErrorEvent"/>.
+ /// </returns>
+ public override UsbDevice Device
+ {
+ get
+ {
+ UsbDevice libUsbDevice;
+ Open(out libUsbDevice);
+ return libUsbDevice;
+ }
+ }
+
+ /// <summary>
+ /// Gets the DeviceInterfaceGuids for the WinUsb device.
+ /// </summary>
+ public override Guid[] DeviceInterfaceGuids
+ {
+ get
+ {
+ if (ReferenceEquals(mDeviceInterfaceGuids, null))
+ {
+ if (!mDeviceProperties.ContainsKey(LIBUSB_INTERFACE_GUIDS)) return new Guid[0];
+
+ string[] saDeviceInterfaceGuids = mDeviceProperties[LIBUSB_INTERFACE_GUIDS] as string[];
+ if (ReferenceEquals(saDeviceInterfaceGuids, null)) return new Guid[0];
+
+ mDeviceInterfaceGuids = new Guid[saDeviceInterfaceGuids.Length];
+
+ for (int i = 0; i < saDeviceInterfaceGuids.Length; i++)
+ {
+ string sGuid = saDeviceInterfaceGuids[i].Trim(new char[] {' ', '{', '}', '[', ']', '\0'});
+ mDeviceInterfaceGuids[i] = new Guid(sGuid);
+ }
+ }
+ return mDeviceInterfaceGuids;
+ }
+ }
+
+ /// <summary>
+ /// Check this value to determine if the usb device is still connected to the bus and ready to open.
+ /// </summary>
+ /// <remarks>
+ /// Uses the symbolic name as a unique id to determine if this device instance is still attached.
+ /// </remarks>
+ /// <exception cref="UsbException">An exception is thrown if the <see cref="UsbRegistry.SymbolicName"/> property is null or empty.</exception>
+ public override bool IsAlive
+ {
+ get
+ {
+ if (String.IsNullOrEmpty(SymbolicName)) throw new UsbException(this, "A symbolic name is required for this property.");
+ List<LegacyUsbRegistry> deviceList = DeviceList;
+ foreach (LegacyUsbRegistry registry in deviceList)
+ {
+ if (String.IsNullOrEmpty(registry.SymbolicName)) continue;
+
+ if (registry.SymbolicName == SymbolicName)
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Gets a list of available LibUsb devices.
+ /// </summary>
+ ///
+ public static List<LegacyUsbRegistry> DeviceList
+ {
+ get
+ {
+ List<LegacyUsbRegistry> deviceList = new List<LegacyUsbRegistry>();
+ if (UsbDevice.IsLinux)
+ {
+ List<MonoUsbDevice> legacyLibUsbDeviceList = MonoUsbDevice.MonoUsbDeviceList;
+ foreach (MonoUsbDevice usbDevice in legacyLibUsbDeviceList)
+ {
+ deviceList.Add(new LegacyUsbRegistry(usbDevice));
+ }
+ }
+ else
+ {
+ for (int i = 1; i < UsbConstants.MAX_DEVICES; i++)
+ {
+ string deviceFileName = LibUsbDriverIO.GetDeviceNameString(i);
+
+ SafeFileHandle deviceHandle = LibUsbDriverIO.OpenDevice(deviceFileName);
+ if (deviceHandle != null && !deviceHandle.IsInvalid && !deviceHandle.IsClosed)
+ {
+ try
+ {
+ LibUsbDevice newUsbDevice = new LibUsbDevice(UsbDevice.LibUsbApi, deviceHandle, deviceFileName);
+
+ LegacyUsbRegistry regInfo = new LegacyUsbRegistry(newUsbDevice);
+
+ deviceList.Add(regInfo);
+ }
+ catch (Exception ex)
+ {
+ Debug.Print(ex.Message);
+ }
+ }
+ if (deviceHandle != null && !deviceHandle.IsClosed) deviceHandle.Close();
+ }
+ }
+ return deviceList;
+ }
+ }
+
+ ///// <summary>
+ ///// ProductID
+ ///// </summary>
+ //public override int Pid
+ //{
+ // get { return (int)((ushort)mUSBDevice.Info.Descriptor.ProductID); }
+ //}
+
+ ///// <summary>
+ ///// VendorID
+ ///// </summary>
+ //public override int Vid
+ //{
+ // get { return (int)((ushort)mUSBDevice.Info.Descriptor.VendorID); }
+ //}
+
+ /// <summary>
+ /// Usb device revision number.
+ /// </summary>
+ public override int Rev
+ {
+ get
+ {
+ int bcdRev;
+ string s = mUSBDevice.Info.Descriptor.BcdDevice.ToString("X4");
+ if (int.TryParse(s, out bcdRev))
+ {
+ return bcdRev;
+ }
+ return (int)((ushort)mUSBDevice.Info.Descriptor.BcdDevice);
+ }
+ }
+
+ internal static string GetRegistryHardwareID(ushort vid, ushort pid, ushort rev)
+ {
+ return string.Format("Vid_{0:X4}&Pid_{1:X4}&Rev_{2}", vid, pid, rev.ToString("0000"));
+ }
+
+ /// <summary>
+ /// Opens the USB device for communucation.
+ /// </summary>
+ /// <param name="usbDevice">The newly created UsbDevice.</param>
+ /// <returns>True on success.</returns>
+ public override bool Open(out UsbDevice usbDevice)
+ {
+ usbDevice = null;
+ bool bSuccess = mUSBDevice.Open();
+ if (bSuccess)
+ {
+ usbDevice = mUSBDevice;
+ usbDevice.mUsbRegistry = this;
+ }
+
+ return bSuccess;
+ }
+
+ internal static void GetPropertiesSPDRP(UsbDevice usbDevice, Dictionary<string, object> deviceProperties)
+ {
+
+
+ deviceProperties.Add(DevicePropertyType.Mfg.ToString(),
+ usbDevice.Info.Descriptor.ManufacturerStringIndex > 0 ? usbDevice.Info.ManufacturerString : string.Empty);
+
+ deviceProperties.Add(DevicePropertyType.DeviceDesc.ToString(),
+ usbDevice.Info.Descriptor.ProductStringIndex > 0 ? usbDevice.Info.ProductString : string.Empty);
+
+ deviceProperties.Add("SerialNumber",
+ usbDevice.Info.Descriptor.SerialStringIndex > 0 ? usbDevice.Info.SerialString : string.Empty);
+
+ string fakeHardwareIds = GetRegistryHardwareID((ushort)usbDevice.Info.Descriptor.VendorID,
+ (ushort)usbDevice.Info.Descriptor.ProductID,
+ (ushort)usbDevice.Info.Descriptor.BcdDevice);
+
+ deviceProperties.Add(DevicePropertyType.HardwareId.ToString(), new string[] { fakeHardwareIds });
+
+ string fakeSymbolicName = fakeHardwareIds + "{" + Guid.Empty + " }";
+
+ if (usbDevice.Info.Descriptor.SerialStringIndex > 0)
+ {
+ fakeSymbolicName += "#" + deviceProperties["SerialNumber"] + "#";
+ }
+ deviceProperties.Add(SYMBOLIC_NAME_KEY, fakeSymbolicName);
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/ReadEndpointID.cs b/LibWinUsb/Main/ReadEndpointID.cs
new file mode 100644
index 00000000..0ae4ec80
--- /dev/null
+++ b/LibWinUsb/Main/ReadEndpointID.cs
@@ -0,0 +1,90 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.Main
+{
+ /// <summary>
+ /// Availabled endpoint numbers/ids for reading.
+ /// </summary>
+ public enum ReadEndpointID : byte
+ {
+ /// <summary>
+ /// Endpoint 1
+ /// </summary>
+ Ep01 = 0x81,
+ /// <summary>
+ /// Endpoint 2
+ /// </summary>
+ Ep02 = 0x82,
+ /// <summary>
+ /// Endpoint 3
+ /// </summary>
+ Ep03 = 0x83,
+ /// <summary>
+ /// Endpoint 4
+ /// </summary>
+ Ep04 = 0x84,
+ /// <summary>
+ /// Endpoint 5
+ /// </summary>
+ Ep05 = 0x85,
+ /// <summary>
+ /// Endpoint 6
+ /// </summary>
+ Ep06 = 0x86,
+ /// <summary>
+ /// Endpoint 7
+ /// </summary>
+ Ep07 = 0x87,
+ /// <summary>
+ /// Endpoint 8
+ /// </summary>
+ Ep08 = 0x88,
+ /// <summary>
+ /// Endpoint 9
+ /// </summary>
+ Ep09 = 0x89,
+ /// <summary>
+ /// Endpoint 10
+ /// </summary>
+ Ep10 = 0x8A,
+ /// <summary>
+ /// Endpoint 11
+ /// </summary>
+ Ep11 = 0x8B,
+ /// <summary>
+ /// Endpoint 12
+ /// </summary>
+ Ep12 = 0x8C,
+ /// <summary>
+ /// Endpoint 13
+ /// </summary>
+ Ep13 = 0x8D,
+ /// <summary>
+ /// Endpoint 14
+ /// </summary>
+ Ep14 = 0x8E,
+ /// <summary>
+ /// Endpoint 15
+ /// </summary>
+ Ep15 = 0x8F,
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/SPDRP.cs b/LibWinUsb/Main/SPDRP.cs
new file mode 100644
index 00000000..0973a036
--- /dev/null
+++ b/LibWinUsb/Main/SPDRP.cs
@@ -0,0 +1,110 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary>
+ /// Device registry property codes
+ /// </summary>
+ [Flags]
+ public enum SPDRP
+ {
+ /// <summary>
+ /// Requests a string describing the device, such as "Microsoft PS/2 Port Mouse", typically defined by the manufacturer.
+ /// </summary>
+ DeviceDesc = (0x00000000),
+ /// <summary>
+ /// Requests the hardware IDs provided by the device that identify the device.
+ /// </summary>
+ HardwareId = (0x00000001),
+ /// <summary>
+ /// Requests the compatible IDs reported by the device.
+ /// </summary>
+ CompatibleIds = (0x00000002),
+ /// <summary>
+ /// Requests the name of the device's setup class, in text format.
+ /// </summary>
+ Class = (0x00000007),
+ /// <summary>
+ /// Requests the GUID for the device's setup class.
+ /// </summary>
+ ClassGuid = (0x00000008),
+ /// <summary>
+ /// Requests the name of the driver-specific registry key.
+ /// </summary>
+ Driver = (0x00000009),
+ /// <summary>
+ /// Requests a string identifying the manufacturer of the device.
+ /// </summary>
+ Mfg = (0x0000000B),
+ /// <summary>
+ /// Requests a string that can be used to distinguish between two similar devices, typically defined by the class installer.
+ /// </summary>
+ FriendlyName = (0x0000000C),
+ /// <summary>
+ /// Requests information about the device's location on the bus; the interpretation of this information is bus-specific.
+ /// </summary>
+ LocationInformation = (0x0000000D),
+ /// <summary>
+ /// Requests the name of the PDO for this device.
+ /// </summary>
+ PhysicalDeviceObjectName = (0x0000000E),
+ /// <summary>
+ /// Requests a number associated with the device that can be displayed in the user interface.
+ /// </summary>
+ UiNumber = (0x00000010),
+ /// <summary>
+ /// Requests the GUID for the bus that the device is connected to.
+ /// </summary>
+ BusTypeGuid = (0x00000013),
+ /// <summary>
+ /// Requests the bus type, such as PCIBus or PCMCIABus.
+ /// </summary>
+ LegacyBusType = (0x00000014),
+ /// <summary>
+ /// Requests the legacy bus number of the bus the device is connected to.
+ /// </summary>
+ BusNumber = (0x00000015),
+ /// <summary>
+ /// Requests the name of the enumerator for the device, such as "USB".
+ /// </summary>
+ EnumeratorName = (0x00000016),
+ /// <summary>
+ /// Requests the address of the device on the bus.
+ /// </summary>
+ Address = (0x0000001C),
+ /// <summary>
+ /// (Windows XP and later.) Requests the device's current removal policy. The operating system uses this value as a hint to determine how the device is normally removed.
+ /// </summary>
+ RemovalPolicy = (0x0000001F),
+ /// <summary>
+ /// Windows XP and later.) Requests the device's installation state.
+ /// </summary>
+ InstallState = (0x00000022),
+ /// <summary>
+ /// Device Location Paths (R)
+ /// </summary>
+ LocationPaths=(0x00000023),
+
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/SafeContextHandle.cs b/LibWinUsb/Main/SafeContextHandle.cs
new file mode 100644
index 00000000..5d0b04eb
--- /dev/null
+++ b/LibWinUsb/Main/SafeContextHandle.cs
@@ -0,0 +1,65 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary>
+ /// Base class for all critial handles.
+ /// </summary>
+ public abstract class SafeContextHandle : SafeHandle
+ {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="pHandle"></param>
+ /// <param name="ownsHandle"></param>
+ protected SafeContextHandle(IntPtr pHandle, bool ownsHandle)
+ : base(IntPtr.Zero, ownsHandle) { SetHandle(pHandle); }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="pHandleToOwn"></param>
+ protected SafeContextHandle(IntPtr pHandleToOwn)
+ : this(pHandleToOwn, true) { }
+
+ /// <summary>
+ /// Gets a value indicating whether the handle value is invalid.
+ /// </summary>
+ /// <returns>
+ /// true if the handle value is invalid; otherwise, false.
+ /// </returns>
+ /// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode"/></PermissionSet>
+ public override bool IsInvalid
+ {
+ get
+ {
+ if (handle != IntPtr.Zero)
+ {
+ return (handle == new IntPtr(-1));
+ }
+ return true;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/SetupApiRegistry.cs b/LibWinUsb/Main/SetupApiRegistry.cs
new file mode 100644
index 00000000..1878b3e7
--- /dev/null
+++ b/LibWinUsb/Main/SetupApiRegistry.cs
@@ -0,0 +1,210 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+using LibUsbDotNet.Internal;
+using LibUsbDotNet.LudnMonoLibUsb;
+using Microsoft.Win32;
+using MonoLibUsb;
+using System.Runtime.InteropServices;
+
+namespace LibUsbDotNet.Main
+{
+ internal static class SetupApiRegistry
+ {
+ private static readonly Object mLockSetupApiRegistry = new object();
+ private static readonly MasterList mMasterSetupApiDeviceList = new MasterList();
+ private static DateTime mLastRefreshTime = DateTime.MinValue;
+ public const string DEVICE_ID_KEY = "DeviceInstanceID";
+
+ public static bool NeedsRefresh
+ {
+ get
+ {
+ lock (mLockSetupApiRegistry)
+ {
+ if ((DateTime.Now - mLastRefreshTime).TotalMilliseconds >= 1000)
+ return true;
+ return false;
+ }
+ }
+ }
+
+ private class MasterItem : Dictionary<string, object>
+ {
+ public Dictionary<Guid, List<string>> DevicePaths = new Dictionary<Guid, List<string>>();
+ }
+
+ private class MasterList : List<MasterItem>
+ {
+ }
+
+ public static bool FillDeviceProperties(UsbRegistry usbRegistry, UsbDevice usbDevice)
+ {
+
+ lock (mLockSetupApiRegistry)
+ {
+ if (NeedsRefresh) BuildMasterList();
+ if (usbDevice is MonoUsbDevice && !Helper.IsLinux)
+ return FillWindowsMonoUsbDeviceRegistry(usbRegistry, (MonoUsbDevice) usbDevice);
+
+ string fakeHwId = LegacyUsbRegistry.GetRegistryHardwareID((ushort) usbDevice.Info.Descriptor.VendorID,
+ (ushort) usbDevice.Info.Descriptor.ProductID,
+ (ushort) usbDevice.Info.Descriptor.BcdDevice);
+ bool bFound = false;
+ string hwIdToFind = fakeHwId.ToLower();
+ foreach (MasterItem masterItem in mMasterSetupApiDeviceList)
+ {
+ string[] hwIds = masterItem[SPDRP.HardwareId.ToString()] as string[];
+ if (ReferenceEquals(hwIds, null)) continue;
+ foreach (string hwID in hwIds)
+ {
+ if (hwID.ToLower().Contains(hwIdToFind))
+ {
+ usbRegistry.mDeviceProperties = masterItem;
+ bFound = true;
+ break;
+ }
+ }
+ if (bFound) break;
+ }
+ return bFound;
+ }
+ }
+
+ private static bool FillWindowsMonoUsbDeviceRegistry(UsbRegistry usbRegistry, MonoUsbDevice usbDevice)
+ {
+ MonoLibUsb.MonoUsbApi.internal_windows_device_priv priv = MonoLibUsb.MonoUsbApi.GetWindowsPriv(usbDevice.Profile.ProfileHandle);
+ string path;
+ for (int i = 0; i < 32; i++)
+ {
+ if (priv.usb_interfaces[i].path == IntPtr.Zero) break;
+ path = Marshal.PtrToStringAnsi(priv.usb_interfaces[i].path);
+ //Debug.Print("Intf:{0} Path:{1}",i,path);
+ }
+ path = Marshal.PtrToStringAnsi(priv.path);
+
+ bool bFound = false;
+
+ //System.Diagnostics.Debug.WriteLine(sb.ToString());
+ path = path.ToString().ToLower().Replace("#", "\\");
+ foreach (MasterItem masterItem in mMasterSetupApiDeviceList)
+ {
+ if (path.Contains(masterItem[DEVICE_ID_KEY].ToString().ToLower()))
+ {
+ usbRegistry.mDeviceProperties = masterItem;
+ bFound = true;
+ break;
+ }
+ }
+ return bFound;
+ }
+
+ public static void BuildMasterList()
+ {
+ lock (mLockSetupApiRegistry)
+ {
+ mMasterSetupApiDeviceList.Clear();
+ SetupApi.EnumClassDevs(null, SetupApi.DICFG.PRESENT | SetupApi.DICFG.ALLCLASSES, BuildMasterCallback, mMasterSetupApiDeviceList);
+ mLastRefreshTime = DateTime.Now;
+ }
+ }
+
+ private static bool BuildMasterCallback(IntPtr deviceInfoSet, int deviceindex, ref SetupApi.SP_DEVINFO_DATA deviceInfoData, object userData)
+ {
+ MasterList deviceList = userData as MasterList;
+ MasterItem deviceItem = new MasterItem();
+ StringBuilder sb=new StringBuilder(256);
+
+ if (SetupApi.CM_Get_Device_ID(deviceInfoData.DevInst, sb, sb.Capacity, 0)!=SetupApi.CR.SUCCESS)
+ return false;
+
+ deviceItem.Add(DEVICE_ID_KEY,sb.ToString());
+ deviceList.Add(deviceItem);
+
+
+ RegistryValueKind propertyType;
+ byte[] propBuffer = new byte[256];
+ int requiredSize;
+ bool bSuccess = SetupApi.SetupDiGetCustomDeviceProperty(deviceInfoSet,
+ ref deviceInfoData,
+ UsbRegistry.DEVICE_INTERFACE_GUIDS,
+ SetupApi.DICUSTOMDEVPROP.NONE,
+ out propertyType,
+ propBuffer,
+ propBuffer.Length,
+ out requiredSize);
+ if (bSuccess)
+ {
+ string[] devInterfaceGuids = UsbRegistry.GetAsStringArray(propBuffer, requiredSize);
+
+ deviceItem.Add(UsbRegistry.DEVICE_INTERFACE_GUIDS, devInterfaceGuids);
+ foreach (string s in devInterfaceGuids)
+ {
+ Guid g = new Guid(s);
+ List<string> devicePathList;
+ if (WinUsb.WinUsbRegistry.GetDevicePathList(g, out devicePathList))
+ {
+ deviceItem.DevicePaths.Add(g, devicePathList);
+ }
+ }
+ }
+ else
+ {
+ bSuccess = SetupApi.SetupDiGetCustomDeviceProperty(deviceInfoSet,
+ ref deviceInfoData,
+ UsbRegistry.LIBUSB_INTERFACE_GUIDS,
+ SetupApi.DICUSTOMDEVPROP.NONE,
+ out propertyType,
+ propBuffer,
+ propBuffer.Length,
+ out requiredSize);
+ if (bSuccess)
+ {
+ string[] devInterfaceGuids = UsbRegistry.GetAsStringArray(propBuffer, requiredSize);
+
+ deviceItem.Add(UsbRegistry.LIBUSB_INTERFACE_GUIDS, devInterfaceGuids);
+ }
+ }
+
+ bSuccess =
+ SetupApi.SetupDiGetCustomDeviceProperty(deviceInfoSet,
+ ref deviceInfoData,
+ UsbRegistry.SYMBOLIC_NAME_KEY,
+ SetupApi.DICUSTOMDEVPROP.NONE,
+ out propertyType,
+ propBuffer,
+ propBuffer.Length,
+ out requiredSize);
+ if (bSuccess)
+ {
+ string symbolicName = UsbRegistry.GetAsString(propBuffer, requiredSize);
+ deviceItem.Add(UsbRegistry.SYMBOLIC_NAME_KEY, symbolicName);
+ }
+ SetupApi.getSPDRPProperties(deviceInfoSet, ref deviceInfoData, deviceItem);
+
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/UsbConstants.cs b/LibWinUsb/Main/UsbConstants.cs
new file mode 100644
index 00000000..26496531
--- /dev/null
+++ b/LibWinUsb/Main/UsbConstants.cs
@@ -0,0 +1,66 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.Main
+{
+ /// <summary> Various USB constants.
+ /// </summary>
+ public static class UsbConstants
+ {
+ /// <summary>
+ /// Default timeout for all USB IO operations.
+ /// </summary>
+ public const int DEFAULT_TIMEOUT = 1000;
+
+ internal const bool EXIT_CONTEXT = false;
+
+ /// <summary>
+ /// Maximum size of a config descriptor.
+ /// </summary>
+ public const int MAX_CONFIG_SIZE = 4096;
+
+ /// <summary>
+ /// Maximum number of USB devices.
+ /// </summary>
+ public const int MAX_DEVICES = 128;
+
+ /// <summary>
+ /// Maximum number of endpoints per device.
+ /// </summary>
+ public const int MAX_ENDPOINTS = 32;
+
+ /// <summary>
+ /// Endpoint direction mask.
+ /// </summary>
+ public const byte ENDPOINT_DIR_MASK = 0x80;
+
+ /// <summary>
+ /// Endpoint number mask.
+ /// </summary>
+ public const byte ENDPOINT_NUMBER_MASK = 0xf;
+
+ ///// <summary>
+ ///// See <see cref="UsbError.Handled"/>. Number of RETRIES before failed regardless of the handled field value.
+ ///// </summary>
+ //public const int MAX_FAIL_RETRIES_ON_HANDLED_ERROR = 4;
+
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/UsbCtrlFlags.cs b/LibWinUsb/Main/UsbCtrlFlags.cs
new file mode 100644
index 00000000..d1a6fcdd
--- /dev/null
+++ b/LibWinUsb/Main/UsbCtrlFlags.cs
@@ -0,0 +1,73 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+// ReSharper disable InconsistentNaming
+namespace LibUsbDotNet.Main
+{
+ ///<summary>For Convienience Endpoint direction, recipient of the request, and request type on one enumeration.</summary>
+ [Flags]
+ public enum UsbCtrlFlags : byte
+ {
+ /// <summary>
+ /// In Direction
+ /// </summary>
+ Direction_In = 0x80,
+ /// <summary>
+ /// Out Direction
+ /// </summary>
+ Direction_Out = 0x00,
+
+ /// <summary>
+ /// Device is recipient.
+ /// </summary>
+ Recipient_Device = 0x00,
+ /// <summary>
+ /// Endpoint is recipient.
+ /// </summary>
+ Recipient_Endpoint = 0x02,
+ /// <summary>
+ /// Interface is recipient.
+ /// </summary>
+ Recipient_Interface = 0x01,
+ /// <summary>
+ /// Other is recipient.
+ /// </summary>
+ Recipient_Other = 0x03,
+
+ /// <summary>
+ /// Class specific request.
+ /// </summary>
+ RequestType_Class = (0x01 << 5),
+ /// <summary>
+ /// RESERVED.
+ /// </summary>
+ RequestType_Reserved = (0x03 << 5),
+ /// <summary>
+ /// Standard request.
+ /// </summary>
+ RequestType_Standard = (0x00 << 5),
+ /// <summary>
+ /// Vendor specific request.
+ /// </summary>
+ RequestType_Vendor = (0x02 << 5),
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/UsbDeviceFinder.cs b/LibWinUsb/Main/UsbDeviceFinder.cs
new file mode 100644
index 00000000..2c3e6321
--- /dev/null
+++ b/LibWinUsb/Main/UsbDeviceFinder.cs
@@ -0,0 +1,319 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters.Binary;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary>
+ /// Finds and identifies usb devices. Used for easily locating
+ /// </summary>
+ /// <remarks>
+ /// <list type="bullet">
+ /// <item>
+ /// Instances of this class can optionally be passed directly into
+ /// <see cref="UsbDevice.OpenUsbDevice(LibUsbDotNet.Main.UsbDeviceFinder)"/>
+ /// to quickly find and open a specific usb device in one step.
+ /// </item>
+ /// <item>
+ /// Pass instances of this class into the
+ /// <see cref="UsbRegDeviceList.Find(UsbDeviceFinder)"/>,
+ /// <see cref="UsbRegDeviceList.FindAll(UsbDeviceFinder)"/>,
+ /// or <see cref="UsbRegDeviceList.FindLast(UsbDeviceFinder)"/>
+ /// functions of a <see cref="UsbRegDeviceList"/>
+ /// instance to find connected usb devices without opening devices or interrogating the bus.
+ /// After locating the required <see cref="UsbRegistry"/> instance, call the
+ /// <see cref="UsbRegistry.Open"/> method to start using the <see cref="UsbDevice"/> instance.
+ /// </item>
+ /// </list>
+ /// </remarks>
+ /// <example>
+ /// <code source="..\Examples\Show.Info\ShowInfo.cs" lang="cs"/>
+ /// </example>
+ public class UsbDeviceFinder : ISerializable
+ {
+ ///<summary> The "exclude from search" value for <see cref="Pid"/>. </summary>
+ public const int NO_PID = int.MaxValue;
+
+ ///<summary> The "exclude from search" value for <see cref="Revision"/>. </summary>
+ public const int NO_REV = int.MaxValue;
+
+ ///<summary> The "exclude from search" value for <see cref="SerialNumber"/>. </summary>
+ public const string NO_SERIAL = null;
+
+ ///<summary> The "exclude from search" value for <see cref="Vid"/>. </summary>
+ public const int NO_VID = int.MaxValue;
+
+ ///<summary> The "exclude from search" value for <see cref="DeviceInterfaceGuid"/>. </summary>
+ public static readonly Guid NO_GUID = Guid.Empty;
+
+ private Guid mDeviceInterfaceGuid = Guid.Empty;
+ private int mPid = int.MaxValue;
+ private int mRevision = int.MaxValue;
+ private string mSerialNumber;
+ private int mVid = int.MaxValue;
+
+ /// <summary>
+ /// Creates a UsbDeviceFinder class for locating and identifying usb devices.
+ /// </summary>
+ /// <param name="vid">The vendor id of the usb device to find, or <see cref="int.MaxValue"/> to ignore.</param>
+ /// <param name="pid">The product id of the usb device to find, or <see cref="int.MaxValue"/> to ignore.</param>
+ /// <param name="revision">The revision number of the usb device to find, or <see cref="int.MaxValue"/> to ignore.</param>
+ /// <param name="serialNumber">The serial number of the usb device to find, or null to ignore.</param>
+ /// <param name="deviceInterfaceGuid">The unique guid of the usb device to find, or <see cref="Guid.Empty"/> to ignore.</param>
+ public UsbDeviceFinder(int vid, int pid, int revision, string serialNumber, Guid deviceInterfaceGuid)
+ {
+ mVid = vid;
+ mPid = pid;
+ mRevision = revision;
+ mSerialNumber = serialNumber;
+ mDeviceInterfaceGuid = deviceInterfaceGuid;
+ }
+
+ /// <summary>
+ /// Creates a UsbDeviceFinder class for locating usb devices by VendorID, ProductID, and Serial number.
+ /// </summary>
+ /// <param name="vid">The vendor id of the usb device to find.</param>
+ /// <param name="pid">The product id of the usb device to find.</param>
+ /// <param name="serialNumber">The serial number of the usb device to find.</param>
+ public UsbDeviceFinder(int vid, int pid, string serialNumber)
+ : this(vid, pid, int.MaxValue, serialNumber, Guid.Empty) { }
+
+ /// <summary>
+ /// Creates a UsbDeviceFinder class for locating usb devices by VendorID, ProuctID, and Revision code.
+ /// </summary>
+ /// <param name="vid">The vendor id of the usb device to find.</param>
+ /// <param name="pid">The product id of the usb device to find.</param>
+ /// <param name="revision">The revision number of the usb device to find.</param>
+ public UsbDeviceFinder(int vid, int pid, int revision)
+ : this(vid, pid, revision, null, Guid.Empty) { }
+
+ /// <summary>
+ /// Creates a UsbDeviceFinder class for locating usb devices vendor and product ID.
+ /// </summary>
+ /// <param name="vid">The vendor id of the usb device to find.</param>
+ /// <param name="pid">The product id of the usb device to find.</param>
+ public UsbDeviceFinder(int vid, int pid)
+ : this(vid, pid, int.MaxValue, null, Guid.Empty) { }
+
+ /// <summary>
+ /// Creates a UsbDeviceFinder class for locating usb devices.
+ /// </summary>
+ /// <param name="vid">The vendor id of the usb device to find.</param>
+ public UsbDeviceFinder(int vid)
+ : this(vid, int.MaxValue, int.MaxValue, null, Guid.Empty) { }
+
+ /// <summary>
+ /// Creates a UsbDeviceFinder class for locating usb devices by a serial number.
+ /// </summary>
+ /// <param name="serialNumber">The serial number of the usb device to find.</param>
+ public UsbDeviceFinder(string serialNumber)
+ : this(int.MaxValue, int.MaxValue, int.MaxValue, serialNumber, Guid.Empty) { }
+
+ /// <summary>
+ /// Creates a UsbDeviceFinder class for locating usb devices by a unique <see cref="Guid"/> string.
+ /// </summary>
+ /// <param name="deviceInterfaceGuid">The unique <see cref="Guid"/> to find.</param>
+ public UsbDeviceFinder(Guid deviceInterfaceGuid)
+ : this(int.MaxValue, int.MaxValue, int.MaxValue, null, deviceInterfaceGuid) { }
+
+ /// <summary>
+ /// Use a serialization stream to fill the <see cref="UsbDeviceFinder"/> class.
+ /// </summary>
+ /// <param name="info"></param>
+ /// <param name="context"></param>
+ protected UsbDeviceFinder(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+
+ mVid = (int) info.GetValue("Vid", typeof (int));
+ mPid = (int) info.GetValue("Pid", typeof (int));
+ mRevision = (int) info.GetValue("Revision", typeof (int));
+ mSerialNumber = (string) info.GetValue("SerialNumber", typeof (string));
+ mDeviceInterfaceGuid = (Guid) info.GetValue("DeviceInterfaceGuid", typeof (Guid));
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ protected UsbDeviceFinder() { }
+
+ /// <summary>
+ /// The device interface guid string to find, or <see cref="String.Empty"/> to ignore.
+ /// </summary>
+ public Guid DeviceInterfaceGuid
+ {
+ get { return mDeviceInterfaceGuid; }
+ set { mDeviceInterfaceGuid = value; }
+ }
+
+ /// <summary>
+ /// The serial number of the device to find.
+ /// </summary>
+ /// <remarks>
+ /// Set to null to ignore.
+ /// </remarks>
+ public string SerialNumber
+ {
+ get { return mSerialNumber; }
+ set { mSerialNumber = value; }
+ }
+
+ /// <summary>
+ /// The revision number of the device to find.
+ /// </summary>
+ /// <remarks>
+ /// Set to <see cref="int.MaxValue"/> to ignore.
+ /// </remarks>
+ public int Revision
+ {
+ get { return mRevision; }
+ set { mRevision = value; }
+ }
+
+ /// <summary>
+ /// The product id of the device to find.
+ /// </summary>
+ /// <remarks>
+ /// Set to <see cref="int.MaxValue"/> to ignore.
+ /// </remarks>
+ public int Pid
+ {
+ get { return mPid; }
+ set { mPid = value; }
+ }
+
+ /// <summary>
+ /// The vendor id of the device to find.
+ /// </summary>
+ /// <remarks>
+ /// Set to <see cref="int.MaxValue"/> to ignore.
+ /// </remarks>
+ public int Vid
+ {
+ get { return mVid; }
+ set { mVid = value; }
+ }
+
+ #region ISerializable Members
+
+ /// <summary>
+ /// Store this class as a binary serializtion object.
+ /// </summary>
+ /// <param name="info">The serialization instance to populate.</param>
+ /// <param name="context"></param>
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+
+ info.AddValue("Vid", mVid);
+ info.AddValue("Pid", mPid);
+ info.AddValue("Revision", mRevision);
+ info.AddValue("SerialNumber", mSerialNumber);
+ info.AddValue("DeviceInterfaceGuid", mDeviceInterfaceGuid);
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Load usb device finder properties from a binary stream.
+ /// </summary>
+ /// <param name="deviceFinderStream">The binary stream containing a
+ /// <see cref="UsbDeviceFinder"/> </param> instance.
+ /// <returns>A pre-loaded <see cref="UsbDeviceFinder"/> instance.</returns>
+ public static UsbDeviceFinder Load(Stream deviceFinderStream)
+ {
+ BinaryFormatter formatter = new BinaryFormatter();
+ return formatter.Deserialize(deviceFinderStream) as UsbDeviceFinder;
+ }
+
+ /// <summary>
+ /// Saves a <see cref="UsbDeviceFinder"/> instance to a stream.
+ /// </summary>
+ /// <param name="usbDeviceFinder"></param>
+ /// <param name="outStream"></param>
+ public static void Save(UsbDeviceFinder usbDeviceFinder, Stream outStream)
+ {
+ BinaryFormatter formatter = new BinaryFormatter();
+ formatter.Serialize(outStream, usbDeviceFinder);
+ }
+
+ /// <summary>
+ /// Dynamic predicate find function. Pass this function into any method that has a <see cref="Predicate{UsbRegistry}"/> parameter.
+ /// </summary>
+ /// <remarks>
+ /// Override this member when inheriting the <see cref="UsbDeviceFinder"/> class to change/alter the matching behavior.
+ /// </remarks>
+ /// <param name="usbRegistry">The UsbRegistry device to check.</param>
+ /// <returns>True if the <see cref="UsbRegistry"/> instance matches the <see cref="UsbDeviceFinder"/> properties.</returns>
+ public virtual bool Check(UsbRegistry usbRegistry)
+ {
+ if (mVid != int.MaxValue)
+ if (usbRegistry.Vid != mVid) return false;
+ if (mPid != int.MaxValue)
+ if (usbRegistry.Pid != mPid) return false;
+ if (mRevision != int.MaxValue)
+ if (usbRegistry.Rev != mRevision) return false;
+
+ if (!String.IsNullOrEmpty(mSerialNumber))
+ {
+ if (String.IsNullOrEmpty(usbRegistry.SymbolicName)) return false;
+
+ UsbSymbolicName usbSymbolicName = UsbSymbolicName.Parse(usbRegistry.SymbolicName);
+ if (mSerialNumber != usbSymbolicName.SerialNumber) return false;
+ }
+ if (mDeviceInterfaceGuid != Guid.Empty)
+ {
+ List<Guid> deviceGuids = new List<Guid>(usbRegistry.DeviceInterfaceGuids);
+ if (!deviceGuids.Contains(mDeviceInterfaceGuid)) return false;
+ }
+ return true;
+ }
+ /// <summary>
+ /// Dynamic predicate find function. Pass this function into any method that has a <see cref="Predicate{UsbDevice}"/> parameter.
+ /// </summary>
+ /// <remarks>
+ /// Override this member when inheriting the <see cref="UsbDeviceFinder"/> class to change/alter the matching behavior.
+ /// </remarks>
+ /// <param name="usbDevice">The UsbDevice to check.</param>
+ /// <returns>True if the <see cref="UsbDevice"/> instance matches the <see cref="UsbDeviceFinder"/> properties.</returns>
+ public virtual bool Check(UsbDevice usbDevice)
+ {
+ if (mVid != int.MaxValue)
+ if (((ushort)usbDevice.Info.Descriptor.VendorID) != mVid) return false;
+ if (mPid != int.MaxValue)
+ if (((ushort)usbDevice.Info.Descriptor.ProductID) != mPid) return false;
+ if (mRevision != int.MaxValue)
+ if (((ushort)usbDevice.Info.Descriptor.BcdDevice) != mRevision) return false;
+
+ if (!String.IsNullOrEmpty(mSerialNumber))
+ if (mSerialNumber!=usbDevice.Info.SerialString) return false;
+
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/UsbEndpointBase.cs b/LibWinUsb/Main/UsbEndpointBase.cs
new file mode 100644
index 00000000..f679775e
--- /dev/null
+++ b/LibWinUsb/Main/UsbEndpointBase.cs
@@ -0,0 +1,391 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.ObjectModel;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Info;
+using LibUsbDotNet.Internal;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary>
+ /// Endpoint members common to Read, Write, Bulk, and Interrupt <see cref="T:LibUsbDotNet.Main.EndpointType"/>.
+ /// </summary>
+ public abstract class UsbEndpointBase : IDisposable
+ {
+ /// <summary>
+ /// The maximum transfer payload size for all usb endpoints.
+ /// </summary>
+ /// <remarks>
+ /// Transfers greater than this amount are automatically split into
+ /// multiple transfers. This applies to all endpoint transfer methods
+ /// (reads and writes). The default is 4megs (4,194,304 bytes)
+ /// </remarks>
+ public static int MaxReadWrite = 65536;
+
+ internal readonly byte mEpNum;
+ internal readonly UsbApiBase mUsbApi;
+ private readonly UsbDevice mUsbDevice;
+ private readonly SafeHandle mUsbHandle;
+ private bool mIsDisposed;
+ internal TransferDelegate mPipeTransferSubmit;
+ private UsbTransfer mTransferContext;
+ private UsbEndpointInfo mUsbEndpointInfo;
+ private EndpointType mEndpointType;
+ private UsbInterfaceInfo mUsbInterfacetInfo;
+
+ internal UsbEndpointBase(UsbDevice usbDevice, byte epNum, EndpointType endpointType)
+ {
+ mUsbDevice = usbDevice;
+ mUsbApi = mUsbDevice.mUsbApi;
+ mUsbHandle = mUsbDevice.Handle;
+ mEpNum = epNum;
+ mEndpointType = endpointType;
+ if ((mEpNum & 0x80) > 0)
+ {
+ mPipeTransferSubmit = ReadPipe;
+ }
+ else
+ mPipeTransferSubmit = WritePipe;
+ }
+
+
+ internal virtual TransferDelegate PipeTransferSubmit
+ {
+ get { return mPipeTransferSubmit; }
+ }
+
+ internal UsbTransfer TransferContext
+ {
+ get
+ {
+ if (ReferenceEquals(mTransferContext, null))
+ {
+ mTransferContext = CreateTransferContext();
+ }
+ return mTransferContext;
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating if the object is disposed.
+ /// </summary>
+ public bool IsDisposed
+ {
+ get { return mIsDisposed; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="UsbDevice"/> class this endpoint belongs to.
+ /// </summary>
+ public UsbDevice Device
+ {
+ get { return mUsbDevice; }
+ }
+
+
+ internal SafeHandle Handle
+ {
+ get { return mUsbHandle; }
+ }
+
+ /// <summary>
+ /// Gets the endpoint ID for this <see cref="UsbEndpointBase"/> class.
+ /// </summary>
+ public byte EpNum
+ {
+ get
+ {
+ return mEpNum;
+ }
+ }
+
+ /// <summary>
+ /// Returns the <see cref="EndpointType"/> for this endpoint.
+ /// </summary>
+ public EndpointType Type
+ {
+ get { return mEndpointType; }
+ }
+
+ /// <summary>
+ /// Returns the <see cref="UsbEndpointInfo"/> descriptor for this endpoint.
+ /// </summary>
+ public UsbEndpointInfo EndpointInfo
+ {
+ get
+ {
+ if (ReferenceEquals(mUsbEndpointInfo, null))
+ {
+ if (!LookupEndpointInfo(Device.Configs[0], mEpNum, out mUsbInterfacetInfo, out mUsbEndpointInfo))
+ {
+ // throw new UsbException(this, String.Format("Failed locating endpoint {0} for the current usb configuration.", mEpNum));
+ return null;
+ }
+ }
+ return mUsbEndpointInfo;
+ }
+ }
+
+ #region IDisposable Members
+
+ /// <summary>
+ /// Frees resources associated with the endpoint. Once disposed this <see cref="UsbEndpointBase"/> cannot be used.
+ /// </summary>
+ public virtual void Dispose() { DisposeAndRemoveFromList(); }
+
+ #endregion
+
+ internal abstract UsbTransfer CreateTransferContext();
+
+ /// <summary>
+ /// Aborts pending IO operation on this enpoint of one exists.
+ /// </summary>
+ /// <returns>True on success or if no pending IO operation exits.</returns>
+ public virtual bool Abort()
+ {
+ if (mIsDisposed) throw new ObjectDisposedException(GetType().Name);
+ bool bSuccess = TransferContext.Cancel() == ErrorCode.Success;
+
+ return bSuccess;
+ }
+
+ /// <summary>
+ /// Discards any data that is cached in this endpoint.
+ /// </summary>
+ /// <returns>True on success.</returns>
+ public virtual bool Flush()
+ {
+ if (mIsDisposed) throw new ObjectDisposedException(GetType().Name);
+
+ bool bSuccess = mUsbApi.FlushPipe(mUsbHandle, EpNum);
+
+ if (!bSuccess) UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "FlushPipe", this);
+
+ return bSuccess;
+ }
+
+ /// <summary>
+ /// Resets the data toggle and clears the stall condition on an enpoint.
+ /// </summary>
+ /// <returns>True on success.</returns>
+ public virtual bool Reset()
+ {
+ if (mIsDisposed) throw new ObjectDisposedException(GetType().Name);
+
+ bool bSuccess = mUsbApi.ResetPipe(mUsbHandle, EpNum);
+
+ if (!bSuccess) UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "ResetPipe", this);
+
+ return bSuccess;
+ }
+
+ /// <summary>
+ /// Synchronous bulk/interrupt transfer function.
+ /// </summary>
+ /// <param name="buffer">An <see cref="IntPtr"/> to a caller-allocated buffer.</param>
+ /// <param name="offset">Position in buffer that transferring begins.</param>
+ /// <param name="length">Number of bytes, starting from thr offset parameter to transfer.</param>
+ /// <param name="timeout">Maximum time to wait for the transfer to complete.</param>
+ /// <param name="transferLength">Number of bytes actually transferred.</param>
+ /// <returns>True on success.</returns>
+ public virtual ErrorCode Transfer(IntPtr buffer, int offset, int length, int timeout, out int transferLength) { return UsbTransfer.SyncTransfer(TransferContext, buffer, offset, length, timeout, out transferLength); }
+
+ /// <summary>
+ /// Creates, fills and submits an asynchronous <see cref="UsbTransfer"/> context.
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip">This is a non-blocking asynchronous transfer function. This function returns immediately after the context is created and submitted.</note>
+ /// </remarks>
+ /// <param name="buffer">A caller-allocated buffer for the data that is transferred.</param>
+ /// <param name="offset">Position in buffer that transferring begins.</param>
+ /// <param name="length">Number of bytes, starting from thr offset parameter to transfer.</param>
+ /// <param name="timeout">Maximum time to wait for the transfer to complete.</param>
+ /// <param name="transferContext">On <see cref="ErrorCode.Success"/>, a new transfer context.</param>
+ /// <returns><see cref="ErrorCode.Success"/> if the transfer context was created and <see cref="UsbTransfer.Submit"/> succeeded.</returns>
+ /// <seealso cref="SubmitAsyncTransfer(System.IntPtr,int,int,int,out LibUsbDotNet.Main.UsbTransfer)"/>
+ /// <seealso cref="NewAsyncTransfer"/>
+ public virtual ErrorCode SubmitAsyncTransfer(object buffer, int offset, int length, int timeout, out UsbTransfer transferContext)
+ {
+ transferContext = CreateTransferContext();
+ transferContext.Fill(buffer, offset, length, timeout);
+
+ ErrorCode ec = transferContext.Submit();
+ if (ec != ErrorCode.None)
+ {
+ transferContext.Dispose();
+ transferContext = null;
+ UsbError.Error(ec, 0, "SubmitAsyncTransfer Failed", this);
+ }
+
+ return ec;
+ }
+
+ /// <summary>
+ /// Creates, fills and submits an asynchronous <see cref="UsbTransfer"/> context.
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip">This is a non-blocking asynchronous transfer function. This function returns immediately after the context is created and submitted.</note>
+ /// </remarks>
+ /// <param name="buffer">A caller-allocated buffer for the data that is transferred.</param>
+ /// <param name="offset">Position in buffer that transferring begins.</param>
+ /// <param name="length">Number of bytes, starting from thr offset parameter to transfer.</param>
+ /// <param name="timeout">Maximum time to wait for the transfer to complete.</param>
+ /// <param name="transferContext">On <see cref="ErrorCode.Success"/>, a new transfer context.</param>
+ /// <returns><see cref="ErrorCode.Success"/> if the transfer context was created and <see cref="UsbTransfer.Submit"/> succeeded.</returns>
+ /// <seealso cref="SubmitAsyncTransfer(object,int,int,int,out LibUsbDotNet.Main.UsbTransfer)"/>
+ /// <seealso cref="NewAsyncTransfer"/>
+ public virtual ErrorCode SubmitAsyncTransfer(IntPtr buffer, int offset, int length, int timeout, out UsbTransfer transferContext)
+ {
+ transferContext = CreateTransferContext();
+ transferContext.Fill(buffer, offset, length, timeout);
+
+ ErrorCode ec = transferContext.Submit();
+ if (ec != ErrorCode.None)
+ {
+ transferContext.Dispose();
+ transferContext = null;
+ UsbError.Error(ec, 0, "SubmitAsyncTransfer Failed", this);
+ }
+
+ return ec;
+ }
+ /// <summary>
+ /// Creates a <see cref="UsbTransfer"/> context for asynchronous transfers.
+ /// </summary>
+ /// <remarks>
+ /// <para> This method returns a new, empty transfer context. Unlike <see cref="SubmitAsyncTransfer(object,int,int,int,out LibUsbDotNet.Main.UsbTransfer)">SubmitAsyncTransfer</see>, this context is <c>not</c> filled and submitted.</para>
+ /// <note type="tip">This is a non-blocking asynchronous transfer function. This function returns immediately after the context created.</note>
+ /// </remarks>
+ /// <returns>A new <see cref="UsbTransfer"/> context.</returns>
+ /// <seealso cref="SubmitAsyncTransfer(System.IntPtr,int,int,int,out LibUsbDotNet.Main.UsbTransfer)"/>
+ /// <seealso cref="SubmitAsyncTransfer(object,int,int,int,out LibUsbDotNet.Main.UsbTransfer)"/>
+ public UsbTransfer NewAsyncTransfer()
+ {
+ UsbTransfer transfer = CreateTransferContext();
+ return transfer;
+ }
+
+ /// <summary>
+ /// Looks up endpoint/interface information in a configuration.
+ /// </summary>
+ /// <param name="currentConfigInfo">The config to seach.</param>
+ /// <param name="endpointAddress">The endpoint address to look for.</param>
+ /// <param name="usbInterfaceInfo">On success, the <see cref="UsbInterfaceInfo"/> class for this endpoint.</param>
+ /// <param name="usbEndpointInfo">On success, the <see cref="UsbEndpointInfo"/> class for this endpoint.</param>
+ /// <returns>True of the endpoint was found, otherwise false.</returns>
+ public static bool LookupEndpointInfo(UsbConfigInfo currentConfigInfo, byte endpointAddress, out UsbInterfaceInfo usbInterfaceInfo, out UsbEndpointInfo usbEndpointInfo)
+ {
+ bool found = false;
+
+ usbInterfaceInfo = null;
+ usbEndpointInfo = null;
+ foreach (UsbInterfaceInfo interfaceInfo in currentConfigInfo.InterfaceInfoList)
+ {
+ foreach (UsbEndpointInfo endpointInfo in interfaceInfo.EndpointInfoList)
+ {
+ if ((endpointAddress & UsbConstants.ENDPOINT_NUMBER_MASK) == 0)
+ {
+ // find first read/write endpoint
+ if ((endpointAddress & UsbConstants.ENDPOINT_DIR_MASK) == 0 &&
+ (endpointInfo.Descriptor.EndpointID & UsbConstants.ENDPOINT_DIR_MASK) == 0)
+ {
+ // first write endpoint
+ found = true;
+ }
+ if ((endpointAddress & UsbConstants.ENDPOINT_DIR_MASK) != 0 &&
+ (endpointInfo.Descriptor.EndpointID & UsbConstants.ENDPOINT_DIR_MASK) != 0)
+ {
+ // first read endpoint
+ found = true;
+ }
+ }
+ else if (endpointInfo.Descriptor.EndpointID == endpointAddress)
+ {
+ found = true;
+ }
+
+ if (found)
+ {
+ usbInterfaceInfo = interfaceInfo;
+ usbEndpointInfo = endpointInfo;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Synchronous bulk/interrupt transfer function.
+ /// </summary>
+ /// <param name="buffer">A caller-allocated buffer for the transfer data. This object is pinned using <see cref="PinnedHandle"/>.</param>
+ /// <param name="offset">Position in buffer that transferring begins.</param>
+ /// <param name="length">Number of bytes, starting from thr offset parameter to transfer.</param>
+ /// <param name="timeout">Maximum time to wait for the transfer to complete.</param>
+ /// <param name="transferLength">Number of bytes actually transferred.</param>
+ /// <returns>True on success.</returns>
+ public ErrorCode Transfer(object buffer, int offset, int length, int timeout, out int transferLength)
+ {
+ PinnedHandle pinned = new PinnedHandle(buffer);
+ ErrorCode eReturn = Transfer(pinned.Handle, offset, length, timeout, out transferLength);
+ pinned.Dispose();
+ return eReturn;
+ }
+
+ private void DisposeAndRemoveFromList()
+ {
+ if (!mIsDisposed)
+ {
+ UsbEndpointReader epReader = this as UsbEndpointReader;
+ if (!ReferenceEquals(epReader, null))
+ {
+ if (epReader.DataReceivedEnabled) epReader.DataReceivedEnabled = false;
+ }
+ Abort();
+ mUsbDevice.ActiveEndpoints.RemoveFromList(this);
+ }
+ mIsDisposed = true;
+ }
+
+ private int ReadPipe(IntPtr pBuffer, int bufferLength, out int lengthTransferred, int isoPacketSize, IntPtr pOverlapped)
+ {
+ bool bSuccess = mUsbApi.ReadPipe(this, pBuffer, bufferLength, out lengthTransferred, isoPacketSize, pOverlapped);
+ if (!bSuccess) return Marshal.GetLastWin32Error();
+ return 0;
+ }
+
+
+ private int WritePipe(IntPtr pBuffer, int bufferLength, out int lengthTransferred, int isoPacketSize, IntPtr pOverlapped)
+ {
+ bool bSuccess = mUsbApi.WritePipe(this, pBuffer, bufferLength, out lengthTransferred, isoPacketSize, pOverlapped);
+ if (!bSuccess) return Marshal.GetLastWin32Error();
+ return 0;
+ }
+
+ #region Nested type: TransferDelegate
+
+ internal delegate int TransferDelegate(IntPtr pBuffer, int bufferLength, out int lengthTransferred, int isoPacketSize, IntPtr pOverlapped);
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/UsbEndpointDirection.cs b/LibWinUsb/Main/UsbEndpointDirection.cs
new file mode 100644
index 00000000..89f15f99
--- /dev/null
+++ b/LibWinUsb/Main/UsbEndpointDirection.cs
@@ -0,0 +1,40 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+
+namespace LibUsbDotNet.Main
+{
+ ///<summary>Endpoint direction.</summary>
+ /// <seealso cref="UsbCtrlFlags"/>
+ [Flags]
+ public enum UsbEndpointDirection : byte
+ {
+ /// <summary>
+ /// In Direction
+ /// </summary>
+ EndpointIn = 0x80,
+ /// <summary>
+ /// Out Direction
+ /// </summary>
+ EndpointOut = 0x00,
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/UsbEndpointList.cs b/LibWinUsb/Main/UsbEndpointList.cs
new file mode 100644
index 00000000..7e6ef8d3
--- /dev/null
+++ b/LibWinUsb/Main/UsbEndpointList.cs
@@ -0,0 +1,147 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System.Collections;
+using System.Collections.Generic;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary> Endpoint list.
+ /// </summary>
+ public class UsbEndpointList : IEnumerable<UsbEndpointBase>
+ {
+ private readonly List<UsbEndpointBase> mEpList = new List<UsbEndpointBase>();
+
+ internal UsbEndpointList() { }
+
+ /// <summary>
+ /// Gets the <see cref="UsbEndpointBase"/> item at the specified index.
+ /// </summary>
+ /// <param name="index">The zero-based index of the item.</param>
+ /// <returns>The <see cref="UsbEndpointBase"/> item at the specified index.</returns>
+ ///<exception cref="T:System.ArgumentOutOfRangeException">index is not a valid index in the <see cref="UsbEndpointList"/>.</exception>
+ public UsbEndpointBase this[int index]
+ {
+ get { return mEpList[index]; }
+ }
+
+ ///<summary>
+ ///Gets the number of elements contained in the <see cref="UsbEndpointList"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///The number of elements contained in the <see cref="UsbEndpointList"/>.
+ ///</returns>
+ ///
+ public int Count
+ {
+ get { return mEpList.Count; }
+ }
+
+ #region IEnumerable<UsbEndpointBase> Members
+
+ ///<summary>
+ ///Returns <see cref="UsbEndpointBase"/> enumerator that iterates through the collection.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="UsbEndpointBase"/> enumerator that can be used to iterate through the collection.
+ ///</returns>
+ public IEnumerator<UsbEndpointBase> GetEnumerator() { return mEpList.GetEnumerator(); }
+
+ ///<summary>
+ ///Returns an enumerator that iterates through a collection.
+ ///</summary>
+ ///
+ ///<returns>
+ ///An <see cref="System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
+ ///</returns>
+ ///<filterpriority>2</filterpriority>
+ IEnumerator IEnumerable.GetEnumerator() { return mEpList.GetEnumerator(); }
+
+ #endregion
+
+ ///<summary>
+ ///Removes all items from the <see cref="UsbEndpointList"/>.
+ ///</summary>
+ public void Clear()
+ {
+ while (mEpList.Count > 0)
+ Remove(mEpList[0]);
+ }
+
+ ///<summary>
+ ///Determines whether the <see cref="UsbEndpointList"/> contains a specific value.
+ ///</summary>
+ ///
+ ///<returns>
+ ///true if item is found in the <see cref="UsbEndpointList"/>; otherwise, false.
+ ///</returns>
+ ///
+ ///<param name="item">The <see cref="UsbEndpointBase"/> to locate in the <see cref="UsbEndpointList"/>.</param>
+ public bool Contains(UsbEndpointBase item) { return mEpList.Contains(item); }
+
+
+ ///<summary>
+ ///Determines the index of a specific <see cref="UsbEndpointBase"/> in the <see cref="UsbEndpointList"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///The index of item if found in the list; otherwise, -1.
+ ///</returns>
+ ///
+ ///<param name="item">The <see cref="UsbEndpointBase"/> to locate in the <see cref="UsbEndpointList"/>.</param>
+ public int IndexOf(UsbEndpointBase item) { return mEpList.IndexOf(item); }
+
+ ///<summary>
+ ///Removes the specified <see cref="UsbEndpointBase"/> in the <see cref="UsbEndpointList"/>.
+ ///</summary>
+ ///
+ ///<param name="item">The <see cref="UsbEndpointBase"/> to remove in the <see cref="UsbEndpointList"/>.</param>
+ public void Remove(UsbEndpointBase item) { item.Dispose(); }
+
+ ///<summary>
+ ///Removes the <see cref="UsbEndpointList"/> item at the specified index.
+ ///</summary>
+ ///
+ ///<param name="index">The zero-based index of the item to remove.</param>
+ ///<exception cref="T:System.ArgumentOutOfRangeException">index is not a valid index in the <see cref="UsbEndpointList"/>.</exception>
+ public void RemoveAt(int index)
+ {
+ UsbEndpointBase item = mEpList[index];
+ Remove(item);
+ }
+
+
+ internal UsbEndpointBase Add(UsbEndpointBase item)
+ {
+ foreach (UsbEndpointBase endpoint in mEpList)
+ {
+ if (endpoint.EpNum == item.EpNum)
+ return endpoint;
+ }
+ mEpList.Add(item);
+ return item;
+ }
+
+ internal bool RemoveFromList(UsbEndpointBase item) { return mEpList.Remove(item); }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/UsbException.cs b/LibWinUsb/Main/UsbException.cs
new file mode 100644
index 00000000..54ffcb40
--- /dev/null
+++ b/LibWinUsb/Main/UsbException.cs
@@ -0,0 +1,46 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+namespace LibUsbDotNet.Main
+{
+ /// <summary>
+ /// Represents an exception generated by a USB operation.
+ /// </summary>
+ public class UsbException : Exception
+ {
+ private readonly object mSender;
+
+ /// <summary>
+ /// LibUsbDotNet USB exception.
+ /// </summary>
+ internal UsbException(object sender, string description)
+ : base(description) { mSender = sender; }
+
+ /// <summary>
+ /// The object that caused the exception.
+ /// </summary>
+ public object Sender
+ {
+ get { return mSender; }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/UsbKernelVersion.cs b/LibWinUsb/Main/UsbKernelVersion.cs
new file mode 100644
index 00000000..b29e7134
--- /dev/null
+++ b/LibWinUsb/Main/UsbKernelVersion.cs
@@ -0,0 +1,91 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System.Runtime.InteropServices;
+
+namespace LibUsbDotNet.Main
+{
+ ///<summary>
+ /// Contains version information for the LibUsb Sys driver.
+ ///</summary>
+ /// <remarks>
+ /// This version is not related to LibUsbDotNet. TO get the LibUsbDotNet version use .NET reflections.
+ /// </remarks>
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct UsbKernelVersion
+ {
+ /// <summary>
+ /// True if Major == 0 and Minor == 0 and Micro == 0 and Nano == 0.
+ /// </summary>
+ public bool IsEmpty
+ {
+ get
+ {
+ if (Major == 0 && Minor == 0 && Micro == 0 && Nano == 0) return true;
+ return false;
+ }
+ }
+
+ internal UsbKernelVersion(int major, int minor, int micro, int nano, int bcdLibUsbDotNetKernelMod)
+ {
+ Major = major;
+ Minor = minor;
+ Micro = micro;
+ Nano = nano;
+ BcdLibUsbDotNetKernelMod = bcdLibUsbDotNetKernelMod;
+ }
+
+ /// <summary>
+ /// LibUsb-Win32 Major version
+ /// </summary>
+ public readonly int Major;
+
+ /// <summary>
+ /// LibUsb-Win32 Minor version
+ /// </summary>
+ public readonly int Minor;
+
+ /// <summary>
+ /// LibUsb-Win32 Micro version
+ /// </summary>
+ public readonly int Micro;
+
+ /// <summary>
+ /// LibUsb-Win32 Nano version
+ /// </summary>
+ public readonly int Nano;
+
+ /// <summary>
+ /// The LibUsbDotNet - LibUsb-Win32 binary mod code. if not running the LibUsbDotNet LibUsb-Win32 modified kernel driver, this value is 0.
+ /// </summary>
+ public readonly int BcdLibUsbDotNetKernelMod;
+
+
+ ///<summary>
+ ///The full LibUsb-Win32 kernel driver version (libusb0.sys).
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> containing the full LibUsb-Win32 version.
+ ///</returns>
+ public override string ToString() { return string.Format("{0}.{1}.{2}.{3}", Major, Minor, Micro, Nano); }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/UsbLockStyle.cs b/LibWinUsb/Main/UsbLockStyle.cs
new file mode 100644
index 00000000..5f905980
--- /dev/null
+++ b/LibWinUsb/Main/UsbLockStyle.cs
@@ -0,0 +1,146 @@
+// Copyright © 2006-2009 Travis Robinson. All rights reserved.
+//
+// website: sourceforge.net/projects/libusbdotnet/
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.Main
+{
+ /// <summary>Contains the locking strategy for a <see cref="UsbDevice"/> and it's associated endpoints.</summary>
+ /// <remarks>Locking styles are use to change the way proccess/threads are allowed to communcate with a USB device and/or endpoints.
+ /// See the <see cref="DeviceLockType"/>, <see cref="ControlEpLockType"/>, and <see cref="DataEpLockType"/> enumerations for a description of the various locking styles.
+ /// </remarks>
+ public class UsbLockStyle
+ {
+ private ControlEpLockType mControlEpLock;
+ private DataEpLockType mDataEpLock;
+ private DeviceLockType mDeviceLockType;
+ private int mEndpointControlTimeout;
+ private int mEndpointLockTimeout;
+
+ /// <summary>
+ /// Create a device lock style class.
+ /// </summary>
+ /// <param name="deviceLockType">See <see cref="DeviceLockType"/>.</param>
+ /// <param name="controlEpLockType">See <see cref="ControlEpLock"/>.</param>
+ /// <param name="dataEpLockType">See <see cref="DataEpLock"/>.</param>
+ public UsbLockStyle(DeviceLockType deviceLockType, ControlEpLockType controlEpLockType, DataEpLockType dataEpLockType)
+ : this(deviceLockType, controlEpLockType, dataEpLockType, 1000, 1000)
+ {
+ }
+
+ /// <summary>
+ /// Create a device lock style class.
+ /// </summary>
+ /// <param name="deviceLockType">See <see cref="DeviceLockType"/>.</param>
+ /// <param name="controlEpLockType">See <see cref="ControlEpLock"/>.</param>
+ /// <param name="dataEpLockType">See <see cref="DataEpLock"/>.</param>
+ /// <param name="endpoint0Timeout">Number of milliseconds to wait for an endpoint 0 lock before returning a timeout errorcode.</param>
+ /// <param name="endpointLockTimeout">Number of milliseconds to wait for an endpoint lock before returning a timeout errorcode.</param>
+ public UsbLockStyle(DeviceLockType deviceLockType,
+ ControlEpLockType controlEpLockType,
+ DataEpLockType dataEpLockType,
+ int endpoint0Timeout,
+ int endpointLockTimeout)
+ {
+ mDeviceLockType = deviceLockType;
+ mControlEpLock = controlEpLockType;
+ mDataEpLock = dataEpLockType;
+ mEndpointControlTimeout = endpoint0Timeout;
+ mEndpointLockTimeout = endpointLockTimeout;
+ }
+
+ /// <summary>
+ /// Locking strategy for the device. See <see cref="DeviceLockType"/> for more information.
+ /// </summary>
+ public DeviceLockType DeviceLockType
+ {
+ get
+ {
+ return mDeviceLockType;
+ }
+ set
+ {
+ mDeviceLockType = value;
+ }
+ }
+
+ /// <summary>
+ /// Locking strategy for <see cref="UsbDevice"/> Endpoint0 operations. This property will generally always be <see cref="ControlEpLockType.None"/>, See <see cref="ControlEpLockType"/> for more information.
+ /// </summary>
+ public ControlEpLockType ControlEpLock
+ {
+ get
+ {
+ return mControlEpLock;
+ }
+ set
+ {
+ mControlEpLock = value;
+ }
+ }
+
+ /// <summary>
+ /// Locking strategy for the <see cref="UsbDevice"/> endpoint operations. See <see cref="DataEpLockType"/> for more information.
+ /// </summary>
+ public DataEpLockType DataEpLock
+ {
+ get
+ {
+ return mDataEpLock;
+ }
+ set
+ {
+ mDataEpLock = value;
+ }
+ }
+
+ /// <summary>
+ /// Timeout value used when attempting to aquire an <see cref="ControlEpLockType"/> when <see cref="ControlEpLock"/> is set to a value other than <see cref="ControlEpLockType.None"/>.
+ /// </summary>
+ public int EndpointControlTimeout
+ {
+ get
+ {
+ return mEndpointControlTimeout;
+ }
+ set
+ {
+ mEndpointControlTimeout = value;
+ }
+ }
+
+ /// <summary>
+ /// Maximum time(ms) to wait for an endpoint to become idle before returning a <see cref="ErrorCode.EndpointLockTimedOut"/> error code.
+ /// </summary>
+ /// <remarks>
+ /// This property has no affect unless the <see cref="UsbDevice.LockStyle"/> includes the <see cref="DataEpLockType.Locked"/> enumeration.
+ /// </remarks>
+ public int EndpointLockTimeout
+ {
+ get
+ {
+ return mEndpointLockTimeout;
+ }
+ set
+ {
+ mEndpointLockTimeout = value;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/UsbRegDeviceList.cs b/LibWinUsb/Main/UsbRegDeviceList.cs
new file mode 100644
index 00000000..574dca32
--- /dev/null
+++ b/LibWinUsb/Main/UsbRegDeviceList.cs
@@ -0,0 +1,179 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary>
+ /// Array of USB device available for communication via LibUsb or WinUsb.
+ /// </summary>
+ public class UsbRegDeviceList : IEnumerable<UsbRegistry>
+ {
+ private readonly List<UsbRegistry> mUsbRegistryList;
+
+ ///<summary>
+ /// Creates an empty <see cref="UsbRegDeviceList"/> instance.
+ ///</summary>
+ public UsbRegDeviceList() { mUsbRegistryList = new List<UsbRegistry>(); }
+
+ private UsbRegDeviceList(IEnumerable<UsbRegistry> usbRegDeviceList) { mUsbRegistryList = new List<UsbRegistry>(usbRegDeviceList); }
+
+ ///<summary>
+ ///Gets the element at the specified index.
+ ///</summary>
+ ///
+ ///<returns>
+ ///The element at the specified index.
+ ///</returns>
+ ///
+ ///<param name="index">The zero-based index of the element to get or set.</param>
+ ///<exception cref="T:System.ArgumentOutOfRangeException">index is not a valid index in the <see cref="T:System.Collections.Generic.IList`1"/>.</exception>
+ ///<exception cref="T:System.NotSupportedException">The property is set and the <see cref="T:System.Collections.Generic.IList`1"/> is read-only.</exception>
+ public UsbRegistry this[int index]
+ {
+ get { return mUsbRegistryList[index]; }
+ }
+
+ ///<summary>
+ ///Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///The number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
+ ///</returns>
+ ///
+ public int Count
+ {
+ get { return mUsbRegistryList.Count; }
+ }
+
+ #region IEnumerable<UsbRegistry> Members
+
+ ///<summary>
+ ///Returns an enumerator that iterates through the collection.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="IEnumerator{T}"/> that can be used to iterate through the collection.
+ ///</returns>
+ IEnumerator<UsbRegistry> IEnumerable<UsbRegistry>.GetEnumerator() { return mUsbRegistryList.GetEnumerator(); }
+
+ ///<summary>
+ ///Returns an enumerator that iterates through a collection.
+ ///</summary>
+ ///
+ ///<returns>
+ ///An <see cref="System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
+ ///</returns>
+ public IEnumerator GetEnumerator() { return ((IEnumerable<UsbRegistry>) this).GetEnumerator(); }
+
+ #endregion
+
+ /// <summary>
+ /// Find the first UsbRegistry device that matches the FindUsbPredicate.
+ /// </summary>
+ /// <param name="findUsbPredicate">The predicate function to use.</param>
+ /// <returns>A valid usb registry class if the device was found or Null if the device was not found.</returns>
+ public UsbRegistry Find(Predicate<UsbRegistry> findUsbPredicate) { return mUsbRegistryList.Find(findUsbPredicate); }
+
+ /// <summary>
+ /// Find all UsbRegistry devices that matches the FindUsbPredicate.
+ /// </summary>
+ /// <param name="findUsbPredicate">The predicate function to use.</param>
+ /// <returns>All usb registry classes that match.</returns>
+ public UsbRegDeviceList FindAll(Predicate<UsbRegistry> findUsbPredicate) { return new UsbRegDeviceList(mUsbRegistryList.FindAll(findUsbPredicate)); }
+
+ /// <summary>
+ /// Find the last a UsbRegistry device that matches the FindUsbPredicate.
+ /// </summary>
+ /// <param name="findUsbPredicate">The predicate function to use.</param>
+ /// <returns>A valid usb registry class if the device was found or Null if the device was not found.</returns>
+ public UsbRegistry FindLast(Predicate<UsbRegistry> findUsbPredicate) { return mUsbRegistryList.FindLast(findUsbPredicate); }
+
+ /// <summary>
+ /// Find the first UsbRegistry device using a <see cref="UsbDeviceFinder"/> instance.
+ /// </summary>
+ /// <param name="usbDeviceFinder">The <see cref="UsbDeviceFinder"/> instance used to locate the usb registry devices.</param>
+ /// <returns>A valid usb registry class if the device was found or Null if the device was not found.</returns>
+ public UsbRegistry Find(UsbDeviceFinder usbDeviceFinder) { return mUsbRegistryList.Find((Predicate<UsbRegistry>) usbDeviceFinder.Check); }
+
+ /// <summary>
+ /// Find all UsbRegistry devices using a <see cref="UsbDeviceFinder"/> instance.
+ /// </summary>
+ /// <param name="usbDeviceFinder">The <see cref="UsbDeviceFinder"/> instance used to locate the usb registry devices.</param>
+ /// <returns>All usb registry classes that match.</returns>
+ public UsbRegDeviceList FindAll(UsbDeviceFinder usbDeviceFinder) { return FindAll((Predicate<UsbRegistry>)usbDeviceFinder.Check); }
+
+ /// <summary>
+ /// Find the last UsbRegistry devices using a <see cref="UsbDeviceFinder"/> instance.
+ /// </summary>
+ /// <param name="usbDeviceFinder">The <see cref="UsbDeviceFinder"/> instance used to locate the usb registry devices.</param>
+ /// <returns>A valid usb registry class if the device was found or Null if the device was not found.</returns>
+ public UsbRegistry FindLast(UsbDeviceFinder usbDeviceFinder) { return mUsbRegistryList.FindLast((Predicate<UsbRegistry>)usbDeviceFinder.Check); }
+
+ ///<summary>
+ ///Determines whether the <see cref="T:System.Collections.Generic.ICollection`1"/> contains a specific value.
+ ///</summary>
+ ///
+ ///<returns>
+ ///true if item is found in the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false.
+ ///</returns>
+ ///
+ ///<param name="item">The object to locate in the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
+ public bool Contains(UsbRegistry item) { return mUsbRegistryList.Contains(item); }
+
+ ///<summary>
+ ///Copies the elements of the <see cref="T:System.Collections.Generic.ICollection`1"/> to an <see cref="T:System.Array"/>, starting at a particular <see cref="T:System.Array"/> index.
+ ///</summary>
+ ///
+ ///<param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:System.Collections.Generic.ICollection`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param>
+ ///<param name="offset">The zero-based index in Array at which copying begins.</param>
+ ///<exception cref="T:System.ArgumentOutOfRangeException">Offset is less than 0.</exception>
+ ///<exception cref="T:System.ArgumentNullException">Array is null.</exception>
+ ///<exception cref="T:System.ArgumentException">Array is multidimensional.-or-Offset is equal to or greater than the length of Array.-or-The number of elements in the source <see cref="T:System.Collections.Generic.ICollection`1"/> is greater than the available space from Offset to the end of the destination Array.-or-Type T cannot be cast automatically to the type of the destination Array.</exception>
+ public void CopyTo(UsbRegistry[] array, int offset) { mUsbRegistryList.CopyTo(array, offset); }
+
+ ///<summary>
+ ///Determines the index of a specific item in the <see cref="T:System.Collections.Generic.IList`1"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///The index of item if found in the list; otherwise, -1.
+ ///</returns>
+ ///
+ ///<param name="item">The object to locate in the <see cref="T:System.Collections.Generic.IList`1"/>.</param>
+ public int IndexOf(UsbRegistry item) { return mUsbRegistryList.IndexOf(item); }
+
+ internal bool Add(UsbRegistry item)
+ {
+ //for (int i = 0; i < Count; i++)
+ //{
+ // if (mUsbRegistryList[i] == item)
+ // return false;
+ //}
+ mUsbRegistryList.Add(item);
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/UsbRegistry.cs b/LibWinUsb/Main/UsbRegistry.cs
new file mode 100644
index 00000000..f957c596
--- /dev/null
+++ b/LibWinUsb/Main/UsbRegistry.cs
@@ -0,0 +1,332 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using System.Text;
+using LibUsbDotNet.Descriptors;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary> USB device registry members common to both LibUsb and WinUsb devices.
+ /// </summary>
+ public abstract class UsbRegistry //: IEquatable<UsbRegistry>
+ {
+ internal const string DEVICE_INTERFACE_GUIDS = "DeviceInterfaceGuids";
+ internal const string LIBUSB_INTERFACE_GUIDS = "LibUsbInterfaceGUIDs";
+
+ internal const string SYMBOLIC_NAME_KEY = "SymbolicName";
+ internal const string DEVICE_ID_KEY = "DeviceID";
+
+ private static readonly char[] ChNull = new char[] {'\0'};
+
+ /// <summary>
+ /// If true, LibUsbDotNet will use the vid, pid and revision of the <see cref="UsbDevice.Info"/>
+ /// descriptor to lookup additional device information in the windows registry via the setupapi.
+ /// Setting this field to false will cause all device information to come directly from the
+ /// device descriptors.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// If using WinUSB or the LibUsbDotNet-libusb-win32 native driver, information provided by
+ /// the <see cref="UsbRegistry"/> class will come from the registry regardless of this setting
+ /// because these drivers have direct support for this.
+ /// </para>
+ /// <para>
+ /// The Libusb-1.0 windows-backend driver and the legacy libusb-win32 driver have their own methods
+ /// for listing, finding, and opening devices. For these drivers, the <see cref="ForceSetupApi"/> can
+ /// be set to do a "reverse lookup" via the setupapi using only the vid, pid and revision of the
+ /// <see cref="UsbDeviceDescriptor"/>. The <see cref="UsbRegistry"/> class is then populated with
+ /// all available <see cref="SPDRP"/> properties, device interface guids, winusb device paths, etc.
+ /// </para>
+ /// </remarks>
+ public static bool ForceSetupApi = true;
+
+ /// <summary>
+ /// Guid array of all <see cref="DeviceInterfaceGuids"/> assigned to this device.
+ /// </summary>
+ internal Guid[] mDeviceInterfaceGuids=new Guid[0];
+
+ internal Dictionary<string, object> mDeviceProperties = new Dictionary<string, object>();
+
+ private UsbSymbolicName mSymHardwareId;
+
+ /// <summary>
+ /// Collection of known usb device properties (from the registry).
+ /// </summary>
+ public Dictionary<string, object> DeviceProperties
+ {
+ get { return mDeviceProperties; }
+ }
+
+ /// <summary>
+ /// Check this value to determine if the usb device is still connected to the bus and ready to open.
+ /// </summary>
+ /// <remarks>
+ /// Uses the symbolic name as a unique id to determine if this device instance is still attached.
+ /// </remarks>
+ /// <exception cref="UsbException">An exception is thrown if the <see cref="UsbRegistry.SymbolicName"/> property is null or empty.</exception>
+ public abstract bool IsAlive { get; }
+
+ /// <summary>
+ /// The unique "SymbolicName" of the device.
+ /// </summary>
+ public string SymbolicName
+ {
+ get
+ {
+ if (mDeviceProperties.ContainsKey(SYMBOLIC_NAME_KEY))
+ return (string) mDeviceProperties[SYMBOLIC_NAME_KEY];
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// The unique "SymbolicName" of the device.
+ /// </summary>
+ public abstract Guid[] DeviceInterfaceGuids { get; }
+
+ /// <summary>
+ /// VendorID
+ /// </summary>
+ public virtual int Vid
+ {
+ get
+ {
+ if (ReferenceEquals(mSymHardwareId, null))
+ {
+ string[] saHardwareIds = mDeviceProperties[SPDRP.HardwareId.ToString()] as string[];
+ if (saHardwareIds != null && saHardwareIds.Length > 0)
+ {
+ mSymHardwareId = UsbSymbolicName.Parse(saHardwareIds[0]);
+ }
+ }
+ if (!ReferenceEquals(mSymHardwareId, null))
+ {
+ return mSymHardwareId.Vid;
+ }
+
+ return 0;
+ }
+ }
+
+ /// <summary>
+ /// ProductID
+ /// </summary>
+ public virtual int Pid
+ {
+ get
+ {
+ if (ReferenceEquals(mSymHardwareId, null))
+ {
+ string[] saHardwareIds = mDeviceProperties[SPDRP.HardwareId.ToString()] as string[];
+ if (saHardwareIds != null && saHardwareIds.Length > 0)
+ {
+ mSymHardwareId = UsbSymbolicName.Parse(saHardwareIds[0]);
+ }
+ }
+ if (!ReferenceEquals(mSymHardwareId, null))
+ {
+ return mSymHardwareId.Pid;
+ }
+
+ return 0;
+ }
+ }
+
+ /// <summary>
+ /// Gets a device property/key from the registry.
+ /// </summary>
+ /// <param name="name">The name of the property to retrieve.</param>
+ /// <returns></returns>
+ public object this[string name]
+ {
+ get
+ {
+ object temp;
+ mDeviceProperties.TryGetValue(name, out temp);
+ return temp;
+ }
+ }
+
+ /// <summary>
+ /// Gets a device property/key from the registry. See the <see cref="SPDRP"/> enumeration for more information.
+ /// </summary>
+ /// <param name="spdrp">The name of the property to retrieve.</param>
+ /// <returns></returns>
+ public object this[SPDRP spdrp]
+ {
+ get
+ {
+ object temp;
+ mDeviceProperties.TryGetValue(spdrp.ToString(), out temp);
+ return temp;
+ }
+ }
+
+ /// <summary>
+ /// Gets a property from the registry. See the <see cref="DevicePropertyType"/> enumeration for more information.
+ /// </summary>
+ /// <param name="devicePropertyType">The name of the property to retrieve.</param>
+ /// <returns></returns>
+ public object this[DevicePropertyType devicePropertyType]
+ {
+ get
+ {
+ object temp;
+ mDeviceProperties.TryGetValue(devicePropertyType.ToString(), out temp);
+ return temp;
+ }
+ }
+
+ /// <summary>
+ /// Gets the short name of the usb device.
+ /// </summary>
+ /// <remarks>This is the device decription as it is defined in the setup/inf file.</remarks>
+ public string Name
+ {
+ get
+ {
+ string deviceDesc = this[SPDRP.DeviceDesc] as string;
+ if (String.IsNullOrEmpty(deviceDesc)) return string.Empty;
+ return deviceDesc;
+ }
+ }
+
+ /// <summary>
+ /// Gets the manufacturer followed by the device decription in the format 'Mfu - Description'
+ /// </summary>
+ /// <remarks>This property works best for a display name. It does additional proccessing on the manufacturer and device description that make it more user readable.</remarks>
+ public string FullName
+ {
+ get
+ {
+ string deviceDesc = Name;
+ string mfg = this[SPDRP.Mfg] as string;
+ if (mfg == null) mfg = String.Empty;
+ deviceDesc = deviceDesc.Trim();
+ mfg = mfg.Trim();
+
+ int firstMfuSpace = mfg.IndexOf(' ');
+ int firstDescSpace = deviceDesc.IndexOf(' ');
+ while (firstMfuSpace == firstDescSpace && firstDescSpace != -1)
+ {
+ if (mfg.Substring(0, firstMfuSpace).Equals(deviceDesc.Substring(0, firstDescSpace)))
+ {
+ deviceDesc = deviceDesc.Remove(0, firstDescSpace + 1);
+ firstMfuSpace = mfg.IndexOf(' ');
+ firstDescSpace = deviceDesc.IndexOf(' ');
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (deviceDesc.ToLower().Contains(mfg.ToLower()))
+ return deviceDesc;
+
+ if (mfg == string.Empty) mfg = "[Not Provided]";
+ if (deviceDesc == string.Empty) deviceDesc = "[Not Provided]";
+
+ return (mfg + " - " + deviceDesc);
+ }
+ }
+
+ /// <summary>
+ /// Number of properties in the array.
+ /// </summary>
+ public int Count
+ {
+ get { return mDeviceProperties.Count; }
+ }
+
+ /// <summary>
+ /// Usb device revision number.
+ /// </summary>
+ public virtual int Rev
+ {
+ get
+ {
+ if (ReferenceEquals(mSymHardwareId, null))
+ {
+ string[] saHardwareIds = mDeviceProperties[SPDRP.HardwareId.ToString()] as string[];
+ if (saHardwareIds != null && saHardwareIds.Length > 0)
+ {
+ mSymHardwareId = UsbSymbolicName.Parse(saHardwareIds[0]);
+ }
+ }
+ if (!ReferenceEquals(mSymHardwareId, null))
+ {
+ return mSymHardwareId.Rev;
+ }
+
+ return 0;
+ }
+ }
+
+ /// <summary>
+ /// Opens the USB device for communucation.
+ /// </summary>
+ /// <returns>Return a new instance of the <see cref="UsbDevice"/> class.
+ /// If the device fails to open a null refrence is return. For extended error
+ /// information see the <see cref="UsbDevice.UsbErrorEvent"/>.
+ /// </returns>
+ public abstract UsbDevice Device { get; }
+
+ /// <summary>
+ /// Opens the USB device for communucation.
+ /// </summary>
+ /// <param name="usbDevice">The newly created UsbDevice.</param>
+ /// <returns>True on success.</returns>
+ public abstract bool Open(out UsbDevice usbDevice);
+
+ internal static Guid GetAsGuid(byte[] buffer, int len)
+ {
+ Guid rtn = Guid.Empty;
+ if (len == 16)
+ {
+ byte[] guidBytes = new byte[len];
+ Array.Copy(buffer, guidBytes, guidBytes.Length);
+ rtn = new Guid(guidBytes);
+ }
+
+ return rtn;
+ }
+
+ internal static string GetAsString(byte[] buffer, int len)
+ {
+ if (len > 2) return Encoding.Unicode.GetString(buffer, 0, len).TrimEnd(ChNull);
+
+ return "";
+ }
+
+ internal static string[] GetAsStringArray(byte[] buffer, int len) { return GetAsString(buffer, len).Split(new char[] {'\0'}, StringSplitOptions.RemoveEmptyEntries); }
+
+ internal static Int32 GetAsStringInt32(byte[] buffer, int len)
+ {
+ Int32 iRtn = 0;
+ if (len == 4)
+ iRtn = buffer[0] | ((buffer[1]) << 8) | ((buffer[2]) << 16) | ((buffer[3]) << 24);
+ return iRtn;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/UsbRequestRecipient.cs b/LibWinUsb/Main/UsbRequestRecipient.cs
new file mode 100644
index 00000000..8ac943c1
--- /dev/null
+++ b/LibWinUsb/Main/UsbRequestRecipient.cs
@@ -0,0 +1,48 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+
+namespace LibUsbDotNet.Main
+{
+ ///<summary>Recipient of the request.</summary>
+ /// <seealso cref="UsbCtrlFlags"/>
+ [Flags]
+ public enum UsbRequestRecipient : byte
+ {
+ /// <summary>
+ /// Device is recipient.
+ /// </summary>
+ RecipDevice = 0x00,
+ /// <summary>
+ /// Endpoint is recipient.
+ /// </summary>
+ RecipEndpoint = 0x02,
+ /// <summary>
+ /// Interface is recipient.
+ /// </summary>
+ RecipInterface = 0x01,
+ /// <summary>
+ /// Other is recipient.
+ /// </summary>
+ RecipOther = 0x03,
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/UsbRequestType.cs b/LibWinUsb/Main/UsbRequestType.cs
new file mode 100644
index 00000000..7c82c9a0
--- /dev/null
+++ b/LibWinUsb/Main/UsbRequestType.cs
@@ -0,0 +1,50 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary>
+ /// Standard USB requests.
+ /// </summary>
+ /// <seealso cref="UsbCtrlFlags"/>
+ [Flags]
+ public enum UsbRequestType : byte
+ {
+ /// <summary>
+ /// Class specific request.
+ /// </summary>
+ TypeClass = (0x01 << 5),
+ /// <summary>
+ /// RESERVED.
+ /// </summary>
+ TypeReserved = (0x03 << 5),
+ /// <summary>
+ /// Standard request.
+ /// </summary>
+ TypeStandard = (0x00 << 5),
+ /// <summary>
+ /// Vendor specific request.
+ /// </summary>
+ TypeVendor = (0x02 << 5),
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/UsbSetupPacket.cs b/LibWinUsb/Main/UsbSetupPacket.cs
new file mode 100644
index 00000000..fb045e80
--- /dev/null
+++ b/LibWinUsb/Main/UsbSetupPacket.cs
@@ -0,0 +1,95 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System.Runtime.InteropServices;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary> Transfers data to the main control endpoint (Endpoint 0).
+ /// </summary>
+ /// <remarks> All USB devices respond to requests from the host on the device’s Default Control Pipe. These requests are made using control transfers. The request and the request’s parameters are sent to the device in the Setup packet. The host is responsible for establishing the values passed in the fields. Every Setup packet has eight bytes.
+ /// </remarks>
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct UsbSetupPacket
+ {
+ /// <summary>
+ /// This bitmapped field identifies the characteristics of the specific request. In particular, this field identifies the direction of data transfer in the second phase of the control transfer. The state of the Direction bit is ignored if the wLength field is zero, signifying there is no Data stage.
+ /// The USB Specification defines a series of standard requests that all devices must support. In addition, a device class may define additional requests. A device vendor may also define requests supported by the device.
+ /// Requests may be directed to the device, an interface on the device, or a specific endpoint on a device. This field also specifies the intended recipient of the request. When an interface or endpoint is specified, the wIndex field identifies the interface or endpoint.
+ /// </summary>
+ /// <remarks>
+ /// <ul>Characteristics of request:
+ /// <li>D7: Data transfer direction</li>
+ /// <li>0 = Host-to-device</li>
+ /// <li>1 = Device-to-host</li>
+ /// <li>D6...5: Type</li>
+ /// <li>0 = Standard</li>
+ /// <li>1 = Class</li>
+ /// <li>2 = Vendor</li>
+ /// <li>3 = Reserved</li>
+ /// <li>D4...0: Recipient</li>
+ /// <li>0 = Device</li>
+ /// <li>1 = Interface</li>
+ /// <li>2 = Endpoint</li>
+ /// <li>3 = Other</li>
+ /// <li>4...31 = Reserved</li>
+ /// </ul>
+ /// </remarks>
+ public byte RequestType;
+
+ /// <summary>
+ /// This field specifies the particular request. The Type bits in the bmRequestType field modify the meaning of this field. This specification defines values for the bRequest field only when the bits are reset to zero, indicating a standard request.
+ /// </summary>
+ public byte Request;
+
+ /// <summary>
+ /// The contents of this field vary according to the request. It is used to pass a parameter to the device, specific to the request.
+ /// </summary>
+ public short Value;
+
+ /// <summary>
+ /// The contents of this field vary according to the request. It is used to pass a parameter to the device, specific to the request.
+ /// </summary>
+ public short Index;
+
+ /// <summary>
+ /// This field specifies the length of the data transferred during the second phase of the control transfer. The direction of data transfer (host-to-device or device-to-host) is indicated by the Direction bit of the <see cref="RequestType"/> field. If this field is zero, there is no data transfer phase. On an input request, a device must never return more data than is indicated by the wLength value; it may return less. On an output request, wLength will always indicate the exact amount of data to be sent by the host. Device behavior is undefined if the host should send more data than is specified in wLength.
+ /// </summary>
+ public short Length;
+
+ /// <summary>
+ /// Creates a new instance of a <see cref="UsbSetupPacket"/> and initializes all the fields with the following parameters.
+ /// </summary>
+ /// <param name="requestType">See <see cref="UsbSetupPacket.RequestType"/>.</param>
+ /// <param name="request">See <see cref="UsbSetupPacket.Request"/>.</param>
+ /// <param name="value">See <see cref="UsbSetupPacket.Value"/>.</param>
+ /// <param name="index">See <see cref="UsbSetupPacket.Index"/>.</param>
+ /// <param name="length">See <see cref="UsbSetupPacket.Length"/>.</param>
+ public UsbSetupPacket(byte requestType, byte request, short value, short index, short length)
+ {
+ RequestType = requestType;
+ Request = request;
+ Value = value;
+ Index = index;
+ Length = length;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/UsbStandardRequest.cs b/LibWinUsb/Main/UsbStandardRequest.cs
new file mode 100644
index 00000000..301ef892
--- /dev/null
+++ b/LibWinUsb/Main/UsbStandardRequest.cs
@@ -0,0 +1,78 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+
+using System;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary>
+ /// Standard Device Requests.
+ /// </summary>
+ [Flags]
+ public enum UsbStandardRequest : byte
+ {
+ /// <summary>
+ /// Clear or disable a specific feature.
+ /// </summary>
+ ClearFeature = 0x01,
+ /// <summary>
+ /// Returns the current device Configuration value.
+ /// </summary>
+ GetConfiguration = 0x08,
+ /// <summary>
+ /// Returns the specified descriptor if the descriptor exists.
+ /// </summary>
+ GetDescriptor = 0x06,
+ /// <summary>
+ /// Returns the selected alternate setting for the specified interface.
+ /// </summary>
+ GetInterface = 0x0A,
+ /// <summary>
+ /// Returns status for the specified recipient.
+ /// </summary>
+ GetStatus = 0x00,
+ /// <summary>
+ /// Sets the device address for all future device accesses.
+ /// </summary>
+ SetAddress = 0x05,
+ /// <summary>
+ /// Sets the device Configuration.
+ /// </summary>
+ SetConfiguration = 0x09,
+ /// <summary>
+ /// Optional and may be used to update existing descriptors or new descriptors may be added.
+ /// </summary>
+ SetDescriptor = 0x07,
+ /// <summary>
+ /// used to set or enable a specific feature.
+ /// </summary>
+ SetFeature = 0x03,
+ /// <summary>
+ /// Allows the host to select an alternate setting for the specified interface.
+ /// </summary>
+ SetInterface = 0x0B,
+ /// <summary>
+ /// Used to set and then report an endpoint’s synchronization frame.
+ /// </summary>
+ SynchFrame = 0x0C,
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/UsbStatusClodes.cs b/LibWinUsb/Main/UsbStatusClodes.cs
new file mode 100644
index 00000000..c2fe4b1c
--- /dev/null
+++ b/LibWinUsb/Main/UsbStatusClodes.cs
@@ -0,0 +1,31 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.Main
+{
+ internal enum UsbStatusClodes
+ {
+ /// <summary>
+ /// Returned bo overlapped IO functions when data is still pending.
+ /// </summary>
+ ErrorIoPending = 997
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/UsbStream.cs b/LibWinUsb/Main/UsbStream.cs
new file mode 100644
index 00000000..542f65d8
--- /dev/null
+++ b/LibWinUsb/Main/UsbStream.cs
@@ -0,0 +1,286 @@
+// Copyright © 2006-2009 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Windows.Forms;
+
+namespace LibUsbDotNet.Main
+{
+ public class IOCancelledException : IOException
+ {
+ public IOCancelledException(string message) : base(message) { }
+ }
+
+ public class UsbStreamAsyncTransfer : IAsyncResult
+ {
+ internal readonly int mCount;
+ internal readonly int mOffset;
+ internal readonly object mState;
+ private readonly int mTimeout;
+ internal AsyncCallback mCallback;
+ internal ManualResetEvent mCompleteEvent = new ManualResetEvent(false);
+ internal GCHandle mGCBuffer;
+ internal bool mIsComplete;
+ private ErrorCode mResult;
+ private int mTrasferredLength;
+ internal UsbEndpointBase mUsbEndpoint;
+
+ public UsbStreamAsyncTransfer(UsbEndpointBase usbEndpoint,
+ byte[] buffer,
+ int offset,
+ int count,
+ AsyncCallback callback,
+ object state,
+ int timeout)
+ {
+ mUsbEndpoint = usbEndpoint;
+ mOffset = offset;
+ mCount = count;
+ mState = state;
+ mTimeout = timeout;
+ mCallback = callback;
+ mGCBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+ }
+
+ public ErrorCode Result
+ {
+ get { return mResult; }
+ }
+
+ public int TransferredLength
+ {
+ get { return mTrasferredLength; }
+ }
+
+ #region IAsyncResult Members
+
+ public bool IsCompleted
+ {
+ get { return mIsComplete; }
+ }
+
+ public WaitHandle AsyncWaitHandle
+ {
+ get { return mCompleteEvent; }
+ }
+
+ public object AsyncState
+ {
+ get { return mState; }
+ }
+
+ public bool CompletedSynchronously
+ {
+ get { return false; }
+ }
+
+ #endregion
+
+ public ErrorCode SyncTransfer()
+ {
+ mResult = mUsbEndpoint.Transfer(mGCBuffer.AddrOfPinnedObject(), mOffset, mCount, mTimeout, out mTrasferredLength);
+ mGCBuffer.Free();
+ mIsComplete = true;
+ if (mCallback != null) mCallback(this as IAsyncResult);
+ mCompleteEvent.Set();
+ return mResult;
+ }
+ }
+
+ public class UsbStream : Stream
+ {
+ private readonly UsbEndpointBase mUsbEndpoint;
+ private int mTimeout = UsbConstants.DEFAULT_TIMEOUT;
+ private Thread mWaitThread;
+
+ public UsbStream(UsbEndpointBase usbEndpoint) { mUsbEndpoint = usbEndpoint; }
+
+ #region NOT SUPPORTED
+
+ public override long Length
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+
+
+ public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); }
+
+ public override void SetLength(long value) { throw new NotSupportedException(); }
+
+ #endregion
+
+ #region Overridden Members
+
+ public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+ UsbStreamAsyncTransfer asyncTransfer = new UsbStreamAsyncTransfer(mUsbEndpoint, buffer, offset, count, callback, state, ReadTimeout);
+ WaitThread.Start(asyncTransfer);
+ return asyncTransfer;
+ }
+ private Thread WaitThread
+ {
+ get
+ {
+ if (ReferenceEquals(mWaitThread,null))
+ mWaitThread=new Thread(AsyncTransferFn);
+
+ while (mWaitThread.IsAlive)Application.DoEvents();
+
+ return mWaitThread;
+ }
+ }
+ public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+ UsbStreamAsyncTransfer asyncTransfer = new UsbStreamAsyncTransfer(mUsbEndpoint, buffer, offset, count, callback, state, WriteTimeout);
+ WaitThread.Start(asyncTransfer);
+ return asyncTransfer;
+ }
+
+ public override bool CanRead
+ {
+ get { return (mUsbEndpoint.EpNum & 0x80) == 0x80; }
+ }
+
+ public override bool CanSeek
+ {
+ get { return false; }
+ }
+
+ public override bool CanTimeout
+ {
+ get { return true; }
+ }
+
+ public override bool CanWrite
+ {
+ get { return (mUsbEndpoint.EpNum & 0x80) == 0; }
+ }
+
+ public override int EndRead(IAsyncResult asyncResult)
+ {
+ UsbStreamAsyncTransfer asyncTransfer = (UsbStreamAsyncTransfer) asyncResult;
+ asyncTransfer.mCompleteEvent.WaitOne();
+
+ if (asyncTransfer.Result == ErrorCode.Success) return asyncTransfer.TransferredLength;
+
+ if (asyncTransfer.Result == ErrorCode.IoTimedOut)
+ throw new TimeoutException(String.Format("{0}:Endpoint 0x{1:X2} IO timed out.", asyncTransfer.Result, mUsbEndpoint.EpNum));
+ if (asyncTransfer.Result == ErrorCode.IoCancelled)
+ throw new IOCancelledException(String.Format("{0}:Endpoint 0x{1:X2} IO was cancelled.", asyncTransfer.Result, mUsbEndpoint.EpNum));
+
+ throw new IOException(string.Format("{0}:Failed reading from endpoint:{1}", asyncTransfer.Result, mUsbEndpoint.EpNum));
+ }
+
+ public override void EndWrite(IAsyncResult asyncResult)
+ {
+ UsbStreamAsyncTransfer asyncTransfer = (UsbStreamAsyncTransfer) asyncResult;
+ asyncTransfer.mCompleteEvent.WaitOne();
+
+ if (asyncTransfer.Result == ErrorCode.Success && asyncTransfer.mCount == asyncTransfer.TransferredLength) return;
+
+ if (asyncTransfer.Result == ErrorCode.IoTimedOut)
+ throw new TimeoutException(String.Format("{0}:Endpoint 0x{1:X2} IO timed out.", asyncTransfer.Result, mUsbEndpoint.EpNum));
+ if (asyncTransfer.Result == ErrorCode.IoCancelled)
+ throw new IOCancelledException(String.Format("{0}:Endpoint 0x{1:X2} IO was cancelled.", asyncTransfer.Result, mUsbEndpoint.EpNum));
+ if (asyncTransfer.mCount != asyncTransfer.TransferredLength)
+ throw new IOException(String.Format("{0}:Failed writing {1} byte(s) to endpoint 0x{2:X2}.",
+ asyncTransfer.Result,
+ asyncTransfer.mCount - asyncTransfer.TransferredLength,
+ mUsbEndpoint.EpNum));
+
+ throw new IOException(String.Format("{0}:Failed writing to endpoint 0x{1:X2}", asyncTransfer.Result, mUsbEndpoint.EpNum));
+ }
+
+ public override void Flush() { return; }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ if (!CanRead)
+ throw new InvalidOperationException(String.Format("Cannot read from WriteEndpoint {0}.", (WriteEndpointID) mUsbEndpoint.EpNum));
+
+ int transferred;
+ ErrorCode ec = mUsbEndpoint.Transfer(buffer, offset, count, ReadTimeout, out transferred);
+
+ if (ec == ErrorCode.Success) return transferred;
+
+ if (ec == ErrorCode.IoTimedOut) throw new TimeoutException(String.Format("{0}:Endpoint 0x{1:X2} IO timed out.", ec, mUsbEndpoint.EpNum));
+ if (ec == ErrorCode.IoCancelled)
+ throw new IOCancelledException(String.Format("{0}:Endpoint 0x{1:X2} IO was cancelled.", ec, mUsbEndpoint.EpNum));
+
+ throw new IOException(string.Format("{0}:Failed reading from endpoint:{1}", ec, mUsbEndpoint.EpNum));
+ }
+
+ public override int ReadTimeout
+ {
+ get { return mTimeout; }
+ set { mTimeout = value; }
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ if (!CanWrite)
+ throw new InvalidOperationException(String.Format("Cannot write to ReadEndpoint {0}.", (ReadEndpointID) mUsbEndpoint.EpNum));
+
+ int transferred;
+ ErrorCode ec = mUsbEndpoint.Transfer(buffer, offset, count, WriteTimeout, out transferred);
+
+ if (ec == ErrorCode.Success && count == transferred) return;
+
+ if (ec == ErrorCode.IoTimedOut) throw new TimeoutException(String.Format("{0}:Endpoint 0x{1:X2} IO timed out.", ec, mUsbEndpoint.EpNum));
+ if (ec == ErrorCode.IoCancelled)
+ throw new IOCancelledException(String.Format("{0}:Endpoint 0x{1:X2} IO was cancelled.", ec, mUsbEndpoint.EpNum));
+ if (count != transferred)
+ throw new IOException(String.Format("{0}:Failed writing {1} byte(s) to endpoint 0x{2:X2}.",
+ ec,
+ count - transferred,
+ mUsbEndpoint.EpNum));
+
+ throw new IOException(String.Format("{0}:Failed writing to endpoint 0x{1:X2}", ec, mUsbEndpoint.EpNum));
+ }
+
+ public override int WriteTimeout
+ {
+ get { return mTimeout; }
+ set { mTimeout = value; }
+ }
+
+ #endregion
+
+ #region STATIC Members
+
+ private static void AsyncTransferFn(object oContext)
+ {
+ UsbStreamAsyncTransfer context = oContext as UsbStreamAsyncTransfer;
+ context.SyncTransfer();
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/UsbSymbolicName.cs b/LibWinUsb/Main/UsbSymbolicName.cs
new file mode 100644
index 00000000..0bf268f6
--- /dev/null
+++ b/LibWinUsb/Main/UsbSymbolicName.cs
@@ -0,0 +1,227 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Globalization;
+using System.Text.RegularExpressions;
+using LibUsbDotNet.Internal.UsbRegex;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary> USB device symbolic names are persistent accrossed boots and uniquely identify each device.
+ /// </summary>
+ /// <remarks> As well as uniquely identify connected devices, the UsbSymbolicName class parses the symbolic name key into usable fields.
+ /// </remarks>
+ public class UsbSymbolicName
+ {
+ private static RegHardwareID _regHardwareId;
+ private static RegSymbolicName _regSymbolicName;
+ private readonly string mSymbolicName;
+
+ private Guid mClassGuid = Guid.Empty;
+ private bool mIsParsed;
+ private int mProductID;
+ private int mRevisionCode;
+ private string mSerialNumber = String.Empty;
+ private int mVendorID;
+
+ internal UsbSymbolicName(string symbolicName) { mSymbolicName = symbolicName; }
+
+ private static RegSymbolicName RegSymbolicName
+ {
+ get
+ {
+ if (ReferenceEquals(_regSymbolicName, null))
+ {
+ _regSymbolicName = new RegSymbolicName();
+ }
+
+ return _regSymbolicName;
+ }
+ }
+
+ private static RegHardwareID RegHardwareId
+ {
+ get
+ {
+ if (ReferenceEquals(_regHardwareId, null))
+ {
+ _regHardwareId = new RegHardwareID();
+ }
+
+ return _regHardwareId;
+ }
+ }
+
+ /// <summary>
+ /// The full symbolic name of the device.
+ /// </summary>
+ public string FullName
+ {
+ get
+ {
+ if (mSymbolicName != null) return mSymbolicName.TrimStart(new char[] {'\\', '?'});
+ return String.Empty;
+ }
+ }
+
+ /// <summary>
+ /// VendorId parsed out of the <see cref="UsbSymbolicName.FullName"/>
+ /// </summary>
+ public int Vid
+ {
+ get
+ {
+ Parse();
+ return mVendorID;
+ }
+ }
+
+ /// <summary>
+ /// ProductId parsed out of the <see cref="UsbSymbolicName.FullName"/>
+ /// </summary>
+ public int Pid
+ {
+ get
+ {
+ Parse();
+ return mProductID;
+ }
+ }
+
+ /// <summary>
+ /// SerialNumber parsed out of the <see cref="UsbSymbolicName.FullName"/>
+ /// </summary>
+ public string SerialNumber
+ {
+ get
+ {
+ Parse();
+ return mSerialNumber;
+ }
+ }
+
+ /// <summary>
+ /// Device class parsed out of the <see cref="UsbSymbolicName.FullName"/>
+ /// </summary>
+ public Guid ClassGuid
+ {
+ get
+ {
+ Parse();
+ return mClassGuid;
+ }
+ }
+
+ /// <summary>
+ /// Usb device revision number.
+ /// </summary>
+ public int Rev
+ {
+ get
+ {
+ Parse();
+ return mRevisionCode;
+ }
+ }
+
+
+ /// <summary>
+ /// Parses registry strings containing USB information. This function can Parse symbolic names as well as hardware ids, compatible ids, etc.
+ /// </summary>
+ /// <param name="identifiers"></param>
+ /// <returns>A <see cref="UsbSymbolicName"/> class with all the available information from the <paramref name="identifiers"/> string.</returns>
+ /// <remarks>
+ /// <code>
+ /// List&lt;UsbRegistryDeviceInfo&gt; regDeviceList = UsbGlobals.RegFindDevices();
+ /// foreach (UsbRegistryDeviceInfo regDevice in mDevList)
+ /// {
+ /// string[] hardwareIds = (string[])regDevice.Properties[DevicePropertyType.HardwareID];
+ /// UsbSymbolicName usbHardwareID = UsbSymbolicName.Parse(hardwareIds[0]);
+ /// Debug.Print(string.Format("Vid:0x{0:X4} Pid:0x{1:X4}", usbHardwareID.Vid, usbHardwareID.Pid));
+ /// }
+ /// </code>
+ /// </remarks>
+ public static UsbSymbolicName Parse(string identifiers) { return new UsbSymbolicName(identifiers); }
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbSymbolicName"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="UsbSymbolicName"/>.
+ ///</returns>
+ public override string ToString()
+ {
+ object[] o = new object[] {FullName, Vid.ToString("X4"), Pid.ToString("X4"), SerialNumber, ClassGuid};
+ return string.Format("FullName:{0}\r\nVid:0x{1}\r\nPid:0x{2}\r\nSerialNumber:{3}\r\nClassGuid:{4}\r\n", o);
+ }
+
+
+ private void Parse()
+ {
+ if (!mIsParsed)
+ {
+ mIsParsed = true;
+ if (mSymbolicName != null)
+ {
+ MatchCollection matches = RegSymbolicName.Matches(mSymbolicName);
+ foreach (Match match in matches)
+ {
+ Group gVid = match.Groups[(int) NamedGroupType.Vid];
+ Group gPid = match.Groups[(int) NamedGroupType.Pid];
+ Group gRev = match.Groups[(int) NamedGroupType.Rev];
+ Group gString = match.Groups[(int) NamedGroupType.String];
+ Group gClass = match.Groups[(int) NamedGroupType.ClassGuid];
+
+ if (gVid.Success && mVendorID == 0)
+ {
+ int.TryParse(gVid.Captures[0].Value, NumberStyles.HexNumber, null, out mVendorID);
+ }
+ if (gPid.Success && mProductID == 0)
+ {
+ int.TryParse(gPid.Captures[0].Value, NumberStyles.HexNumber, null, out mProductID);
+ }
+ if (gRev.Success && mRevisionCode == 0)
+ {
+ int.TryParse(gRev.Captures[0].Value, out mRevisionCode);
+ }
+ if ((gString.Success) && mSerialNumber == String.Empty)
+ {
+ mSerialNumber = gString.Captures[0].Value;
+ }
+ if ((gClass.Success) && mClassGuid == Guid.Empty)
+ {
+ try
+ {
+ mClassGuid = new Guid(gClass.Captures[0].Value);
+ }
+ catch (Exception)
+ {
+ mClassGuid = Guid.Empty;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/UsbTransfer.cs b/LibWinUsb/Main/UsbTransfer.cs
new file mode 100644
index 00000000..52646d1f
--- /dev/null
+++ b/LibWinUsb/Main/UsbTransfer.cs
@@ -0,0 +1,629 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Diagnostics;
+using System.Threading;
+
+namespace LibUsbDotNet.Main
+{
+ /// <summary>
+ /// Base class for async transfer context.
+ /// </summary>
+ public abstract class UsbTransfer : IDisposable,IAsyncResult
+ {
+ private readonly UsbEndpointBase mEndpointBase;
+
+ private IntPtr mBuffer;
+ private int mCurrentOffset;
+ private int mCurrentRemaining;
+ private int mCurrentTransmitted;
+
+ /// <summary></summary>
+ protected int mIsoPacketSize;
+
+ /// <summary></summary>
+ protected int mOriginalCount;
+ /// <summary></summary>
+ protected int mOriginalOffset;
+ private PinnedHandle mPinnedHandle;
+
+ /// <summary></summary>
+ protected int mTimeout;
+
+ /// <summary></summary>
+ protected bool mHasWaitBeenCalled = true;
+
+ /// <summary></summary>
+ protected readonly object mTransferLOCK = new object();
+
+ /// <summary></summary>
+ protected ManualResetEvent mTransferCancelEvent = new ManualResetEvent(false);
+ /// <summary></summary>
+ protected internal ManualResetEvent mTransferCompleteEvent = new ManualResetEvent(true);
+
+ /// <summary></summary>
+ protected UsbTransfer(UsbEndpointBase endpointBase) { mEndpointBase = endpointBase; }
+
+ /// <summary>
+ /// Returns the <see cref="UsbEndpointReader"/> or <see cref="UsbEndpointWriter"/> this transfer context is associated with.
+ /// </summary>
+ public UsbEndpointBase EndpointBase
+ {
+ get { return mEndpointBase; }
+ }
+
+ /// <summary>
+ /// Number of bytes that will be requested for the next transfer.
+ /// </summary>
+ protected int RequestCount
+ {
+ get { return (mCurrentRemaining > UsbEndpointBase.MaxReadWrite ? UsbEndpointBase.MaxReadWrite : mCurrentRemaining); }
+ }
+
+ ///// <summary></summary>
+ //protected int FailRetries
+ //{
+ // get { return mFailRetries; }
+ //}
+
+ /// <summary></summary>
+ protected IntPtr NextBufPtr
+ {
+ get { return new IntPtr(mBuffer.ToInt64() + mCurrentOffset); }
+ }
+
+ ///<summary>
+ /// True if the transfer has been cacelled with <see cref="Cancel"/>.
+ ///</summary>
+ public bool IsCancelled
+ {
+ get { return mTransferCancelEvent.WaitOne(0, UsbConstants.EXIT_CONTEXT); }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="WaitHandle"/> for the cancel event.
+ /// </summary>
+ public WaitHandle CancelWaitHandle
+ {
+ get { return mTransferCancelEvent; }
+ }
+
+ /// <summary>
+ /// Gets the size of each isochronous packet.
+ /// </summary>
+ /// <remarks>
+ /// To change the packet size see <see cref="Fill(System.IntPtr,int,int,int,int)"/>
+ /// </remarks>
+ public int IsoPacketSize
+ {
+ get { return mIsoPacketSize; }
+ }
+
+
+ #region IDisposable Members
+
+ /// <summary>
+ /// Cancels any pending transfer and frees resources.
+ /// </summary>
+ public virtual void Dispose()
+ {
+ if (!IsCancelled) Cancel();
+
+ int dummy;
+ if (!mHasWaitBeenCalled) Wait(out dummy);
+ if (mPinnedHandle != null) mPinnedHandle.Dispose();
+ mPinnedHandle = null;
+ }
+
+ #endregion
+
+ ~UsbTransfer() { Dispose(); }
+
+ /// <summary>
+ /// Cancels a pending transfer that was previously submitted with <see cref="Submit"/>.
+ /// </summary>
+ /// <returns></returns>
+ public virtual ErrorCode Cancel()
+ {
+ mTransferCancelEvent.Set();
+ mTransferCompleteEvent.WaitOne(5000, false);
+
+ return ErrorCode.Success;
+ }
+
+ /// <summary>
+ /// Submits the transfer.
+ /// </summary>
+ /// <remarks>
+ /// This functions submits the USB transfer and return immediately.
+ /// </remarks>
+ /// <returns>
+ /// <see cref="ErrorCode.Success"/> if the submit succeeds,
+ /// otherwise one of the other <see cref="ErrorCode"/> codes.
+ /// </returns>
+ public abstract ErrorCode Submit();
+
+ /// <summary>
+ /// Wait for the transfer to complete, timeout, or get cancelled.
+ /// </summary>
+ /// <param name="transferredCount">The number of bytes transferred on <see cref="ErrorCode.Success"/>.</param>
+ /// <param name="cancel">If true, the transfer is cancelled if it does not complete within the time specified in <see cref="Timeout"/>.</param>
+ /// <returns><see cref="ErrorCode.Success"/> if the transfer completes successfully, otherwise one of the other <see cref="ErrorCode"/> codes.</returns>
+ public abstract ErrorCode Wait(out int transferredCount, bool cancel);
+
+ /// <summary>
+ /// Wait for the transfer to complete, timeout, or get cancelled.
+ /// </summary>
+ /// <param name="transferredCount">The number of bytes transferred on <see cref="ErrorCode.Success"/>.</param>
+ /// <returns><see cref="ErrorCode.Success"/> if the transfer completes successfully, otherwise one of the other <see cref="ErrorCode"/> codes.</returns>
+ public ErrorCode Wait(out int transferredCount) { return Wait(out transferredCount, true); }
+
+ /// <summary>
+ /// Fills the transfer with the data to <see cref="Submit"/>.
+ /// </summary>
+ /// <param name="buffer">The buffer; See <see cref="PinnedHandle"/> for more details.</param>
+ /// <param name="offset">The offset on the buffer where the transfer should read/write.</param>
+ /// <param name="count">The number of bytes to transfer.</param>
+ /// <param name="timeout">Time (milliseconds) to wait before the transfer times out.</param>
+ public virtual void Fill(object buffer, int offset, int count, int timeout)
+ {
+ if (mPinnedHandle != null) mPinnedHandle.Dispose();
+ mPinnedHandle = new PinnedHandle(buffer);
+ Fill(mPinnedHandle.Handle, offset, count, timeout);
+ }
+ /// <summary>
+ /// Fills the transfer with the data to <see cref="Submit"/> an isochronous transfer.
+ /// </summary>
+ /// <param name="buffer">The buffer; See <see cref="PinnedHandle"/> for more details.</param>
+ /// <param name="offset">The offset on the buffer where the transfer should read/write.</param>
+ /// <param name="count">The number of bytes to transfer.</param>
+ /// <param name="timeout">Time (milliseconds) to wait before the transfer times out.</param>
+ /// <param name="isoPacketSize">Size of each isochronous packet.</param>
+ public virtual void Fill(object buffer, int offset, int count, int timeout, int isoPacketSize)
+ {
+ if (mPinnedHandle != null) mPinnedHandle.Dispose();
+ mPinnedHandle = new PinnedHandle(buffer);
+ Fill(mPinnedHandle.Handle, offset, count, timeout, isoPacketSize);
+ }
+ /// <summary>
+ /// Fills the transfer with the data to <see cref="Submit"/>.
+ /// </summary>
+ /// <param name="buffer">The buffer.</param>
+ /// <param name="offset">The offset on the buffer where the transfer should read/write.</param>
+ /// <param name="count">The number of bytes to transfer.</param>
+ /// <param name="timeout">Time (milliseconds) to wait before the transfer times out.</param>
+ public virtual void Fill(IntPtr buffer, int offset, int count, int timeout)
+ {
+ mBuffer = buffer;
+
+ mOriginalOffset = offset;
+ mOriginalCount = count;
+ mTimeout = timeout;
+ Reset();
+ }
+ /// <summary>
+ /// Fills the transfer with the data to <see cref="Submit"/> an isochronous transfer.
+ /// </summary>
+ /// <param name="buffer">The buffer.</param>
+ /// <param name="offset">The offset on the buffer where the transfer should read/write.</param>
+ /// <param name="count">The number of bytes to transfer.</param>
+ /// <param name="timeout">Time (milliseconds) to wait before the transfer times out.</param>
+ /// <param name="isoPacketSize">Size of each isochronous packet.</param>
+ public virtual void Fill(IntPtr buffer, int offset, int count, int timeout, int isoPacketSize)
+ {
+ mBuffer = buffer;
+
+ mOriginalOffset = offset;
+ mOriginalCount = count;
+ mTimeout = timeout;
+ mIsoPacketSize = isoPacketSize;
+ Reset();
+ }
+ internal static ErrorCode SyncTransfer(UsbTransfer transferContext,
+ IntPtr buffer,
+ int offset,
+ int length,
+ int timeout,
+ out int transferLength)
+ {
+ return SyncTransfer(transferContext, buffer, offset, length, timeout, 0, out transferLength);
+ }
+ internal static ErrorCode SyncTransfer(UsbTransfer transferContext,
+ IntPtr buffer,
+ int offset,
+ int length,
+ int timeout,
+ int isoPacketSize,
+ out int transferLength)
+ {
+ if (ReferenceEquals(transferContext, null)) throw new NullReferenceException("Invalid transfer context.");
+ if (offset < 0) throw new ArgumentException("must be >=0", "offset");
+ if (isoPacketSize == 0 && transferContext.EndpointBase.Type == EndpointType.Isochronous)
+ {
+ Info.UsbEndpointInfo endpointInfo = transferContext.EndpointBase.EndpointInfo;
+ if (endpointInfo!=null)
+ isoPacketSize = endpointInfo.Descriptor.MaxPacketSize;
+ }
+ lock (transferContext.mTransferLOCK)
+ {
+ transferLength = 0;
+
+ int transferred;
+ ErrorCode ec;
+ transferContext.Fill(buffer, offset, length, timeout, isoPacketSize);
+
+ while (true)
+ {
+ ec = transferContext.Submit();
+ if (ec != ErrorCode.Success) return ec;
+
+ ec = transferContext.Wait(out transferred);
+ if (ec != ErrorCode.Success) return ec;
+
+ transferLength += transferred;
+
+ if ((ec != ErrorCode.None || transferred != UsbEndpointBase.MaxReadWrite) ||
+ !transferContext.IncrementTransfer(transferred))
+ break;
+ }
+
+ return ec;
+ }
+ }
+
+ /// <summary>
+ /// Increments the internal counters to the next transfer batch (for transfers greater than <see cref="UsbEndpointBase.MaxReadWrite"/>)
+ /// </summary>
+ /// <param name="amount">This will usually be the total transferred on the previous batch.</param>
+ /// <returns>True if the buffer still has data available and internal counters were successfully incremented.</returns>
+ public bool IncrementTransfer(int amount)
+ {
+ mCurrentTransmitted += amount;
+ mCurrentRemaining -= amount;
+ mCurrentOffset += amount;
+
+ if ((mCurrentRemaining) <= 0)
+ {
+ Debug.Assert(mCurrentRemaining == 0);
+ return false;
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Totoal number of bytes transferred.
+ /// </summary>
+ public int Transmitted
+ {
+ get
+ {
+ return mCurrentTransmitted;
+ }
+ }
+
+ /// <summary>
+ /// Remaining bytes in the transfer data buffer.
+ /// </summary>
+ public int Remaining
+ {
+ get
+ {
+ return mCurrentRemaining;
+ }
+ }
+ /// <summary>
+ /// Resets the transfer to its orignal state.
+ /// </summary>
+ /// <remarks>
+ /// Prepares a <see cref="UsbTransfer"/> to be resubmitted.
+ /// </remarks>
+ public void Reset()
+ {
+ mCurrentOffset = mOriginalOffset;
+ mCurrentRemaining = mOriginalCount;
+ mCurrentTransmitted = 0;
+
+ mTransferCancelEvent.Reset();
+ }
+
+ /// <summary>
+ /// Gets an indication whether the asynchronous operation has completed.
+ /// </summary>
+ /// <returns>
+ /// true if the operation is complete; otherwise, false.
+ /// </returns>
+ /// <filterpriority>2</filterpriority>
+ public bool IsCompleted
+ {
+ get { return mTransferCompleteEvent.WaitOne(0, UsbConstants.EXIT_CONTEXT); }
+ }
+
+
+ /// <summary>
+ /// Gets a <see cref="T:System.Threading.WaitHandle"/> that is used to wait for an asynchronous operation to complete.
+ /// </summary>
+ /// <returns>
+ /// A <see cref="T:System.Threading.WaitHandle"/> that is used to wait for an asynchronous operation to complete.
+ /// </returns>
+ /// <filterpriority>2</filterpriority>
+ public WaitHandle AsyncWaitHandle
+ {
+ get { return mTransferCompleteEvent; }
+ }
+
+ /// <summary>
+ /// Gets a user-defined object that qualifies or contains information about an asynchronous operation.
+ /// </summary>
+ /// <returns>
+ /// A user-defined object that qualifies or contains information about an asynchronous operation.
+ /// </returns>
+ /// <filterpriority>2</filterpriority>
+ public object AsyncState
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ /// <summary>
+ /// Gets an indication of whether the asynchronous operation completed synchronously.
+ /// </summary>
+ /// <returns>
+ /// true if the asynchronous operation completed synchronously; otherwise, false.
+ /// </returns>
+ /// <filterpriority>2</filterpriority>
+ public bool CompletedSynchronously
+ {
+ get { return false; }
+ }
+ }
+
+ /// <summary>
+ /// Helper class for maintaining a user defined number of outstanding aync transfers on an endpoint.
+ /// </summary>
+ public class UsbTransferQueue
+ {
+ /// <summary>
+ /// Creates a new transfer queue instance.
+ /// </summary>
+ /// <param name="endpointBase">The endpoint to transfer data to/from.</param>
+ /// <param name="maxOutstandingIO">The number of transfers to <see cref="UsbTransfer.Submit"/> before waiting for a completion.</param>
+ /// <param name="bufferSize">The size of each data buffer.</param>
+ /// <param name="timeout">The maximum time to wait for each transfer.</param>
+ /// <param name="isoPacketSize">For isochronous use only. The iso packet size. If 0, the endpoints max packet size is used.</param>
+ public UsbTransferQueue(UsbEndpointBase endpointBase, int maxOutstandingIO, int bufferSize, int timeout, int isoPacketSize)
+ {
+ EndpointBase = endpointBase;
+ IsoPacketSize = isoPacketSize;
+ Timeout = timeout;
+ BufferSize = bufferSize;
+ MaxOutstandingIO = maxOutstandingIO;
+
+ mTransferHandles = new Handle[maxOutstandingIO];
+
+ mBuffer = new byte[maxOutstandingIO][];
+ for(int i=0; i < maxOutstandingIO; i++)
+ mBuffer[i] = new byte[bufferSize];
+
+ IsoPacketSize = isoPacketSize > 0 ? isoPacketSize : endpointBase.EndpointInfo.Descriptor.MaxPacketSize;
+ }
+
+ /// <summary>
+ /// Endpoint for I/O operations.
+ /// </summary>
+ public readonly UsbEndpointBase EndpointBase;
+
+ /// <summary>
+ /// Maximum outstanding I/O operations before waiting for a completion.
+ /// This is also the number of data buffers allocated for this transfer queue.
+ /// </summary>
+ public readonly int MaxOutstandingIO;
+
+ /// <summary>
+ /// Size (in bytes) of each data buffer in this transfer queue.
+ /// </summary>
+ public readonly int BufferSize;
+
+ /// <summary>
+ /// Time (in milliseconds) to wait for a transfer to complete before returning <see cref="ErrorCode.IoTimedOut"/>.
+ /// </summary>
+ public readonly int Timeout;
+
+ /// <summary>
+ /// For isochronous use only. The iso packet size.
+ /// </summary>
+ public readonly int IsoPacketSize;
+
+ private int mOutstandingTransferCount;
+ private readonly Handle[] mTransferHandles;
+ private readonly byte[][] mBuffer;
+ private int mTransferHandleNextIndex;
+ private int mTransferHandleWaitIndex;
+
+ /// <summary>
+ /// A transfer queue handle.
+ /// </summary>
+ public class Handle
+ {
+ internal Handle(UsbTransfer context, byte[] data)
+ {
+ Context = context;
+ Data = data;
+
+ }
+
+ /// <summary>
+ /// Transfer context.
+ /// </summary>
+ public readonly UsbTransfer Context;
+
+ /// <summary>
+ /// Data buffer.
+ /// </summary>
+ public readonly byte[] Data;
+
+ /// <summary>
+ /// Number of bytes sent/received.
+ /// </summary>
+ public int Transferred;
+
+ internal bool InUse;
+
+ }
+
+ /// <summary>
+ /// Gets the transfer data buffer at the specified index.
+ /// </summary>
+ /// <param name="index">The index of the buffer to retrieve.</param>
+ /// <returns>The byte array for a transfer.</returns>
+ public byte[] this[int index]
+ {
+ get{ return mBuffer[index]; }
+ }
+
+ /// <summary>
+ /// Gets a two dimensional array of data buffers. The first index represents the transfer the second represents the data buffer.
+ /// </summary>
+ public byte[][] Buffer
+ {
+ get { return mBuffer; }
+ }
+
+ private static void IncWithRoll(ref int incField, int rollOverValue)
+ {
+ if ((++incField) >= rollOverValue)
+ incField = 0;
+ }
+
+ /// <summary>
+ /// Submits transfers until <see cref="MaxOutstandingIO"/> is reached then waits for the oldest transfer to complete.
+ /// </summary>
+ /// <param name="handle">The queue handle to the <see cref="UsbTransfer"/> that completed.</param>
+ /// <returns><see cref="ErrorCode.Success"/> if data was transferred, or another <see cref="ErrorCode"/> on error.</returns>
+ public ErrorCode Transfer(out Handle handle)
+ {
+ return transfer(this, out handle);
+ }
+ private static ErrorCode transfer(UsbTransferQueue transferParam, out Handle handle)
+ {
+ handle = null;
+ ErrorCode ret = ErrorCode.Success;
+
+ // Submit transfers until the maximum number of outstanding transfer(s) is reached.
+ while (transferParam.mOutstandingTransferCount < transferParam.MaxOutstandingIO)
+ {
+ if (ReferenceEquals(transferParam.mTransferHandles[transferParam.mTransferHandleNextIndex], null))
+ {
+ handle = transferParam.mTransferHandles[transferParam.mTransferHandleNextIndex] =
+ new Handle(transferParam.EndpointBase.NewAsyncTransfer(), transferParam.mBuffer[transferParam.mTransferHandleNextIndex]);
+
+ // Get the next available benchmark transfer handle.
+ handle.Context.Fill(handle.Data, 0, handle.Data.Length, transferParam.Timeout, transferParam.IsoPacketSize);
+ }
+ else
+ {
+ // Get the next available benchmark transfer handle.
+ handle = transferParam.mTransferHandles[transferParam.mTransferHandleNextIndex];
+
+ }
+
+ handle.Transferred = 0;
+
+ // Submit this transfer now.
+ handle.Context.Reset();
+ ret = handle.Context.Submit();
+ if (ret != ErrorCode.Success) goto Done;
+
+ // Mark this handle has InUse.
+ handle.InUse = true;
+
+ // When transfers ir successfully submitted, OutstandingTransferCount goes up; when
+ // they are completed it goes down.
+ //
+ transferParam.mOutstandingTransferCount++;
+
+ // Move TransferHandleNextIndex to the next available transfer.
+ IncWithRoll(ref transferParam.mTransferHandleNextIndex, transferParam.MaxOutstandingIO);
+ }
+
+ // If the number of outstanding transfers has reached the limit, wait for the
+ // oldest outstanding transfer to complete.
+ //
+ if (transferParam.mOutstandingTransferCount == transferParam.MaxOutstandingIO)
+ {
+ // TransferHandleWaitIndex is the index of the oldest outstanding transfer.
+ handle = transferParam.mTransferHandles[transferParam.mTransferHandleWaitIndex];
+ ret = handle.Context.Wait(out handle.Transferred, false);
+ if (ret != ErrorCode.Success)
+ goto Done;
+
+ // Mark this handle has no longer InUse.
+ handle.InUse = false;
+
+ // When transfers ir successfully submitted, OutstandingTransferCount goes up; when
+ // they are completed it goes down.
+ //
+ transferParam.mOutstandingTransferCount--;
+
+ // Move TransferHandleWaitIndex to the oldest outstanding transfer.
+ IncWithRoll(ref transferParam.mTransferHandleWaitIndex, transferParam.MaxOutstandingIO);
+
+ return ErrorCode.Success;
+ }
+
+ Done:
+ return ret;
+ }
+
+ /// <summary>
+ /// Cancels and frees all oustanding transfers.
+ /// </summary>
+ public void Free()
+ {
+ free(this);
+ }
+
+ private static void free(UsbTransferQueue transferParam)
+ {
+ for (int i = 0; i < transferParam.MaxOutstandingIO; i++)
+ {
+ if (!ReferenceEquals(transferParam.mTransferHandles[i], null))
+ {
+ if (transferParam.mTransferHandles[i].InUse)
+ {
+ if (!transferParam.mTransferHandles[i].Context.IsCompleted)
+ {
+ transferParam.EndpointBase.Abort();
+ Thread.Sleep(1);
+ }
+
+ transferParam.mTransferHandles[i].InUse = false;
+ transferParam.mTransferHandles[i].Context.Dispose();
+ }
+ transferParam.mTransferHandles[i] = null;
+ }
+ }
+ transferParam.mOutstandingTransferCount = 0;
+ transferParam.mTransferHandleNextIndex = 0;
+ transferParam.mTransferHandleWaitIndex = 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/Main/WriteEndpointID.cs b/LibWinUsb/Main/WriteEndpointID.cs
new file mode 100644
index 00000000..feac1142
--- /dev/null
+++ b/LibWinUsb/Main/WriteEndpointID.cs
@@ -0,0 +1,89 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.Main
+{
+ /// <summary> Availabled endpoint numbers/ids for writing.
+ /// </summary>
+ public enum WriteEndpointID : byte
+ {
+ /// <summary>
+ /// Endpoint 1
+ /// </summary>
+ Ep01 = 0x01,
+ /// <summary>
+ /// Endpoint 2
+ /// </summary>
+ Ep02 = 0x02,
+ /// <summary>
+ /// Endpoint 3
+ /// </summary>
+ Ep03 = 0x03,
+ /// <summary>
+ /// Endpoint 4
+ /// </summary>
+ Ep04 = 0x04,
+ /// <summary>
+ /// Endpoint 5
+ /// </summary>
+ Ep05 = 0x05,
+ /// <summary>
+ /// Endpoint 6
+ /// </summary>
+ Ep06 = 0x06,
+ /// <summary>
+ /// Endpoint 7
+ /// </summary>
+ Ep07 = 0x07,
+ /// <summary>
+ /// Endpoint 8
+ /// </summary>
+ Ep08 = 0x08,
+ /// <summary>
+ /// Endpoint 9
+ /// </summary>
+ Ep09 = 0x09,
+ /// <summary>
+ /// Endpoint 10
+ /// </summary>
+ Ep10 = 0x0A,
+ /// <summary>
+ /// Endpoint 11
+ /// </summary>
+ Ep11 = 0x0B,
+ /// <summary>
+ /// Endpoint 12
+ /// </summary>
+ Ep12 = 0x0C,
+ /// <summary>
+ /// Endpoint 13
+ /// </summary>
+ Ep13 = 0x0D,
+ /// <summary>
+ /// Endpoint 14
+ /// </summary>
+ Ep14 = 0x0E,
+ /// <summary>
+ /// Endpoint 15
+ /// </summary>
+ Ep15 = 0x0F,
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/CallbackDelegates.cs b/LibWinUsb/MonoLibUsb/CallbackDelegates.cs
new file mode 100644
index 00000000..10011fce
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/CallbackDelegates.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Runtime.InteropServices;
+using MonoLibUsb.Transfer;
+
+namespace MonoLibUsb
+{
+ /// <summary>
+ /// Asynchronous transfer callback delegate
+ /// </summary>
+ /// <param name="transfer">The transfer previously allocated with <see cref="MonoUsbApi.AllocTransfer"/>.</param>
+ [UnmanagedFunctionPointer(MonoUsbApi.CC)]
+ public delegate void MonoUsbTransferDelegate(MonoUsbTransfer transfer);
+
+ /// <summary>
+ /// Callback delegate, invoked when a new file descriptor should be added to the set of file descriptors monitored for events.
+ /// </summary>
+ /// <param name="fd">The new file descriptor.</param>
+ /// <param name="events">Events to monitor for, see PollfdItem for a description.</param>
+ /// <param name="user_data">User data pointer specified in <see cref="MonoUsbApi.SetPollfdNotifiers"/> call.</param>
+ [UnmanagedFunctionPointer(MonoUsbApi.CC)]
+ public delegate void PollfdAddedDelegate(int fd, short events, IntPtr user_data);
+
+ /// <summary>
+ /// Callback delegate, invoked when a file descriptor should be removed from the set of file descriptors being monitored for events.
+ /// </summary>
+ /// <remarks>After returning from this callback, do not use that file descriptor again. </remarks>
+ /// <param name="fd">The file descriptor to stop monitoring.</param>
+ /// <param name="user_data">User data pointer specified in <see cref="MonoUsbApi.SetPollfdNotifiers"/> call.</param>
+ [UnmanagedFunctionPointer(MonoUsbApi.CC)]
+ public delegate void PollfdRemovedDelegate(int fd, IntPtr user_data);
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Descriptors/MonoUsbAltInterfaceDescriptor.cs b/LibWinUsb/MonoLibUsb/Descriptors/MonoUsbAltInterfaceDescriptor.cs
new file mode 100644
index 00000000..c3b85718
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Descriptors/MonoUsbAltInterfaceDescriptor.cs
@@ -0,0 +1,103 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Descriptors;
+
+namespace MonoLibUsb.Descriptors
+{
+ /// <summary>
+ /// A structure representing the standard USB interface descriptor. This
+ /// descriptor is documented in section 9.6.5 of the USB 2.0 specification.
+ /// All multiple-byte fields are represented in host-endian format.
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential, Pack = MonoUsbApi.LIBUSB_PACK)]
+ public class MonoUsbAltInterfaceDescriptor
+ {
+ ///<summary>Size of this descriptor (in bytes)</summary>
+ public readonly Byte bLength;
+
+ ///<summary>Descriptor type. Will have value LIBUSB_DT_INTERFACE in this context.</summary>
+ public readonly DescriptorType bDescriptorType;
+
+ ///<summary>Number of this interface</summary>
+ public readonly Byte bInterfaceNumber;
+
+ ///<summary>Value used to select this alternate setting for this interface</summary>
+ public readonly Byte bAlternateSetting;
+
+ ///<summary> Number of endpoints used by this interface (excluding the control endpoint).</summary>
+ public readonly Byte bNumEndpoints;
+
+ ///<summary> USB-IF class code for this interface. See ClassCodeType.</summary>
+ public readonly ClassCodeType bInterfaceClass;
+
+ ///<summary> USB-IF subclass code for this interface, qualified by the bInterfaceClass value</summary>
+ public readonly Byte bInterfaceSubClass;
+
+ ///<summary> USB-IF protocol code for this interface, qualified by the bInterfaceClass and bInterfaceSubClass values</summary>
+ public readonly Byte bInterfaceProtocol;
+
+ ///<summary> Index of string descriptor describing this interface</summary>
+ public readonly Byte iInterface;
+
+ ///<summary> Array of endpoint descriptors. This length of this array is determined by the bNumEndpoints field.</summary>
+ private readonly IntPtr pEndpointDescriptors;
+
+ ///<summary> Extra descriptors. If libusb encounters unknown interface descriptors, it will store them here, should you wish to parse them.</summary>
+ private IntPtr pExtraBytes;
+
+ ///<summary> Length of the extra descriptors, in bytes.</summary>
+ public readonly int ExtraLength;
+
+ ///<summary> Extra descriptors. If libusb encounters unknown interface descriptors, it will store them here, should you wish to parse them.</summary>
+ public byte[] ExtraBytes
+ {
+ get
+ {
+ byte[] bytes = new byte[ExtraLength];
+ Marshal.Copy(pExtraBytes, bytes, 0, bytes.Length);
+ return bytes;
+ }
+ }
+
+ ///<summary> Array of endpoint descriptors. This length of this array is determined by the bNumEndpoints field.</summary>
+ public List<MonoUsbEndpointDescriptor> EndpointList
+ {
+ get
+ {
+ List<MonoUsbEndpointDescriptor> endpointList = new List<MonoUsbEndpointDescriptor>();
+ int iEndpoint;
+ for (iEndpoint = 0; iEndpoint < bNumEndpoints; iEndpoint++)
+ {
+ IntPtr pNextInterface = new IntPtr(pEndpointDescriptors.ToInt64() + (Marshal.SizeOf(typeof (MonoUsbEndpointDescriptor))*iEndpoint));
+ MonoUsbEndpointDescriptor monoUsbEndpoint = new MonoUsbEndpointDescriptor();
+ Marshal.PtrToStructure(pNextInterface, monoUsbEndpoint);
+ endpointList.Add(monoUsbEndpoint);
+ }
+
+ return endpointList;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Descriptors/MonoUsbConfigDescriptor.cs b/LibWinUsb/MonoLibUsb/Descriptors/MonoUsbConfigDescriptor.cs
new file mode 100644
index 00000000..f10297de
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Descriptors/MonoUsbConfigDescriptor.cs
@@ -0,0 +1,115 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+
+using LibUsbDotNet.Descriptors;
+using MonoLibUsb.Profile;
+
+namespace MonoLibUsb.Descriptors
+{
+ ///<summary>A structure representing the standard USB configuration descriptor.
+ ///This descriptor is documented in section 9.6.3 of the USB 2.0 specification.
+ ///All multiple-byte fields are represented in host-endian format.</summary>
+ /// <example><code source="..\MonoLibUsb\MonoUsb.ShowConfig\ShowConfig.cs" lang="cs"/></example>
+ [StructLayout(LayoutKind.Sequential, Pack = MonoUsbApi.LIBUSB_PACK)]
+ public class MonoUsbConfigDescriptor
+ {
+ internal MonoUsbConfigDescriptor()
+ {
+ }
+
+ /// <summary>
+ /// Create a new <see cref="MonoUsbConfigDescriptor"/> instance from a <see cref="MonoUsbConfigHandle"/>.
+ /// </summary>
+ /// <param name="configHandle">A config handle.</param>
+ public MonoUsbConfigDescriptor(MonoUsbConfigHandle configHandle)
+ {
+ Marshal.PtrToStructure(configHandle.DangerousGetHandle(), this);
+ }
+
+ ///<summary> Size of this descriptor (in bytes)</summary>
+ public readonly byte bLength;
+
+ ///<summary> Descriptor type. Will have value LIBUSB_DT_CONFIG in this context.</summary>
+ public readonly DescriptorType bDescriptorType;
+
+ ///<summary> Total length of data returned for this configuration</summary>
+ public readonly short wTotalLength;
+
+ ///<summary> Number of interfaces supported by this configuration</summary>
+ public readonly byte bNumInterfaces;
+
+ ///<summary> Identifier value for this configuration</summary>
+ public readonly byte bConfigurationValue;
+
+ ///<summary> Index of string descriptor describing this configuration</summary>
+ public readonly byte iConfiguration;
+
+ ///<summary> Configuration characteristics</summary>
+ public readonly byte bmAttributes;
+
+ ///<summary> Maximum power consumption of the USB device from this bus in this configuration when the device is fully opreation. Expressed in units of 2 mA.</summary>
+ public readonly byte MaxPower;
+
+ ///<summary> Array of interfaces supported by this configuration. The length of this array is determined by the bNumInterfaces field.</summary>
+ private readonly IntPtr pInterfaces;
+
+ ///<summary> Extra descriptors. If libusb encounters unknown configuration descriptors, it will store them here, should you wish to parse them.</summary>
+ private readonly IntPtr pExtraBytes;
+
+ ///<summary> Length of the extra descriptors, in bytes.</summary>
+ public readonly int ExtraLength;
+
+ ///<summary> Extra descriptors. If libusb encounters unknown configuration descriptors, it will store them here, should you wish to parse them.</summary>
+ public byte[] ExtraBytes
+ {
+ get
+ {
+ byte[] bytes = new byte[ExtraLength];
+ Marshal.Copy(pExtraBytes, bytes, 0, bytes.Length);
+ return bytes;
+ }
+ }
+
+ ///<summary> Array of interfaces supported by this configuration. The length of this array is determined by the bNumInterfaces field.</summary>
+ public List<MonoUsbInterface> InterfaceList
+ {
+ get
+ {
+ List<MonoUsbInterface> interfaceList = new List<MonoUsbInterface>();
+ int iInterface;
+ for (iInterface = 0; iInterface < bNumInterfaces; iInterface++)
+ {
+ IntPtr pNextInterface = new IntPtr(pInterfaces.ToInt64() + (Marshal.SizeOf(typeof (MonoUsbInterface))*iInterface));
+ MonoUsbInterface monoUsbInterface = new MonoUsbInterface();
+ Marshal.PtrToStructure(pNextInterface, monoUsbInterface);
+ interfaceList.Add(monoUsbInterface);
+ }
+
+ return interfaceList;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Descriptors/MonoUsbDeviceDescriptor.cs b/LibWinUsb/MonoLibUsb/Descriptors/MonoUsbDeviceDescriptor.cs
new file mode 100644
index 00000000..6330e685
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Descriptors/MonoUsbDeviceDescriptor.cs
@@ -0,0 +1,134 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Descriptors;
+using LibUsbDotNet.Main;
+
+namespace MonoLibUsb.Descriptors
+{
+ ///<summary>A structure representing the standard USB device descriptor.
+ ///This descriptor is documented in section 9.6.1 of the USB 2.0 specification.
+ ///All multiple-byte fields are represented in host-endian format.</summary>
+ [StructLayout(LayoutKind.Sequential, Pack = MonoUsbApi.LIBUSB_PACK)]
+ public class MonoUsbDeviceDescriptor
+ {
+ /// <summary>
+ /// Total size of this structure in bytes.
+ /// </summary>
+ public static readonly int Size = Marshal.SizeOf(typeof (MonoUsbDeviceDescriptor));
+
+ /// <summary>
+ /// Length of structure reported by the associated usb device.
+ /// </summary>
+ public byte Length;
+
+ /// <summary>
+ /// Type of structure reported by the associated usb device.
+ /// </summary>
+ public DescriptorType DescriptorType;
+
+ /// <summary>
+ /// USB Specification Number which device complies too.
+ /// </summary>
+ public readonly short BcdUsb;
+
+ /// <summary>
+ /// Class Code (Assigned by USB Org)
+ /// If equal to Zero, each interface specifies it’s own class code; If equal to 0xFF, the class code is vendor specified; Otherwise field is valid Class Code.
+ /// </summary>
+ public readonly ClassCodeType Class;
+
+ /// <summary>
+ /// Subclass Code (Assigned by USB Org)
+ /// </summary>
+ public readonly byte SubClass;
+
+ /// <summary>
+ /// Protocol Code (Assigned by USB Org)
+ /// </summary>
+ public readonly byte Protocol;
+
+ /// <summary>
+ /// Maximum Packet Size for Zero Endpoint. Valid Sizes are 8, 16, 32, 64
+ /// </summary>
+ public readonly byte MaxPacketSize0;
+
+ /// <summary>
+ /// Vendor ID (Assigned by USB Org)
+ /// </summary>
+ public readonly short VendorID;
+
+ /// <summary>
+ /// Product ID (Assigned by Manufacturer)
+ /// </summary>
+ public readonly short ProductID;
+
+ /// <summary>
+ /// Device Release Number
+ /// </summary>
+ public readonly short BcdDevice;
+
+ /// <summary>
+ /// Index of Manufacturer String Descriptor
+ /// </summary>
+ public readonly byte ManufacturerStringIndex;
+
+ /// <summary>
+ /// Index of Product String Descriptor
+ /// </summary>
+ public readonly byte ProductStringIndex;
+
+ /// <summary>
+ /// Index of Serial Number String Descriptor
+ /// </summary>
+ public readonly byte SerialStringIndex;
+
+ /// <summary>
+ /// Number of Possible Configurations
+ /// </summary>
+ public readonly byte ConfigurationCount;
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="MonoUsbDeviceDescriptor"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="MonoUsbDeviceDescriptor"/>.
+ ///</returns>
+ public override string ToString()
+ {
+ Object[] values = {
+ Length, DescriptorType, "0x" + BcdUsb.ToString("X4"), Class, SubClass, Protocol, MaxPacketSize0,
+ "0x" + VendorID.ToString("X4"), "0x" + ProductID.ToString("X4"), BcdDevice,
+ ManufacturerStringIndex, ProductStringIndex, SerialStringIndex, ConfigurationCount
+ };
+ string[] names = {
+ "Length", "DescriptorType", "BcdUsb", "Class", "SubClass", "Protocol", "MaxPacketSize0", "VendorID", "ProductID",
+ "BcdDevice",
+ "ManufacturerStringIndex", "ProductStringIndex", "SerialStringIndex", "ConfigurationCount"
+ };
+ return Helper.ToString("", names, ":", values, "\r\n");
+
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Descriptors/MonoUsbEndpointDescriptor.cs b/LibWinUsb/MonoLibUsb/Descriptors/MonoUsbEndpointDescriptor.cs
new file mode 100644
index 00000000..82f60523
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Descriptors/MonoUsbEndpointDescriptor.cs
@@ -0,0 +1,77 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Descriptors;
+
+namespace MonoLibUsb.Descriptors
+{
+ /// <summary>
+ /// A structure representing the standard USB endpoint descriptor. This
+ /// descriptor is documented in section 9.6.3 of the USB 2.0 specification.
+ /// All multiple-byte fields are represented in host-endian format.
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential, Pack = MonoUsbApi.LIBUSB_PACK)]
+ public class MonoUsbEndpointDescriptor
+ {
+ ///<summary> Size of this descriptor (in bytes)</summary>
+ public readonly Byte bLength;
+
+ ///<summary> Descriptor type. Will have value LIBUSB_DT_ENDPOINT in this context.</summary>
+ public readonly DescriptorType bDescriptorType;
+
+ ///<summary> The address of the endpoint described by this descriptor. Bits 0:3 are the endpoint number. Bits 4:6 are reserved. Bit 7 indicates direction, see \ref libusb_endpoint_direction.</summary>
+ public readonly Byte bEndpointAddress;
+
+ ///<summary> Attributes which apply to the endpoint when it is configured using the bConfigurationValue. Bits 0:1 determine the transfer type and correspond to \ref libusb_transfer_type. Bits 2:3 are only used for isochronous endpoints and correspond to \ref libusb_iso_sync_type. Bits 4:5 are also only used for isochronous endpoints and correspond to \ref libusb_iso_usage_type. Bits 6:7 are reserved.</summary>
+ public readonly Byte bmAttributes;
+
+ ///<summary> Maximum packet size this endpoint is capable of sending/receiving.</summary>
+ public readonly short wMaxPacketSize;
+
+ ///<summary> Interval for polling endpoint for data transfers.</summary>
+ public readonly Byte bInterval;
+
+ ///<summary> For audio devices only: the rate at which synchronization feedback is provided.</summary>
+ public readonly Byte bRefresh;
+
+ ///<summary> For audio devices only: the address if the synch endpoint</summary>
+ public readonly Byte bSynchAddress;
+
+ ///<summary> Extra descriptors. If libusb encounters unknown endpoint descriptors, it will store them here, should you wish to parse them.</summary>
+ private readonly IntPtr pExtraBytes;
+
+ ///<summary> Length of the extra descriptors, in bytes.</summary>
+ public readonly int ExtraLength;
+
+ ///<summary> Extra descriptors. If libusb encounters unknown endpoint descriptors, it will store them here, should you wish to parse them.</summary>
+ public byte[] ExtraBytes
+ {
+ get
+ {
+ byte[] bytes = new byte[ExtraLength];
+ Marshal.Copy(pExtraBytes, bytes, 0, bytes.Length);
+ return bytes;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Descriptors/MonoUsbInterface.cs b/LibWinUsb/MonoLibUsb/Descriptors/MonoUsbInterface.cs
new file mode 100644
index 00000000..d31e1b01
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Descriptors/MonoUsbInterface.cs
@@ -0,0 +1,59 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace MonoLibUsb.Descriptors
+{
+ ///<summary>A collection of alternate settings for a particular USB interface.</summary>
+ [StructLayout(LayoutKind.Sequential, Pack = MonoUsbApi.LIBUSB_PACK)]
+ public class MonoUsbInterface
+ {
+ ///<summary> Array of interface descriptors. The length of this array is determined by the num_altsetting field.</summary>
+ private IntPtr pAltSetting;
+
+ ///<summary> The number of alternate settings that belong to this interface</summary>
+ public readonly int num_altsetting;
+
+
+ ///<summary> Array of interface descriptors. The length of this array is determined by the num_altsetting field.</summary>
+ public List<MonoUsbAltInterfaceDescriptor> AltInterfaceList
+ {
+ get
+ {
+ List<MonoUsbAltInterfaceDescriptor> altInterfaceList = new List<MonoUsbAltInterfaceDescriptor>();
+ int iAltInterface;
+ for (iAltInterface = 0; iAltInterface < num_altsetting; iAltInterface++)
+ {
+ IntPtr pNextInterface = new IntPtr(pAltSetting.ToInt64() + (Marshal.SizeOf(typeof (MonoUsbAltInterfaceDescriptor))*iAltInterface));
+ MonoUsbAltInterfaceDescriptor monoUSBAltInterfaceDescriptor = new MonoUsbAltInterfaceDescriptor();
+ Marshal.PtrToStructure(pNextInterface, monoUSBAltInterfaceDescriptor);
+
+ altInterfaceList.Add(monoUSBAltInterfaceDescriptor);
+ }
+
+ return altInterfaceList;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/MonoLibUsbApi.cs b/LibWinUsb/MonoLibUsb/MonoLibUsbApi.cs
new file mode 100644
index 00000000..45b44f4d
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/MonoLibUsbApi.cs
@@ -0,0 +1,1470 @@
+#pragma warning disable 0649
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+using LibUsbDotNet.Descriptors;
+using LibUsbDotNet.Main;
+using MonoLibUsb.Descriptors;
+using MonoLibUsb.Profile;
+using MonoLibUsb.Transfer;
+using System.Threading;
+
+namespace MonoLibUsb
+{
+ /// <summary>
+ /// Libusb-1.0 low-level API library.
+ /// </summary>
+ public static class MonoUsbApi
+ {
+ internal const CallingConvention CC = 0;
+ internal const string LIBUSB_DLL = "libusb-1.0.dll";
+ internal const int LIBUSB_PACK = 0;
+
+ #region Private Members
+
+ private static readonly MonoUsbTransferDelegate DefaultAsyncDelegate = DefaultAsyncCB;
+ private static void DefaultAsyncCB(MonoUsbTransfer transfer)
+ {
+ ManualResetEvent completeEvent = GCHandle.FromIntPtr(transfer.PtrUserData).Target as ManualResetEvent;
+ completeEvent.Set();
+ }
+
+ #endregion
+ #region API LIBRARY FUNCTIONS - Initialization & Deinitialization
+
+
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_init")]
+ internal static extern int Init(ref IntPtr pContext);
+
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_exit")]
+ internal static extern void Exit(IntPtr pContext);
+
+
+ /// <summary>Set message verbosity.</summary>
+ /// <param name="sessionHandle">A valid <see cref="MonoUsbSessionHandle"/>.</param>
+ /// <param name="level">Debug level to set.</param>
+ /// <remarks>
+ /// <list type="bullet">
+ /// <item>Level 0: no messages ever printed by the library. (default)</item>
+ /// <item>Level 1: error messages are printed to stderr.</item>
+ /// <item>Level 2: warning and error messages are printed to stderr.</item>
+ /// <item>Level 3: informational messages are printed to stdout, warning and error messages are printed to stderr</item>
+ /// </list>
+ /// <para>The default level is 0, which means no messages are ever printed. If you choose to increase the message verbosity level, ensure that your application does not close the stdout/stderr file descriptors.</para>
+ /// <para>You are advised to set level 3. libusb is conservative with its message logging and most of the time, will only log messages that explain error conditions and other oddities. This will help you debug your software.</para>
+ /// <para>If the LIBUSB_DEBUG environment variable was set when libusb was initialized, this function does nothing: the message verbosity is fixed to the value in the environment variable.</para>
+ /// <para>If libusb was compiled without any message logging, this function does nothing: you'll never get any messages.</para>
+ /// <para>If libusb was compiled with verbose debug message logging, this function does nothing: you'll always get messages from all levels.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="lib"/></note>
+ /// </remarks>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_set_debug")]
+ public static extern void SetDebug([In]MonoUsbSessionHandle sessionHandle, int level);
+
+ #endregion
+
+ #region API LIBRARY FUNCTIONS - Device handling and enumeration
+
+ /// <summary>
+ /// Returns a list of USB devices currently attached to the system.
+ /// </summary>
+ /// <remarks>
+ /// <para>This is your entry point into finding a USB device to operate.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="dev"/></note>
+ /// </remarks>
+ /// <param name="sessionHandle">A valid <see cref="MonoUsbSessionHandle"/>.</param>
+ /// <param name="monoUSBProfileListHandle"> output location for a list of devices.</param>
+ /// <returns>The number of devices in the outputted list, or <see cref="MonoUsbError.ErrorNoMem"/> on memory allocation failure.</returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_get_device_list")]
+ public static extern int GetDeviceList([In]MonoUsbSessionHandle sessionHandle, [Out] out MonoUsbProfileListHandle monoUSBProfileListHandle);
+
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_free_device_list")]
+ internal static extern void FreeDeviceList(IntPtr pHandleList, int unrefDevices);
+
+ /// <summary>
+ /// Get the number of the bus that a device is connected to.
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="dev"/></note>
+ /// </remarks>
+ /// <returns>The bus number.</returns>
+ /// <param name="deviceProfileHandle">A device profile handle.</param>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_get_bus_number")]
+ public static extern byte GetBusNumber([In] MonoUsbProfileHandle deviceProfileHandle);
+
+
+ /// <summary>
+ /// Get the address of the device on the bus it is connected to.
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="dev"/></note>
+ /// </remarks>
+ /// <returns>The device address.</returns>
+ /// <param name="deviceProfileHandle">A device profile handle.</param>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_get_device_address")]
+ public static extern byte GetDeviceAddress([In] MonoUsbProfileHandle deviceProfileHandle);
+
+ /// <summary>
+ /// Convenience function to retrieve the wMaxPacketSize value for a particular endpoint in the active device configuration.
+ /// </summary>
+ /// <param name="deviceProfileHandle">A device profile handle.</param>
+ /// <param name="endpoint">Endpoint address to retrieve the max packet size for.</param>
+ /// <remarks>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="dev"/></note>
+ /// <para>This function was originally intended to be of assistance when setting up isochronous transfers, but a design mistake resulted in this function instead. It simply returns the <see cref="MonoUsbEndpointDescriptor.wMaxPacketSize"/> value without considering its contents. If you're dealing with isochronous transfers, you probably want <see cref="GetMaxIsoPacketSize"/> instead.</para>
+ /// </remarks>
+ /// <returns>The <see cref="MonoUsbEndpointDescriptor.wMaxPacketSize"/></returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_get_max_packet_size")]
+ public static extern int GetMaxPacketSize([In] MonoUsbProfileHandle deviceProfileHandle, byte endpoint);
+
+ /// <summary>
+ /// Calculate the maximum packet size which a specific endpoint is capable is sending or receiving in the duration of 1 microframe.
+ /// </summary>
+ /// <remarks>
+ /// <para>Only the active configuration is examined. The calculation is based on the wMaxPacketSize field in the endpoint descriptor as described in section 9.6.6 in the USB 2.0 specifications.</para>
+ /// <para>If acting on an isochronous or interrupt endpoint, this function will multiply the value found in bits 0:10 by the number of transactions per microframe (determined by bits 11:12). Otherwise, this function just returns the numeric value found in bits 0:10.</para>
+ /// <para>This function is useful for setting up isochronous transfers, for example you might pass the return value from this function to <see cref="MonoUsbTransfer.SetIsoPacketLengths">libusb_set_iso_packet_lengths</see> in order to set the length field of every isochronous packet in a transfer.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="dev"/></note>
+ /// </remarks>
+ /// <param name="deviceProfileHandle">A device profile handle.</param>
+ /// <param name="endpoint">Endpoint address to retrieve the max packet size for.</param>
+ /// <returns>The maximum packet size which can be sent/received on this endpoint.</returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_get_max_iso_packet_size")]
+ public static extern int GetMaxIsoPacketSize([In] MonoUsbProfileHandle deviceProfileHandle, byte endpoint);
+
+
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_ref_device")]
+ internal static extern IntPtr RefDevice(IntPtr pDeviceProfileHandle);
+
+
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_unref_device")]
+ internal static extern IntPtr UnrefDevice(IntPtr pDeviceProfileHandle);
+
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_open")]
+ internal static extern int Open([In] MonoUsbProfileHandle deviceProfileHandle, ref IntPtr deviceHandle);
+
+
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_open_device_with_vid_pid")]
+ private static extern IntPtr OpenDeviceWithVidPidInternal([In]MonoUsbSessionHandle sessionHandle, short vendorID, short productID);
+
+ /// <summary>
+ /// Convenience function for finding a device with a particular idVendor/idProduct combination.
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="dev"/></note>
+ /// </remarks>
+ /// <param name="sessionHandle">A valid <see cref="MonoUsbSessionHandle"/>.</param>
+ /// <param name="vendorID">The idVendor value to search for.</param>
+ /// <param name="productID">The idProduct value to search for.</param>
+ /// <returns>Null if the device was not opened or not found, otherwise an opened device handle.</returns>
+ public static MonoUsbDeviceHandle OpenDeviceWithVidPid([In]MonoUsbSessionHandle sessionHandle, short vendorID, short productID)
+ {
+ IntPtr pHandle = OpenDeviceWithVidPidInternal(sessionHandle, vendorID, productID);
+ if (pHandle == IntPtr.Zero) return null;
+ return new MonoUsbDeviceHandle(pHandle);
+ }
+
+
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_close")]
+ internal static extern void Close(IntPtr deviceHandle);
+
+
+ /// <summary>
+ /// Get a <see cref="MonoUsbProfileHandle"/> for a <see cref="MonoUsbDeviceHandle"/>.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// This function differs from the Libusb-1.0 C API in that when the new <see cref="MonoUsbProfileHandle"/> is returned, the device profile reference count
+ /// is incremented ensuring the profile will remain valid as long as it is in-use.
+ /// </para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="dev"/></note>
+ /// </remarks>
+ /// <param name="devicehandle">A device handle.</param>
+ /// <returns>The underlying profile handle.</returns>
+ public static MonoUsbProfileHandle GetDevice(MonoUsbDeviceHandle devicehandle) { return new MonoUsbProfileHandle(GetDeviceInternal(devicehandle)); }
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_get_device")]
+ private static extern IntPtr GetDeviceInternal([In] MonoUsbDeviceHandle devicehandle);
+
+ /// <summary>
+ /// Determine the <see cref="MonoUsbConfigDescriptor.bConfigurationValue"/> of the currently active configuration.
+ /// </summary>
+ /// <remarks>
+ /// <para>You could formulate your own control request to obtain this information, but this function has the advantage that it may be able to retrieve the information from operating system caches (no I/O involved).</para>
+ /// <para>If the OS does not cache this information, then this function will block while a control transfer is submitted to retrieve the information.</para>
+ /// <para>This function will return a value of 0 in the <paramref name="configuration"/> parameter if the device is in unconfigured state.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="dev"/></note>
+ /// </remarks>
+ /// <param name="deviceHandle">A device handle.</param>
+ /// <param name="configuration">Output location for the <see cref="MonoUsbConfigDescriptor.bConfigurationValue"/> of the active configuration. (only valid for return code 0)</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>0 on success</item>
+ /// <item><see cref="MonoUsbError.ErrorNoDevice"/> if the device has been disconnected</item>
+ /// <item>another <see cref="MonoUsbError"/> code on other failure</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_get_configuration")]
+ public static extern int GetConfiguration([In] MonoUsbDeviceHandle deviceHandle, ref int configuration);
+
+ /// <summary>
+ /// Set the active configuration for a device.
+ /// </summary>
+ /// <remarks>
+ /// <para>The operating system may or may not have already set an active configuration on the device. It is up to your application to ensure the correct configuration is selected before you attempt to claim interfaces and perform other operations.</para>
+ /// <para>If you call this function on a device already configured with the selected configuration, then this function will act as a lightweight device reset: it will issue a SET_CONFIGURATION request using the current configuration, causing most USB-related device state to be reset (altsetting reset to zero, endpoint halts cleared, toggles reset).</para>
+ /// <para>You cannot change/reset configuration if your application has claimed interfaces - you should free them with <see cref="ReleaseInterface"/> first. You cannot change/reset configuration if other applications or drivers have claimed interfaces.</para>
+ /// <para>A configuration value of -1 will put the device in unconfigured state. The USB specifications state that a configuration value of 0 does this, however buggy devices exist which actually have a configuration 0.</para>
+ /// <para>You should always use this function rather than formulating your own SET_CONFIGURATION control request. This is because the underlying operating system needs to know when such changes happen.</para>
+ /// <para>This is a blocking function.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="dev"/></note>
+ /// </remarks>
+ /// <param name="deviceHandle">A device handle.</param>
+ /// <param name="configuration">The <see cref="MonoUsbConfigDescriptor.bConfigurationValue"/> of the configuration you wish to activate, or -1 if you wish to put the device in unconfigured state </param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>0 on success</item>
+ /// <item><see cref="MonoUsbError.ErrorNotFound"/> if the requested configuration does not exist</item>
+ /// <item><see cref="MonoUsbError.ErrorBusy"/> if interfaces are currently claimed</item>
+ /// <item><see cref="MonoUsbError.ErrorNoDevice"/> if the device has been disconnected</item>
+ /// <item>another <see cref="MonoUsbError"/> code on other failure</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_set_configuration")]
+ public static extern int SetConfiguration([In] MonoUsbDeviceHandle deviceHandle, int configuration);
+
+ /// <summary>
+ /// Claim an interface on a given device handle.
+ /// </summary>
+ /// <remarks>
+ /// <para>You must claim the interface you wish to use before you can perform I/O on any of its endpoints.</para>
+ /// <para>It is legal to attempt to claim an already-claimed interface, in which case libusb just returns 0 without doing anything.</para>
+ /// <para>Claiming of interfaces is a purely logical operation; it does not cause any requests to be sent over the bus. Interface claiming is used to instruct the underlying operating system that your application wishes to take ownership of the interface.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="dev"/></note>
+ /// </remarks>
+ /// <param name="deviceHandle">A device handle.</param>
+ /// <param name="interfaceNumber">the <see cref="MonoUsbAltInterfaceDescriptor.bInterfaceNumber"/> of the interface you wish to claim.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>0 on success</item>
+ /// <item><see cref="MonoUsbError.ErrorNotFound"/> if the requested interface does not exist</item>
+ /// <item><see cref="MonoUsbError.ErrorBusy"/> if another program or driver has claimed the interface </item>
+ /// <item><see cref="MonoUsbError.ErrorNoDevice"/> if the device has been disconnected</item>
+ /// <item>another <see cref="MonoUsbError"/> code on other failure</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_claim_interface")]
+ public static extern int ClaimInterface([In] MonoUsbDeviceHandle deviceHandle, int interfaceNumber);
+
+ /// <summary>
+ /// Release an interface previously claimed with <see cref="ClaimInterface"/>.
+ /// </summary>
+ /// <remarks>
+ /// <para>You should release all claimed interfaces before closing a device handle.</para>
+ /// <para>This is a blocking function. A SET_INTERFACE control request will be sent to the device, resetting interface state to the first alternate setting.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="dev"/></note>
+ /// </remarks>
+ /// <param name="deviceHandle">A device handle.</param>
+ /// <param name="interfaceNumber">the <see cref="MonoUsbAltInterfaceDescriptor.bInterfaceNumber"/> of the interface you wish to claim.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>0 on success</item>
+ /// <item><see cref="MonoUsbError.ErrorNotFound"/> if the interface was not claimed</item>
+ /// <item><see cref="MonoUsbError.ErrorNoDevice"/> if the device has been disconnected</item>
+ /// <item>another <see cref="MonoUsbError"/> code on other failure</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_release_interface")]
+ public static extern int ReleaseInterface([In] MonoUsbDeviceHandle deviceHandle, int interfaceNumber);
+
+ /// <summary>
+ /// Activate an alternate setting for an interface.
+ /// </summary>
+ /// <remarks>
+ /// <para>The interface must have been previously claimed with <see cref="ClaimInterface"/>.</para>
+ /// <para>You should always use this function rather than formulating your own SET_INTERFACE control request. This is because the underlying operating system needs to know when such changes happen.</para>
+ /// <para>This is a blocking function.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="dev"/></note>
+ /// </remarks>
+ /// <param name="deviceHandle">A device handle.</param>
+ /// <param name="interfaceNumber">The <see cref="MonoUsbAltInterfaceDescriptor.bInterfaceNumber"/> of the previously-claimed interface.</param>
+ /// <param name="alternateSetting">The <see cref="MonoUsbAltInterfaceDescriptor.bAlternateSetting"/> of the alternate setting to activate.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>0 on success</item>
+ /// <item><see cref="MonoUsbError.ErrorNotFound"/> if the interface was not claimed, or the requested alternate setting does not exist</item>
+ /// <item><see cref="MonoUsbError.ErrorNoDevice"/> if the device has been disconnected</item>
+ /// <item>another <see cref="MonoUsbError"/> code on other failure</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_set_interface_alt_setting")]
+ public static extern int SetInterfaceAltSetting([In] MonoUsbDeviceHandle deviceHandle, int interfaceNumber, int alternateSetting);
+
+ /// <summary>
+ /// Clear the halt/stall condition for an endpoint.
+ /// </summary>
+ /// <remarks>
+ /// <para>Endpoints with halt status are unable to receive or transmit data until the halt condition is stalled.</para>
+ /// <para>You should cancel all pending transfers before attempting to clear the halt condition.</para>
+ /// <para>This is a blocking function.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="dev"/></note>
+ /// </remarks>
+ /// <param name="deviceHandle">A device handle.</param>
+ /// <param name="endpoint">The endpoint to clear halt status.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>0 on success</item>
+ /// <item><see cref="MonoUsbError.ErrorNotFound"/> if the endpoint does not exist</item>
+ /// <item><see cref="MonoUsbError.ErrorNoDevice"/> if the device has been disconnected</item>
+ /// <item>another <see cref="MonoUsbError"/> code on other failure</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_clear_halt")]
+ public static extern int ClearHalt([In] MonoUsbDeviceHandle deviceHandle, byte endpoint);
+
+ /// <summary>
+ /// Perform a USB port reset to reinitialize a device.
+ /// </summary>
+ /// <remarks>
+ /// <para>The system will attempt to restore the previous configuration and alternate settings after the reset has completed.</para>
+ /// <para>If the reset fails, the descriptors change, or the previous state cannot be restored, the device will appear to be disconnected and reconnected. This means that the device handle is no longer valid (you should close it) and rediscover the device. A return code of <see cref="MonoUsbError.ErrorNotFound"/> indicates when this is the case.</para>
+ /// <para>This is a blocking function which usually incurs a noticeable delay.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="dev"/></note>
+ /// </remarks>
+ /// <param name="deviceHandle">A device handle.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>0 on success</item>
+ /// <item><see cref="MonoUsbError.ErrorNotFound"/> if re-enumeration is required, or if the device has been disconnected</item>
+ /// <item>another <see cref="MonoUsbError"/> code on other failure</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_reset_device")]
+ public static extern int ResetDevice([In] MonoUsbDeviceHandle deviceHandle);
+
+ /// <summary>
+ /// Determine if a kernel driver is active on an interface.
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="dev"/></note>
+ /// </remarks>
+ /// <param name="deviceHandle">A device handle.</param>
+ /// <param name="interfaceNumber">The interface to check.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>0 if no kernel driver is active.</item>
+ /// <item>1 if a kernel driver is active.</item>
+ /// <item><see cref="MonoUsbError.ErrorNoDevice"/> if the device has been disconnected.</item>
+ /// <item>Another <see cref="MonoUsbError"/> code on other failure.</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_kernel_driver_active")]
+ public static extern int KernelDriverActive([In] MonoUsbDeviceHandle deviceHandle, int interfaceNumber);
+
+ /// <summary>
+ /// Detach a kernel driver from an interface.
+ /// </summary>
+ /// <remarks>
+ /// <para>If successful, you will then be able to claim the interface and perform I/O.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="dev"/></note>
+ /// </remarks>
+ /// <param name="deviceHandle">A device handle.</param>
+ /// <param name="interfaceNumber">The interface to detach the driver from.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>0 on success.</item>
+ /// <item><see cref="MonoUsbError.ErrorNotFound"/> if no kernel driver was active.</item>
+ /// <item><see cref="MonoUsbError.ErrorInvalidParam"/> if the interface does not exist.</item>
+ /// <item><see cref="MonoUsbError.ErrorNoDevice"/> if the device has been disconnected </item>
+ /// <item>Another <see cref="MonoUsbError"/> code on other failure.</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_detach_kernel_driver")]
+ public static extern int DetachKernelDriver([In] MonoUsbDeviceHandle deviceHandle, int interfaceNumber);
+
+ /// <summary>
+ /// Re-attach an interface's kernel driver, which was previously detached using <see cref="DetachKernelDriver"/>.
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="dev"/></note>
+ /// </remarks>
+ /// <param name="deviceHandle">A device handle.</param>
+ /// <param name="interfaceNumber">The interface to attach the driver from.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>0 on success.</item>
+ /// <item><see cref="MonoUsbError.ErrorNotFound"/> if no kernel driver was active.</item>
+ /// <item><see cref="MonoUsbError.ErrorInvalidParam"/> if the interface does not exist.</item>
+ /// <item><see cref="MonoUsbError.ErrorNoDevice"/> if the device has been disconnected.</item>
+ /// <item><see cref="MonoUsbError.ErrorBusy"/> if the driver cannot be attached because the interface is claimed by a program or driver.</item>
+ /// <item>Another <see cref="MonoUsbError"/> code on other failure.</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_attach_kernel_driver")]
+ public static extern int AttachKernelDriver([In] MonoUsbDeviceHandle deviceHandle, int interfaceNumber);
+
+ #endregion
+
+ #region API LIBRARY FUNCTIONS - USB descriptors
+
+ /// <summary>
+ /// Gets the standard device descriptor.
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip">This is a non-blocking function which does not involve any requests being sent to the device.</note>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="desc"/></note>
+ /// </remarks>
+ /// <param name="deviceProfileHandle">A device profile handle.</param>
+ /// <param name="deviceDescriptor">The <see cref="MonoUsbDeviceDescriptor"/> clas that will hold the data.</param>
+ /// <returns>0 on success or a <see cref="MonoUsbError"/> code on failure.</returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_get_device_descriptor")]
+ public static extern int GetDeviceDescriptor([In] MonoUsbProfileHandle deviceProfileHandle,
+ [Out] MonoUsbDeviceDescriptor deviceDescriptor);
+
+ /// <summary>
+ /// Get the USB configuration descriptor for the currently active configuration.
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip">This is a non-blocking function which does not involve any requests being sent to the device.</note>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="desc"/></note>
+ /// </remarks>
+ /// <param name="deviceProfileHandle">A device profile handle.</param>
+ /// <param name="configHandle">A config handle.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>0 on success</item>
+ /// <item><see cref="MonoUsbError.ErrorNotFound"/> if the device is in unconfigured state </item>
+ /// <item>another <see cref="MonoUsbError"/> code on error</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_get_active_config_descriptor")]
+ public static extern int GetActiveConfigDescriptor([In] MonoUsbProfileHandle deviceProfileHandle,
+ [Out] out MonoUsbConfigHandle configHandle);
+
+
+ /// <summary>
+ /// Get a USB configuration descriptor based on its index.
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip">This is a non-blocking function which does not involve any requests being sent to the device.</note>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="desc"/></note>
+ /// </remarks>
+ /// <param name="deviceProfileHandle">A device profile handle.</param>
+ /// <param name="configIndex">The index of the configuration you wish to retrieve.</param>
+ /// <param name="configHandle">A config handle.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>0 on success</item>
+ /// <item><see cref="MonoUsbError.ErrorNotFound"/> if the device is in unconfigured state </item>
+ /// <item>another <see cref="MonoUsbError"/> code on error</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_get_config_descriptor")]
+ public static extern int GetConfigDescriptor([In] MonoUsbProfileHandle deviceProfileHandle,
+ byte configIndex,
+ [Out] out MonoUsbConfigHandle configHandle);
+
+ /// <summary>
+ /// Get a USB configuration descriptor with a specific bConfigurationValue.
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip">This is a non-blocking function which does not involve any requests being sent to the device.</note>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="desc"/></note>
+ /// </remarks>
+ /// <param name="deviceProfileHandle">A device profile handle.</param>
+ /// <param name="bConfigurationValue">The bConfigurationValue of the configuration you wish to retrieve.</param>
+ /// <param name="configHandle">A config handle.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>0 on success</item>
+ /// <item><see cref="MonoUsbError.ErrorNotFound"/> if the device is in unconfigured state </item>
+ /// <item>another <see cref="MonoUsbError"/> code on error</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_get_config_descriptor_by_value")]
+ public static extern int GetConfigDescriptorByValue([In] MonoUsbProfileHandle deviceProfileHandle,
+ byte bConfigurationValue,
+ [Out] out MonoUsbConfigHandle configHandle);
+
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_free_config_descriptor")]
+ internal static extern void FreeConfigDescriptor(IntPtr pConfigDescriptor);
+
+ /// <summary>
+ /// Retrieve a descriptor from the default control pipe.
+ /// </summary>
+ /// <remarks>
+ /// <para>This is a convenience function which formulates the appropriate control message to retrieve the descriptor.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="desc"/></note>
+ /// </remarks>
+ /// <param name="deviceHandle">Retrieve a descriptor from the default control pipe.</param>
+ /// <param name="descType">The descriptor type, <see cref="DescriptorType"/></param>
+ /// <param name="descIndex">The index of the descriptor to retrieve.</param>
+ /// <param name="pData">Output buffer for descriptor.</param>
+ /// <param name="length">Size of data buffer.</param>
+ /// <returns>Number of bytes returned in data, or a <see cref="MonoUsbError"/> code on failure.</returns>
+ public static int GetDescriptor(MonoUsbDeviceHandle deviceHandle, byte descType, byte descIndex, IntPtr pData, int length)
+ {
+ return ControlTransfer(deviceHandle,
+ (byte) UsbEndpointDirection.EndpointIn,
+ (byte) UsbStandardRequest.GetDescriptor,
+ (short) ((descType << 8) | descIndex),
+ 0,
+ pData,
+ (short) length,
+ 1000);
+ }
+
+ /// <summary>
+ /// Retrieve a descriptor from the default control pipe.
+ /// </summary>
+ /// <remarks>
+ /// <para>This is a convenience function which formulates the appropriate control message to retrieve the descriptor.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="desc"/></note>
+ /// </remarks>
+ /// <param name="deviceHandle">Retrieve a descriptor from the default control pipe.</param>
+ /// <param name="descType">The descriptor type, <see cref="DescriptorType"/></param>
+ /// <param name="descIndex">The index of the descriptor to retrieve.</param>
+ /// <param name="data">Output buffer for descriptor. This object is pinned using <see cref="PinnedHandle"/>.</param>
+ /// <param name="length">Size of data buffer.</param>
+ /// <returns>Number of bytes returned in data, or <see cref="MonoUsbError"/> code on failure.</returns>
+ public static int GetDescriptor(MonoUsbDeviceHandle deviceHandle, byte descType, byte descIndex, object data, int length)
+ {
+ PinnedHandle p = new PinnedHandle(data);
+ return GetDescriptor(deviceHandle, descType, descIndex, p.Handle, length);
+ }
+
+ #endregion
+
+ #region API LIBRARY FUNCTIONS - Asynchronous device I/O
+
+
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_alloc_transfer")]
+ internal static extern IntPtr AllocTransfer(int isoPackets);
+
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_free_transfer")]
+ internal static extern void FreeTransfer(IntPtr pTransfer);
+
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_submit_transfer")]
+ internal static extern int SubmitTransfer(IntPtr pTransfer);
+
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_cancel_transfer")]
+ internal static extern int CancelTransfer(IntPtr pTransfer);
+
+ #endregion
+
+ #region API LIBRARY FUNCTIONS - Polling and timing
+
+ /// <summary>
+ /// Attempt to acquire the event handling lock.
+ /// </summary>
+ /// <remarks>
+ /// <para>This lock is used to ensure that only one thread is monitoring libusb event sources at any one time.</para>
+ /// <para>You only need to use this lock if you are developing an application which calls poll() or select() on libusb's file descriptors directly. If you stick to libusb's event handling loop functions (e.g. <see cref="HandleEvents(MonoUsbSessionHandle)">libusb_handle_events</see>) then you do not need to be concerned with this locking.</para>
+ /// <para>While holding this lock, you are trusted to actually be handling events. If you are no longer handling events, you must call <see cref="UnlockEvents">libusb_unlock_events</see> as soon as possible.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="poll"/></note>
+ /// </remarks>
+ /// <param name="sessionHandle">A valid <see cref="MonoUsbSessionHandle"/>.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>0 if the lock was obtained successfully.</item>
+ /// <item>1 if the lock was not obtained. (i.e. another thread holds the lock)</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_try_lock_events")]
+ public static extern int TryLockEvents([In]MonoUsbSessionHandle sessionHandle);
+
+ /// <summary>
+ /// Acquire the event handling lock, blocking until successful acquisition if it is contended.
+ /// </summary>
+ /// <remarks>
+ /// <para>This lock is used to ensure that only one thread is monitoring libusb event sources at any one time.</para>
+ /// <para>You only need to use this lock if you are developing an application which calls poll() or select() on libusb's file descriptors directly. If you stick to libusb's event handling loop functions (e.g. <see cref="HandleEvents(MonoUsbSessionHandle)">libusb_handle_events</see>) then you do not need to be concerned with this locking.</para>
+ /// <para>While holding this lock, you are trusted to actually be handling events. If you are no longer handling events, you must call <see cref="UnlockEvents">libusb_unlock_events</see> as soon as possible.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="poll"/></note>
+ /// </remarks>
+ /// <param name="sessionHandle">A valid <see cref="MonoUsbSessionHandle"/>.</param>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_lock_events")]
+ public static extern void LockEvents([In]MonoUsbSessionHandle sessionHandle);
+
+ /// <summary>
+ /// Release the lock previously acquired with <see cref="TryLockEvents">libusb_try_lock_events</see> or <see cref="LockEvents">libusb_lock_events</see>.
+ /// </summary>
+ /// <remarks>
+ /// <para>Releasing this lock will wake up any threads blocked on <see cref="WaitForEvent">libusb_wait_for_event</see>.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="poll"/></note>
+ /// </remarks>
+ /// <param name="sessionHandle">A valid <see cref="MonoUsbSessionHandle"/>.</param>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_unlock_events")]
+ public static extern void UnlockEvents([In]MonoUsbSessionHandle sessionHandle);
+
+ /// <summary>
+ /// Determine if it is still OK for this thread to be doing event handling.
+ /// </summary>
+ /// <remarks>
+ /// <para>Sometimes, libusb needs to temporarily pause all event handlers, and this is the function you should use before polling file descriptors to see if this is the case.</para>
+ /// <para>If this function instructs your thread to give up the events lock, you should just continue the usual logic that is documented in Multi-threaded applications and asynchronous I/O. On the next iteration, your thread will fail to obtain the events lock, and will hence become an event waiter.</para>
+ /// <para>This function should be called while the events lock is held: you don't need to worry about the results of this function if your thread is not the current event handler.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="poll"/></note>
+ /// </remarks>
+ /// <param name="sessionHandle">A valid <see cref="MonoUsbSessionHandle"/>.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>1 if event handling can start or continue.</item>
+ /// <item>0 if this thread must give up the events lock.</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_event_handling_ok")]
+ public static extern int EventHandlingOk([In]MonoUsbSessionHandle sessionHandle);
+
+ /// <summary>
+ /// Determine if an active thread is handling events (i.e. if anyone is holding the event handling lock).
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="poll"/></note>
+ /// </remarks>
+ /// <param name="sessionHandle">A valid <see cref="MonoUsbSessionHandle"/>.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>1 if a thread is handling events.</item>
+ /// <item>0 if there are no threads currently handling events.</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_event_handler_active")]
+ public static extern int EventHandlerActive([In]MonoUsbSessionHandle sessionHandle);
+
+ /// <summary>
+ /// Acquire the event waiters lock.
+ /// </summary>
+ /// <remarks>
+ /// <para>This lock is designed to be obtained under the situation where you want to be aware when events are completed, but some other thread is event handling so calling <see cref="HandleEvents(MonoUsbSessionHandle)">libusb_handle_events</see> is not allowed.</para>
+ /// <para>You then obtain this lock, re-check that another thread is still handling events, then call <see cref="WaitForEvent">libusb_wait_for_event</see>.</para>
+ /// <para>You only need to use this lock if you are developing an application which calls poll() or select() on libusb's file descriptors directly, and may potentially be handling events from 2 threads simultaenously. If you stick to libusb's event handling loop functions (e.g. <see cref="HandleEvents(MonoUsbSessionHandle)">libusb_handle_events</see>) then you do not need to be concerned with this locking.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="poll"/></note>
+ /// </remarks>
+ /// <param name="sessionHandle">A valid <see cref="MonoUsbSessionHandle"/>.</param>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_lock_event_waiters")]
+ public static extern void LockEventWaiters([In]MonoUsbSessionHandle sessionHandle);
+
+ /// <summary>
+ /// Release the event waiters lock.
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="poll"/></note>
+ /// </remarks>
+ /// <param name="sessionHandle">A valid <see cref="MonoUsbSessionHandle"/>.</param>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_unlock_event_waiters")]
+ public static extern void UnlockEventWaiters([In]MonoUsbSessionHandle sessionHandle);
+
+ /// <summary>
+ /// Wait for another thread to signal completion of an event.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// This function will block until any of the following conditions are met:
+ /// <list type="numbered">
+ /// <item>The timeout expires.</item>
+ /// <item>A transfer completes.</item>
+ /// <item>A thread releases the event handling lock through <see cref="UnlockEvents">libusb_unlock_events</see>.</item>
+ /// </list>
+ /// </para>
+ /// <para>Condition 1 is obvious. Condition 2 unblocks your thread after the callback for the transfer has completed. Condition 3 is important because it means that the thread that was previously handling events is no longer doing so, so if any events are to complete, another thread needs to step up and start event handling.</para>
+ /// <para>This function releases the event waiters lock before putting your thread to sleep, and reacquires the lock as it is being woken up.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="poll"/></note>
+ /// </remarks>
+ /// <param name="sessionHandle">A valid <see cref="MonoUsbSessionHandle"/>.</param>
+ /// <param name="timeval">Maximum timeout for this blocking function.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>0 after a transfer completes or another thread stops event handling.</item>
+ /// <item>1 if the timeout expired.</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_wait_for_event")]
+ public static extern int WaitForEvent([In]MonoUsbSessionHandle sessionHandle, ref UnixNativeTimeval timeval);
+
+ /// <summary>
+ /// Handle any pending events.
+ /// </summary>
+ /// <remarks>
+ /// <para>libusb determines "pending events" by checking if any timeouts have expired and by checking the set of file descriptors for activity.</para>
+ /// <para>If a non-zero timeval is passed and no events are currently pending, this function will block waiting for events to handle up until the specified timeout. If an event arrives or a signal is raised, this function will return early.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="poll"/></note>
+ /// </remarks>
+ /// <param name="sessionHandle">A valid <see cref="MonoUsbSessionHandle"/>.</param>
+ /// <param name="tv">The maximum time to block waiting for events, or zero for non-blocking mode</param>
+ /// <returns>0 on success, or a <see cref="MonoUsbError"/> code on other failure.</returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_handle_events_timeout")]
+ public static extern int HandleEventsTimeout([In]MonoUsbSessionHandle sessionHandle, ref UnixNativeTimeval tv);
+
+ /// <summary>
+ /// Handle any pending events in blocking mode with a sensible timeout.
+ /// </summary>
+ /// <remarks>
+ /// <para>This timeout is currently hardcoded at 2 seconds but we may change this if we decide other values are more sensible. For finer control over whether this function is blocking or non-blocking, or the maximum timeout, use <see cref="HandleEventsTimeout">libusb_handle_events_timeout</see> instead.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="poll"/></note>
+ /// </remarks>
+ /// <param name="sessionHandle">A valid <see cref="MonoUsbSessionHandle"/>.</param>
+ /// <returns>0 on success, or a <see cref="MonoUsbError"/> code on other failure.</returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_handle_events")]
+ public static extern int HandleEvents([In]MonoUsbSessionHandle sessionHandle);
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_handle_events")]
+ private static extern int HandleEvents(IntPtr pSessionHandle);
+
+ /// <summary>
+ /// Handle any pending events by polling file descriptors, without checking if any other threads are already doing so.
+ /// </summary>
+ /// <remarks>
+ /// <para>Must be called with the event lock held, see <see cref="LockEvents">libusb_lock_events</see>.</para>
+ /// <para>This function is designed to be called under the situation where you have taken the event lock and are calling poll()/select() directly on libusb's file descriptors (as opposed to using <see cref="HandleEvents(MonoUsbSessionHandle)">libusb_handle_events</see> or similar). You detect events on libusb's descriptors, so you then call this function with a zero timeout value (while still holding the event lock).</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="poll"/></note>
+ /// </remarks>
+ /// <param name="sessionHandle">A valid <see cref="MonoUsbSessionHandle"/>.</param>
+ /// <param name="tv">The maximum time to block waiting for events, or zero for non-blocking mode</param>
+ /// <returns>0 on success, or a <see cref="MonoUsbError"/> code on other failure.</returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_handle_events_locked")]
+ public static extern int HandleEventsLocked([In]MonoUsbSessionHandle sessionHandle, ref UnixNativeTimeval tv);
+
+ /// <summary>
+ /// Determines whether your application must apply special timing considerations when monitoring libusb's file descriptors.
+ /// </summary>
+ /// <remarks>
+ /// <para>This function is only useful for applications which retrieve and poll libusb's file descriptors in their own main loop (The more advanced option).</para>
+ /// <para>Ordinarily, libusb's event handler needs to be called into at specific moments in time (in addition to times when there is activity on the file descriptor set). The usual approach is to use <see cref="GetNextTimeout">libusb_get_next_timeout</see> to learn about when the next timeout occurs, and to adjust your poll()/select() timeout accordingly so that you can make a call into the library at that time.</para>
+ /// <para>Some platforms supported by libusb do not come with this baggage - any events relevant to timing will be represented by activity on the file descriptor set, and <see cref="GetNextTimeout">libusb_get_next_timeout</see> will always return 0. This function allows you to detect whether you are running on such a platform.</para>
+ /// <para>Since v1.0.5.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="poll"/></note>
+ /// </remarks>
+ /// <param name="sessionHandle">A valid <see cref="MonoUsbSessionHandle"/>.</param>
+ /// <returns>0 if you must call into libusb at times determined by <see cref="GetNextTimeout">libusb_get_next_timeout</see>, or 1 if all timeout events are handled internally or through regular activity on the file descriptors.</returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_pollfds_handle_timeouts")]
+ public static extern int PollfdsHandleTimeouts([In]MonoUsbSessionHandle sessionHandle);
+
+ /// <summary>
+ /// Determine the next internal timeout that libusb needs to handle.
+ /// </summary>
+ /// <remarks>
+ /// <para>You only need to use this function if you are calling poll() or select() or similar on libusb's file descriptors yourself - you do not need to use it if you are calling <see cref="HandleEvents(MonoUsbSessionHandle)">libusb_handle_events</see> or a variant directly.</para>
+ /// <para>You should call this function in your main loop in order to determine how long to wait for select() or poll() to return results. libusb needs to be called into at this timeout, so you should use it as an upper bound on your select() or poll() call.</para>
+ /// <para>When the timeout has expired, call into <see cref="HandleEventsTimeout">libusb_handle_events_timeout</see> (perhaps in non-blocking mode) so that libusb can handle the timeout.</para>
+ /// <para>This function may return 1 (success) and an all-zero timeval. If this is the case, it indicates that libusb has a timeout that has already expired so you should call <see cref="HandleEventsTimeout">libusb_handle_events_timeout</see> or similar immediately. A return code of 0 indicates that there are no pending timeouts.</para>
+ /// <para>On some platforms, this function will always returns 0 (no pending timeouts). See Notes on time-based events.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="poll"/></note>
+ /// </remarks>
+ /// <param name="sessionHandle">A valid <see cref="MonoUsbSessionHandle"/>.</param>
+ /// <param name="tv">The maximum time to block waiting for events, or zero for non-blocking mode</param>
+ /// <returns>0 if there are no pending timeouts, 1 if a timeout was returned, or <see cref="MonoUsbError.ErrorOther"/> on failure.</returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_get_next_timeout")]
+ public static extern int GetNextTimeout([In]MonoUsbSessionHandle sessionHandle, ref UnixNativeTimeval tv);
+
+ /// <summary>
+ /// Register notification functions for file descriptor additions/removals.
+ /// </summary>
+ /// <remarks>
+ /// <para>To remove notifiers, pass NULL values for the function pointers.</para>
+ /// <para>Note that file descriptors may have been added even before you register these notifiers (e.g. when a new <see cref="MonoUsbSessionHandle"/> is created).</para>
+ /// <para>Additionally, note that the removal notifier may be called during <see cref="Exit"/> (e.g. when it is closing file descriptors that were opened and added to the poll set when a new <see cref="MonoUsbSessionHandle"/> was created). If you don't want this, remove the notifiers immediately before calling <see cref="SafeHandle.Close">MonoUsbSessionHandle.Close()</see>.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="poll"/></note>
+ /// </remarks>
+ /// <param name="sessionHandle">A valid <see cref="MonoUsbSessionHandle"/>.</param>
+ /// <param name="addedDelegate">Function delegate for addition notifications.</param>
+ /// <param name="removedDelegate">Function delegate for removal notifications.</param>
+ /// <param name="pUserData">User data to be passed back to callbacks (useful for passing sessionHandle information).</param>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_set_pollfd_notifiers")]
+ public static extern void SetPollfdNotifiers([In]MonoUsbSessionHandle sessionHandle,
+ PollfdAddedDelegate addedDelegate,
+ PollfdRemovedDelegate removedDelegate,
+ IntPtr pUserData);
+
+
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_get_pollfds")]
+ private static extern IntPtr GetPollfdsInternal([In]MonoUsbSessionHandle sessionHandle);
+
+ /// <summary>
+ /// Retrieve a list of file descriptors that should be polled by your main loop as libusb event sources.
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="poll"/></note>
+ /// </remarks>
+ /// <param name="sessionHandle">A valid <see cref="MonoUsbSessionHandle"/>.</param>
+ /// <returns>A list of PollfdItem structures, or null on error.</returns>
+ public static List<PollfdItem> GetPollfds(MonoUsbSessionHandle sessionHandle)
+ {
+ List<PollfdItem> rtnList = new List<PollfdItem>();
+ IntPtr pList = GetPollfdsInternal(sessionHandle);
+ if (pList == IntPtr.Zero) return null;
+
+ IntPtr pNext = pList;
+ IntPtr pPollfd;
+ while ((((pNext != IntPtr.Zero))) && (pPollfd = Marshal.ReadIntPtr(pNext)) != IntPtr.Zero)
+ {
+ PollfdItem pollfdItem = new PollfdItem(pPollfd);
+ rtnList.Add(pollfdItem);
+ pNext = new IntPtr(pNext.ToInt64() + IntPtr.Size);
+ }
+ Marshal.FreeHGlobal(pList);
+
+ return rtnList;
+ }
+
+ #endregion
+
+ #region API LIBRARY FUNCTIONS - Synchronous device I/O
+
+ /// <summary>
+ /// Perform a USB control transfer.
+ /// </summary>
+ /// <remarks>
+ /// <para>The direction of the transfer is inferred from the bmRequestType field of the setup packet.</para>
+ /// <para>The wValue, wIndex and wLength fields values should be given in host-endian byte order.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="syncio"/></note>
+ /// </remarks>
+ /// <param name="deviceHandle">A handle for the device to communicate with.</param>
+ /// <param name="requestType">The request type field for the setup packet.</param>
+ /// <param name="request">The request field for the setup packet.</param>
+ /// <param name="value">The value field for the setup packet</param>
+ /// <param name="index">The index field for the setup packet.</param>
+ /// <param name="pData">A suitably-sized data buffer for either input or output (depending on direction bits within bmRequestType).</param>
+ /// <param name="dataLength">The length field for the setup packet. The data buffer should be at least this size.</param>
+ /// <param name="timeout">timeout (in milliseconds) that this function should wait before giving up due to no response being received. For an unlimited timeout, use value 0.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>on success, the number of bytes actually transferred</item>
+ /// <item><see cref="MonoUsbError.ErrorTimeout"/> if the transfer timed out</item>
+ /// <item><see cref="MonoUsbError.ErrorPipe"/> if the control request was not supported by the device.</item>
+ /// <item><see cref="MonoUsbError.ErrorNoDevice"/> if the device has been disconnected</item>
+ /// <item>another <see cref="MonoUsbError"/> code on other failures</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_control_transfer")]
+ public static extern int ControlTransfer([In] MonoUsbDeviceHandle deviceHandle,
+ byte requestType,
+ byte request,
+ short value,
+ short index,
+ IntPtr pData,
+ short dataLength,
+ int timeout);
+
+
+ /// <summary>
+ /// Perform a USB control transfer for multi-threaded applications using the <see cref="MonoUsbEventHandler"/> class.
+ /// </summary>
+ /// <remarks>
+ /// <para>The direction of the transfer is inferred from the bmRequestType field of the setup packet.</para>
+ /// <para>The wValue, wIndex and wLength fields values should be given in host-endian byte order.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="syncio"/></note>
+ /// </remarks>
+ /// <param name="deviceHandle">A handle for the device to communicate with.</param>
+ /// <param name="requestType">The request type field for the setup packet.</param>
+ /// <param name="request">The request field for the setup packet.</param>
+ /// <param name="value">The value field for the setup packet</param>
+ /// <param name="index">The index field for the setup packet.</param>
+ /// <param name="pData">A suitably-sized data buffer for either input or output (depending on direction bits within bmRequestType).</param>
+ /// <param name="dataLength">The length field for the setup packet. The data buffer should be at least this size.</param>
+ /// <param name="timeout">timeout (in milliseconds) that this function should wait before giving up due to no response being received. For an unlimited timeout, use value 0.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>on success, the number of bytes actually transferred</item>
+ /// <item><see cref="MonoUsbError.ErrorTimeout"/> if the transfer timed out</item>
+ /// <item><see cref="MonoUsbError.ErrorPipe"/> if the control request was not supported by the device.</item>
+ /// <item><see cref="MonoUsbError.ErrorNoDevice"/> if the device has been disconnected</item>
+ /// <item>another <see cref="MonoUsbError"/> code on other failures</item>
+ /// </list>
+ /// </returns>
+ public static int ControlTransferAsync([In] MonoUsbDeviceHandle deviceHandle,
+ byte requestType,
+ byte request,
+ short value,
+ short index,
+ IntPtr pData,
+ short dataLength,
+ int timeout)
+ {
+ MonoUsbControlSetupHandle setupHandle = new MonoUsbControlSetupHandle(requestType, request, value, index, pData, dataLength);
+ MonoUsbTransfer transfer = new MonoUsbTransfer(0);
+ ManualResetEvent completeEvent = new ManualResetEvent(false);
+ GCHandle gcCompleteEvent = GCHandle.Alloc(completeEvent);
+
+ transfer.FillControl(deviceHandle, setupHandle, DefaultAsyncDelegate, GCHandle.ToIntPtr(gcCompleteEvent), timeout);
+
+ int r = (int)transfer.Submit();
+ if (r < 0)
+ {
+ transfer.Free();
+ gcCompleteEvent.Free();
+ return r;
+ }
+ IntPtr pSessionHandle;
+ MonoUsbSessionHandle sessionHandle = MonoUsbEventHandler.SessionHandle;
+ if (sessionHandle == null)
+ pSessionHandle = IntPtr.Zero;
+ else
+ pSessionHandle = sessionHandle.DangerousGetHandle();
+
+ if (MonoUsbEventHandler.IsStopped)
+ {
+ while (!completeEvent.WaitOne(0, false))
+ {
+ r = HandleEvents(pSessionHandle);
+ if (r < 0)
+ {
+ if (r == (int)MonoUsbError.ErrorInterrupted)
+ continue;
+ transfer.Cancel();
+ while (!completeEvent.WaitOne(0, false))
+ if (HandleEvents(pSessionHandle) < 0)
+ break;
+ transfer.Free();
+ gcCompleteEvent.Free();
+ return r;
+ }
+ }
+ }
+ else
+ {
+ completeEvent.WaitOne(Timeout.Infinite, UsbConstants.EXIT_CONTEXT);
+ }
+
+ if (transfer.Status == MonoUsbTansferStatus.TransferCompleted)
+ {
+ r = transfer.ActualLength;
+ if (r > 0)
+ {
+ byte[] ctrlDataBytes = setupHandle.ControlSetup.GetData(r);
+ Marshal.Copy(ctrlDataBytes, 0, pData, Math.Min(ctrlDataBytes.Length, dataLength));
+ }
+
+ }
+ else
+ r = (int)MonoLibUsbErrorFromTransferStatus(transfer.Status);
+
+ transfer.Free();
+ gcCompleteEvent.Free();
+ return r;
+ }
+
+ /// <summary>
+ /// Perform a USB control transfer.
+ /// </summary>
+ /// <remarks>
+ /// <para>The direction of the transfer is inferred from the bmRequestType field of the setup packet.</para>
+ /// <para>The wValue, wIndex and wLength fields values should be given in host-endian byte order.</para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="syncio"/></note>
+ /// </remarks>
+ /// <param name="deviceHandle">A handle for the device to communicate with.</param>
+ /// <param name="requestType">The request type field for the setup packet.</param>
+ /// <param name="request">The request field for the setup packet.</param>
+ /// <param name="value">The value field for the setup packet</param>
+ /// <param name="index">The index field for the setup packet.</param>
+ /// <param name="data">
+ /// <para>A suitably-sized data buffer for either input or output (depending on direction bits within bmRequestType).</para>
+ /// This value can be:
+ /// <list type="bullet">
+ /// <item>An <see cref="Array"/> of bytes or other <a href="http://msdn.microsoft.com/en-us/library/75dwhxf7.aspx">blittable</a> types.</item>
+ /// <item>An already allocated, pinned <see cref="GCHandle"/>. In this case <see cref="GCHandle.AddrOfPinnedObject"/> is used for the buffer address.</item>
+ /// <item>An <see cref="IntPtr"/>.</item>
+ /// </list>
+ /// </param>
+ /// <param name="dataLength">The length field for the setup packet. The data buffer should be at least this size.</param>
+ /// <param name="timeout">timeout (in milliseconds) that this function should wait before giving up due to no response being received. For an unlimited timeout, use value 0.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>on success, the number of bytes actually transferred</item>
+ /// <item><see cref="MonoUsbError.ErrorTimeout"/> if the transfer timed out</item>
+ /// <item><see cref="MonoUsbError.ErrorPipe"/> if the control request was not supported by the device.</item>
+ /// <item><see cref="MonoUsbError.ErrorNoDevice"/> if the device has been disconnected</item>
+ /// <item>another <see cref="MonoUsbError"/> code on other failures</item>
+ /// </list>
+ /// </returns>
+ public static int ControlTransfer([In] MonoUsbDeviceHandle deviceHandle,
+ byte requestType,
+ byte request,
+ short value,
+ short index,
+ object data,
+ short dataLength,
+ int timeout)
+ {
+ PinnedHandle p = new PinnedHandle(data);
+ int ret = ControlTransfer(deviceHandle, requestType, request, value, index, p.Handle, dataLength, timeout);
+ p.Dispose();
+ return ret;
+ }
+
+#if NOT_USED
+ /// <summary>
+ /// Perform a USB control transfer.
+ /// </summary>
+ /// <remarks>
+ /// The direction of the transfer is inferred from the bmRequestType field of the setup packet.
+ /// The wValue, wIndex and wLength fields values should be given in host-endian byte order.
+ /// </remarks>
+ /// <param name="deviceHandle">A handle for the device to communicate with.</param>
+ /// <param name="setupPacket">The setup packet.</param>
+ /// <param name="pData">A suitably-sized data buffer for either input or output (depending on direction bits within bmRequestType).</param>
+ /// <param name="dataLength">The length field for the setup packet. The data buffer should be at least this size.</param>
+ /// <param name="timeout">timeout (in millseconds) that this function should wait before giving up due to no response being received. For an unlimited timeout, use value 0.</param>
+ /// <returns>on success, the number of bytes actually transferred, Other wise a <see cref="MonoUsbError"/>.</returns>
+ public static int libusb_control_transfer(MonoUsbDeviceHandle deviceHandle,
+ ref libusb_control_setup setupPacket,
+ IntPtr pData,
+ short dataLength,
+ int timeout)
+ {
+ return libusb_control_transfer(deviceHandle,
+ setupPacket.bmRequestType,
+ setupPacket.bRequest,
+ setupPacket.wValue,
+ setupPacket.wIndex,
+ pData,
+ dataLength,
+ timeout);
+ }
+#endif
+
+ /// <summary>
+ /// Perform a USB bulk transfer.
+ /// </summary>
+ /// <remarks>
+ /// <para>The direction of the transfer is inferred from the direction bits of the endpoint address.</para>
+ /// <para>
+ /// For bulk reads, the length field indicates the maximum length of data you are expecting to receive.
+ /// If less data arrives than expected, this function will return that data, so be sure to check the
+ /// transferred output parameter.
+ /// </para>
+ /// <para>
+ /// You should also check the transferred parameter for bulk writes. Not all of the data may have been
+ /// written. Also check transferred when dealing with a timeout error code. libusb may have to split
+ /// your transfer into a number of chunks to satisfy underlying O/S requirements, meaning that the
+ /// timeout may expire after the first few chunks have completed. libusb is careful not to lose any
+ /// data that may have been transferred; do not assume that timeout conditions indicate a complete lack
+ /// of I/O.
+ /// </para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="syncio"/></note>
+ /// </remarks>
+ /// <param name="deviceHandle">A handle for the device to communicate with.</param>
+ /// <param name="endpoint">The address of a valid endpoint to communicate with.</param>
+ /// <param name="pData">
+ /// A suitably-sized data buffer for either input or output (depending on endpoint).</param>
+ /// <param name="length">For bulk writes, the number of bytes from data to be sent. for bulk reads, the maximum number of bytes to receive into the data buffer.</param>
+ /// <param name="actualLength">Output location for the number of bytes actually transferred.</param>
+ /// <param name="timeout">Timeout (in milliseconds) that this function should wait before giving up due to no response being received. For an unlimited timeout, use value 0.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>0 on success (and populates <paramref name="actualLength"/>)</item>
+ /// <item><see cref="MonoUsbError.ErrorTimeout"/> if the transfer timed out</item>
+ /// <item><see cref="MonoUsbError.ErrorPipe"/> if the endpoint halted</item>
+ /// <item><see cref="MonoUsbError.ErrorOverflow"/>if the device offered more data, see <a href="http://libusb.sourceforge.net/api-1.0/packetoverflow.html">Packets and overflows</a></item>
+ /// <item><see cref="MonoUsbError.ErrorNoDevice"/> if the device has been disconnected</item>
+ /// <item>another <see cref="MonoUsbError"/> code on other failures</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_bulk_transfer")]
+ public static extern int BulkTransfer([In] MonoUsbDeviceHandle deviceHandle,
+ byte endpoint,
+ IntPtr pData,
+ int length,
+ out int actualLength,
+ int timeout);
+
+ /// <summary>
+ /// Perform a USB bulk transfer.
+ /// </summary>
+ /// <remarks>
+ /// <para>The direction of the transfer is inferred from the direction bits of the endpoint address.</para>
+ /// <para>
+ /// For bulk reads, the length field indicates the maximum length of data you are expecting to receive.
+ /// If less data arrives than expected, this function will return that data, so be sure to check the
+ /// transferred output parameter.
+ /// </para>
+ /// <para>
+ /// You should also check the transferred parameter for bulk writes. Not all of the data may have been
+ /// written. Also check transferred when dealing with a timeout error code. libusb may have to split
+ /// your transfer into a number of chunks to satisfy underlying O/S requirements, meaning that the
+ /// timeout may expire after the first few chunks have completed. libusb is careful not to lose any
+ /// data that may have been transferred; do not assume that timeout conditions indicate a complete lack
+ /// of I/O.
+ /// </para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="syncio"/></note>
+ /// </remarks>
+ /// <param name="deviceHandle">A handle for the device to communicate with.</param>
+ /// <param name="endpoint">The address of a valid endpoint to communicate with.</param>
+ /// <param name="data">
+ /// <para>A suitably-sized data buffer for either input or output (depending on endpoint).</para>
+ /// This value can be:
+ /// <list type="bullet">
+ /// <item>An <see cref="Array"/> of bytes or other <a href="http://msdn.microsoft.com/en-us/library/75dwhxf7.aspx">blittable</a> types.</item>
+ /// <item>An already allocated, pinned <see cref="GCHandle"/>. In this case <see cref="GCHandle.AddrOfPinnedObject"/> is used for the buffer address.</item>
+ /// <item>An <see cref="IntPtr"/>.</item>
+ /// </list>
+ /// </param>
+ /// <param name="length">For bulk writes, the number of bytes from data to be sent. for bulk reads, the maximum number of bytes to receive into the data buffer.</param>
+ /// <param name="actualLength">Output location for the number of bytes actually transferred.</param>
+ /// <param name="timeout">Timeout (in milliseconds) that this function should wait before giving up due to no response being received. For an unlimited timeout, use value 0.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>0 on success (and populates <paramref name="actualLength"/>)</item>
+ /// <item><see cref="MonoUsbError.ErrorTimeout"/> if the transfer timed out</item>
+ /// <item><see cref="MonoUsbError.ErrorPipe"/> if the endpoint halted</item>
+ /// <item><see cref="MonoUsbError.ErrorOverflow"/>if the device offered more data, see <a href="http://libusb.sourceforge.net/api-1.0/packetoverflow.html">Packets and overflows</a></item>
+ /// <item><see cref="MonoUsbError.ErrorNoDevice"/> if the device has been disconnected</item>
+ /// <item>another <see cref="MonoUsbError"/> code on other failures</item>
+ /// </list>
+ /// </returns>
+ public static int BulkTransfer([In] MonoUsbDeviceHandle deviceHandle,
+ byte endpoint,
+ object data,
+ int length,
+ out int actualLength,
+ int timeout)
+ {
+ PinnedHandle p = new PinnedHandle(data);
+ int ret = BulkTransfer(deviceHandle, endpoint, p.Handle, length, out actualLength, timeout);
+ p.Dispose();
+ return ret;
+ }
+
+ /// <summary>
+ /// Perform a USB interrupt transfer.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The direction of the transfer is inferred from the direction bits of the endpoint address.
+ /// </para><para>
+ /// For interrupt reads, the length field indicates the maximum length of data you are expecting to receive.
+ /// If less data arrives than expected, this function will return that data, so be sure to check the
+ /// transferred output parameter.
+ /// </para><para>
+ /// You should also check the transferred parameter for interrupt writes. Not all of the data may have been
+ /// written. Also check transferred when dealing with a timeout error code. libusb may have to split
+ /// your transfer into a number of chunks to satisfy underlying O/S requirements, meaning that the
+ /// timeout may expire after the first few chunks have completed. libusb is careful not to lose any
+ /// data that may have been transferred; do not assume that timeout conditions indicate a complete lack
+ /// of I/O.
+ /// </para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="syncio"/></note>
+ /// </remarks>
+ /// <param name="deviceHandle">A handle for the device to communicate with.</param>
+ /// <param name="endpoint">The address of a valid endpoint to communicate with.</param>
+ /// <param name="pData">A suitably-sized data buffer for either input or output (depending on endpoint).</param>
+ /// <param name="length">For interrupt writes, the number of bytes from data to be sent. for interrupt reads, the maximum number of bytes to receive into the data buffer.</param>
+ /// <param name="actualLength">Output location for the number of bytes actually transferred.</param>
+ /// <param name="timeout">Timeout (in milliseconds) that this function should wait before giving up due to no response being received. For an unlimited timeout, use value 0.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>0 on success (and populates <paramref name="actualLength"/>)</item>
+ /// <item><see cref="MonoUsbError.ErrorTimeout"/> if the transfer timed out</item>
+ /// <item><see cref="MonoUsbError.ErrorPipe"/> if the endpoint halted</item>
+ /// <item><see cref="MonoUsbError.ErrorOverflow"/>if the device offered more data, see <a href="http://libusb.sourceforge.net/api-1.0/packetoverflow.html">Packets and overflows</a></item>
+ /// <item><see cref="MonoUsbError.ErrorNoDevice"/> if the device has been disconnected</item>
+ /// <item>another <see cref="MonoUsbError"/> code on other failures</item>
+ /// </list>
+ /// </returns>
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_interrupt_transfer")]
+ public static extern int InterruptTransfer([In] MonoUsbDeviceHandle deviceHandle,
+ byte endpoint,
+ IntPtr pData,
+ int length,
+ out int actualLength,
+ int timeout);
+
+
+ /// <summary>
+ /// Perform a USB interrupt transfer.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The direction of the transfer is inferred from the direction bits of the endpoint address.
+ /// </para><para>
+ /// For interrupt reads, the length field indicates the maximum length of data you are expecting to receive.
+ /// If less data arrives than expected, this function will return that data, so be sure to check the
+ /// transferred output parameter.
+ /// </para><para>
+ /// You should also check the transferred parameter for interrupt writes. Not all of the data may have been
+ /// written. Also check transferred when dealing with a timeout error code. libusb may have to split
+ /// your transfer into a number of chunks to satisfy underlying O/S requirements, meaning that the
+ /// timeout may expire after the first few chunks have completed. libusb is careful not to lose any
+ /// data that may have been transferred; do not assume that timeout conditions indicate a complete lack
+ /// of I/O.
+ /// </para>
+ /// <note type="tip" title="Libusb-1.0 API:"><seelibusb10 group="syncio"/></note>
+ /// </remarks>
+ /// <param name="deviceHandle">A handle for the device to communicate with.</param>
+ /// <param name="endpoint">The address of a valid endpoint to communicate with.</param>
+ /// <param name="data">
+ /// <para>A suitably-sized data buffer for either input or output (depending on endpoint).</para>
+ /// This value can be:
+ /// <list type="bullet">
+ /// <item>An <see cref="Array"/> of bytes or other <a href="http://msdn.microsoft.com/en-us/library/75dwhxf7.aspx">blittable</a> types.</item>
+ /// <item>An already allocated, pinned <see cref="GCHandle"/>. In this case <see cref="GCHandle.AddrOfPinnedObject"/> is used for the buffer address.</item>
+ /// <item>An <see cref="IntPtr"/>.</item>
+ /// </list>
+ /// </param>
+ /// <param name="length">For interrupt writes, the number of bytes from data to be sent. for interrupt reads, the maximum number of bytes to receive into the data buffer.</param>
+ /// <param name="actualLength">Output location for the number of bytes actually transferred.</param>
+ /// <param name="timeout">Timeout (in milliseconds) that this function should wait before giving up due to no response being received. For an unlimited timeout, use value 0.</param>
+ /// <returns>
+ /// <list type="bullet">
+ /// <item>0 on success (and populates <paramref name="actualLength"/>)</item>
+ /// <item><see cref="MonoUsbError.ErrorTimeout"/> if the transfer timed out</item>
+ /// <item><see cref="MonoUsbError.ErrorPipe"/> if the endpoint halted</item>
+ /// <item><see cref="MonoUsbError.ErrorOverflow"/>if the device offered more data, see <a href="http://libusb.sourceforge.net/api-1.0/packetoverflow.html">Packets and overflows</a></item>
+ /// <item><see cref="MonoUsbError.ErrorNoDevice"/> if the device has been disconnected</item>
+ /// <item>another <see cref="MonoUsbError"/> code on other failures</item>
+ /// </list>
+ /// </returns>
+ public static int InterruptTransfer([In] MonoUsbDeviceHandle deviceHandle,
+ byte endpoint,
+ object data,
+ int length,
+ out int actualLength,
+ int timeout)
+ {
+ PinnedHandle p = new PinnedHandle(data);
+ int ret = InterruptTransfer(deviceHandle, endpoint, p.Handle, length, out actualLength, timeout);
+ p.Dispose();
+ return ret;
+ }
+
+ #endregion
+
+ #region API LIBRARY FUNCTIONS - Misc
+
+ [DllImport(LIBUSB_DLL, CallingConvention = CC, SetLastError = false, EntryPoint = "libusb_strerror")]
+ private static extern IntPtr StrError(int errcode);
+
+ /// <summary>
+ /// Get a string describing a <see cref="MonoUsbError"/>.
+ /// </summary>
+ /// <param name="errcode">The <see cref="MonoUsbError"/> code to retrieve a description for.</param>
+ /// <returns>A string describing the <see cref="MonoUsbError"/> code.</returns>
+ public static string StrError(MonoUsbError errcode)
+ {
+ switch (errcode)
+ {
+ case MonoUsbError.Success:
+ return "Success";
+ case MonoUsbError.ErrorIO:
+ return "Input/output error";
+ case MonoUsbError.ErrorInvalidParam:
+ return "Invalid parameter";
+ case MonoUsbError.ErrorAccess:
+ return "Access denied (insufficient permissions)";
+ case MonoUsbError.ErrorNoDevice:
+ return "No such device (it may have been disconnected)";
+ case MonoUsbError.ErrorBusy:
+ return "Resource busy";
+ case MonoUsbError.ErrorTimeout:
+ return "Operation timed out";
+ case MonoUsbError.ErrorOverflow:
+ return "Overflow";
+ case MonoUsbError.ErrorPipe:
+ return "Pipe error or endpoint halted";
+ case MonoUsbError.ErrorInterrupted:
+ return "System call interrupted (perhaps due to signal)";
+ case MonoUsbError.ErrorNoMem:
+ return "Insufficient memory";
+ case MonoUsbError.ErrorIOCancelled:
+ return "Transfer was canceled";
+ case MonoUsbError.ErrorNotSupported:
+ return "Operation not supported or unimplemented on this platform";
+ default:
+ return "Unknown error:" + errcode;
+ }
+ }
+
+ #endregion
+
+ #region API LIBRARY - Windows Testing Only
+#if WINDOWS_TESTING
+ internal static internal_windows_device_priv GetWindowsPriv(MonoUsbProfileHandle profileHandle)
+ {
+ internal_windows_device_priv priv = new internal_windows_device_priv();
+ IntPtr pPriv = new IntPtr(profileHandle.DangerousGetHandle().ToInt64() + Marshal.SizeOf(typeof(internal_libusb_device)));
+ Marshal.PtrToStructure(pPriv, priv);
+ return priv;
+ }
+
+ [StructLayout(LayoutKind.Sequential,Pack=0)]
+ internal class internal_libusb_device
+ {
+ public readonly IntPtr mutexLock;
+ public readonly int refCnt; /*QL - changed short to int*/
+
+ public readonly IntPtr ctx;
+
+ public readonly byte busNumber;
+ public readonly byte deviceAddress;
+ public readonly byte numConfigurations;
+
+ public readonly internal_list_head list = new internal_list_head();
+ public readonly uint sessionData;
+ //public readonly IntPtr temp;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 0)]
+ internal class internal_list_head
+ {
+ public readonly IntPtr prev;
+ public readonly IntPtr next;
+ }
+
+ internal struct internal_usb_interface
+ {
+ public readonly IntPtr path; // each interface needs a Windows device interface path,
+ public readonly IntPtr apib; // an API backend (multiple drivers support),
+ public readonly byte nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS)
+ public readonly IntPtr endpoint; /*QL - added */
+ public readonly bool restricted_functionality; /*QL - added */
+ }
+
+[StructLayout(LayoutKind.Sequential, Pack = 0)]
+ internal class internal_windows_device_priv
+ {
+ public readonly IntPtr parent_dev; // access to parent is required for usermode ops
+ public readonly uint connection_index; // also required for some usermode ops
+ public readonly IntPtr path; // path used by Windows to reference the USB node
+
+ public readonly IntPtr apib;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
+ public readonly internal_usb_interface[] usb_interfaces=new internal_usb_interface[32];
+
+ public readonly byte composite_api_flags; // HID and composite devices require additional data
+ public readonly IntPtr hid;
+ public readonly byte active_config;
+
+ public readonly IntPtr dev_descriptor; /*QL - added*/
+ public readonly IntPtr config_descriptor; /*QL - added*/
+ //USB_DEVICE_DESCRIPTOR dev_descriptor;
+ //char **config_descriptor; // list of pointers to the cached config descriptors
+ }
+#endif
+ #endregion
+
+ /// <summary>
+ /// Converts a <see cref="MonoUsbTansferStatus"/> enum to a <see cref="MonoUsbError"/> enum.
+ /// </summary>
+ /// <param name="status">the <see cref="MonoUsbTansferStatus"/> to convert.</param>
+ /// <returns>A <see cref="MonoUsbError"/> that represents <paramref name="status"/>.</returns>
+ public static MonoUsbError MonoLibUsbErrorFromTransferStatus(MonoUsbTansferStatus status)
+ {
+ switch (status)
+ {
+ case MonoUsbTansferStatus.TransferCompleted:
+ return MonoUsbError.Success;
+ case MonoUsbTansferStatus.TransferError:
+ return MonoUsbError.ErrorPipe;
+ case MonoUsbTansferStatus.TransferTimedOut:
+ return MonoUsbError.ErrorTimeout;
+ case MonoUsbTansferStatus.TransferCancelled:
+ return MonoUsbError.ErrorIOCancelled;
+ case MonoUsbTansferStatus.TransferStall:
+ return MonoUsbError.ErrorPipe;
+ case MonoUsbTansferStatus.TransferNoDevice:
+ return MonoUsbError.ErrorNoDevice;
+ case MonoUsbTansferStatus.TransferOverflow:
+ return MonoUsbError.ErrorOverflow;
+ default:
+ return MonoUsbError.ErrorOther;
+ }
+ }
+
+ /// <summary>
+ /// Calls <see cref="MonoUsbEventHandler.Init()"/> and <see cref="MonoUsbEventHandler.Start"/> if <see cref="MonoUsbEventHandler.IsStopped"/> = true.
+ /// </summary>
+ internal static void InitAndStart()
+ {
+ if (!MonoUsbEventHandler.IsStopped) return;
+ MonoUsbEventHandler.Init();
+ MonoUsbEventHandler.Start();
+ }
+
+ /// <summary>
+ /// Calls <see cref="MonoUsbEventHandler.Stop"/> and <see cref="MonoUsbEventHandler.Exit"/>.
+ /// </summary>
+ internal static void StopAndExit()
+ {
+#if LIBUSBDOTNET
+ if (LibUsbDotNet.LudnMonoLibUsb.MonoUsbDevice.mMonoUSBProfileList != null) LibUsbDotNet.LudnMonoLibUsb.MonoUsbDevice.mMonoUSBProfileList.Close();
+ LibUsbDotNet.LudnMonoLibUsb.MonoUsbDevice.mMonoUSBProfileList = null;
+#endif
+ MonoUsbEventHandler.Stop(true);
+ MonoUsbEventHandler.Exit();
+ }
+
+
+#if LIBUSBDOTNET
+ internal static ErrorCode ErrorCodeFromLibUsbError(int ret, out string description)
+ {
+ description = string.Empty;
+ if (ret == 0) return ErrorCode.Success;
+
+ switch ((MonoUsbError) ret)
+ {
+ case MonoUsbError.Success:
+ description += "Success";
+ return ErrorCode.Success;
+ case MonoUsbError.ErrorIO:
+ description += "Input/output error";
+ return ErrorCode.IoSyncFailed;
+ case MonoUsbError.ErrorInvalidParam:
+ description += "Invalid parameter";
+ return ErrorCode.InvalidParam;
+ case MonoUsbError.ErrorAccess:
+ description += "Access denied (insufficient permissions)";
+ return ErrorCode.AccessDenied;
+ case MonoUsbError.ErrorNoDevice:
+ description += "No such device (it may have been disconnected)";
+ return ErrorCode.DeviceNotFound;
+ case MonoUsbError.ErrorBusy:
+ description += "Resource busy";
+ return ErrorCode.ResourceBusy;
+ case MonoUsbError.ErrorTimeout:
+ description += "Operation timed out";
+ return ErrorCode.IoTimedOut;
+ case MonoUsbError.ErrorOverflow:
+ description += "Overflow";
+ return ErrorCode.Overflow;
+ case MonoUsbError.ErrorPipe:
+ description += "Pipe error or endpoint halted";
+ return ErrorCode.PipeError;
+ case MonoUsbError.ErrorInterrupted:
+ description += "System call interrupted (perhaps due to signal)";
+ return ErrorCode.Interrupted;
+ case MonoUsbError.ErrorNoMem:
+ description += "Insufficient memory";
+ return ErrorCode.InsufficientMemory;
+ case MonoUsbError.ErrorIOCancelled:
+ description += "Transfer was canceled";
+ return ErrorCode.IoCancelled;
+ case MonoUsbError.ErrorNotSupported:
+ description += "Operation not supported or unimplemented on this platform";
+ return ErrorCode.NotSupported;
+ default:
+ description += "Unknown error:" + ret;
+ return ErrorCode.UnknownError;
+ }
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/MonoUsbDevice.cs b/LibWinUsb/MonoLibUsb/MonoUsbDevice.cs
new file mode 100644
index 00000000..8e929925
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/MonoUsbDevice.cs
@@ -0,0 +1,522 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Descriptors;
+using LibUsbDotNet.Info;
+using LibUsbDotNet.Main;
+using MonoLibUsb;
+using MonoLibUsb.Descriptors;
+using MonoLibUsb.Profile;
+
+namespace LibUsbDotNet.LudnMonoLibUsb
+{
+ /// <summary>This is the LibUsbDotNet Libusb-1.0 implementation of a <see cref="UsbDevice"/>.
+ /// </summary>
+ /// <remarks>
+ /// <para>This class is used for perform I/O and other operations on Libusb-1.0 devices using with LibUsbDotNet.</para>
+ /// <para>This class is not a part of the low-level MonLibUsb API. This is <see cref="UsbDevice"/> class LibUsbDotNet uses to implement the low-level MonoLibUsb API.</para>
+ /// </remarks>
+ public class MonoUsbDevice : UsbDevice, IUsbDevice
+ {
+ internal static readonly object OLockDeviceList = new object();
+ internal static MonoUsbProfileList mMonoUSBProfileList;
+ private readonly MonoUsbProfile mMonoUSBProfile;
+
+ private int mClaimedInteface;
+
+ internal MonoUsbDevice(ref MonoUsbProfile monoUSBProfile)
+ : base(null, null)
+ {
+ mMonoUSBProfile = monoUSBProfile;
+ mCachedDeviceDescriptor = new UsbDeviceDescriptor(monoUSBProfile.DeviceDescriptor);
+ }
+
+ internal static MonoUsbProfileList ProfileList
+ {
+ get
+ {
+ lock (OLockDeviceList)
+ {
+ MonoUsbApi.InitAndStart();
+ if (mMonoUSBProfileList == null)
+ {
+ mMonoUSBProfileList = new MonoUsbProfileList();
+ }
+ return mMonoUSBProfileList;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets a <see cref="MonoUsbDevice"/> list of Libusb-1.0 devices.
+ /// </summary>
+ /// <remarks>
+ /// <para>Using the <see cref="MonoUsbDeviceList"/> property will request a device list directly from the <a href="http://www.libusb.org/">Libusb-1.0</a> driver.</para>
+ /// <para><a href="http://www.libusb.org/">Libusb-1.0</a> is compatible with several platforms including windows.</para>
+ /// <para>You can force LibUsbDotNet to always use <a href="http://www.libusb.org/">Libusb-1.0</a> with the <see cref="UsbDevice.ForceLibUsbWinBack"/> member.</para>
+ /// <seealso cref="UsbDevice.AllDevices"/>
+ /// <seealso cref="UsbDevice.AllLibUsbDevices"/>
+ /// </remarks>
+ public static List<MonoUsbDevice> MonoUsbDeviceList
+ {
+ get
+ {
+ lock (OLockDeviceList)
+ {
+ MonoUsbApi.InitAndStart();
+ if (mMonoUSBProfileList == null)
+ {
+ mMonoUSBProfileList = new MonoUsbProfileList();
+ }
+ int ret = (int) mMonoUSBProfileList.Refresh(MonoUsbEventHandler.SessionHandle);
+ if (ret < 0) return null;
+ List<MonoUsbDevice> rtnList = new List<MonoUsbDevice>();
+ for (int iProfile = 0; iProfile < mMonoUSBProfileList.Count; iProfile++)
+ {
+ MonoUsbProfile monoUSBProfile = mMonoUSBProfileList[iProfile];
+ if (monoUSBProfile.DeviceDescriptor.BcdUsb == 0) continue;
+ MonoUsbDevice newDevice = new MonoUsbDevice(ref monoUSBProfile);
+ rtnList.Add(newDevice);
+ }
+
+ return rtnList;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the instance address the device is using.
+ /// </summary>
+ public byte DeviceAddress
+ {
+ get { return mMonoUSBProfile.DeviceAddress; }
+ }
+
+ /// <summary>
+ /// Gets the bus number the device is connected to.
+ /// </summary>
+ public byte BusNumber
+ {
+ get { return mMonoUSBProfile.BusNumber; }
+ }
+
+ #region IUsbDevice Members
+
+ /// <summary>
+ /// Sends a usb device reset command.
+ /// </summary>
+ /// <remarks>
+ /// After calling <see cref="ResetDevice"/>, the <see cref="MonoUsbDevice"/> instance is disposed and
+ /// no longer usable. A new <see cref="MonoUsbDevice"/> instance must be obtained from the device list.
+ /// </remarks>
+ /// <returns>True on success.</returns>
+ public bool ResetDevice()
+ {
+ int ret;
+ if (!IsOpen) throw new UsbException(this, "Device is not opened.");
+ ActiveEndpoints.Clear();
+
+ if ((ret = MonoUsbApi.ResetDevice((MonoUsbDeviceHandle) mUsbHandle)) != 0)
+ {
+ UsbError.Error(ErrorCode.MonoApiError, ret, "ResetDevice Failed", this);
+ }
+ else
+ {
+ Close();
+ }
+
+ return ret == 0;
+ }
+
+ /// <summary>
+ /// Returns the DriverMode this USB device is using.
+ /// </summary>
+ public override DriverModeType DriverMode
+ {
+ get
+ {
+ if (IsLinux)
+ return DriverModeType.MonoLibUsb;
+
+ return DriverModeType.LibUsbWinBack;
+ }
+ }
+
+ /// <summary>
+ /// Closes the <see cref="UsbDevice"/> and disposes any <see cref="UsbDevice.ActiveEndpoints"/>.
+ /// </summary>
+ /// <returns>True on success.</returns>
+ public override bool Close()
+ {
+ ActiveEndpoints.Clear();
+ if (IsOpen) mUsbHandle.Close();
+
+ return true;
+ }
+
+
+ /// <summary>
+ /// Transmits control data over a default control endpoint.
+ /// </summary>
+ /// <param name="setupPacket">An 8-byte setup packet which contains parameters for the control request.
+ /// See section 9.3 USB Device Requests of the Universal Serial Bus Specification Revision 2.0 for more information. </param>
+ /// <param name="buffer">Data to be sent/received from the device.</param>
+ /// <param name="bufferLength">Length of the buffer param.</param>
+ /// <param name="lengthTransferred">Number of bytes sent or received (depends on the direction of the control transfer).</param>
+ /// <returns>True on success.</returns>
+ public override bool ControlTransfer(ref UsbSetupPacket setupPacket, IntPtr buffer, int bufferLength, out int lengthTransferred)
+ {
+ Debug.WriteLine(GetType().Name + ".ControlTransfer() Before", "Libusb-1.0");
+ int ret = MonoUsbApi.ControlTransferAsync((MonoUsbDeviceHandle) mUsbHandle,
+ setupPacket.RequestType,
+ setupPacket.Request,
+ setupPacket.Value,
+ setupPacket.Index,
+ buffer,
+ (short) bufferLength,
+ UsbConstants.DEFAULT_TIMEOUT);
+
+ Debug.WriteLine(GetType().Name + ".ControlTransfer() Error:" + ((MonoUsbError) ret).ToString(), "Libusb-1.0");
+ if (ret < 0)
+ {
+ UsbError.Error(ErrorCode.MonoApiError, ret, "ControlTransfer Failed", this);
+ lengthTransferred = 0;
+ return false;
+ }
+ lengthTransferred = ret;
+ return true;
+ }
+
+ /// <summary>
+ /// Gets a descriptor from the device. See <see cref="DescriptorType"/> for more information.
+ /// </summary>
+ /// <param name="descriptorType">The descriptor type ID to retrieve; this is usually one of the <see cref="DescriptorType"/> enumerations.</param>
+ /// <param name="index">Descriptor index.</param>
+ /// <param name="langId">Descriptor language id.</param>
+ /// <param name="buffer">Memory to store the returned descriptor in.</param>
+ /// <param name="bufferLength">Length of the buffer parameter in bytes.</param>
+ /// <param name="transferLength">The number of bytes transferred to buffer upon success.</param>
+ /// <returns>True on success.</returns>
+ public override bool GetDescriptor(byte descriptorType, byte index, short langId, IntPtr buffer, int bufferLength, out int transferLength)
+ {
+ transferLength = 0;
+ bool bSuccess = false;
+ bool wasOpen = IsOpen;
+ if (!wasOpen) Open();
+ if (!IsOpen) return false;
+
+ int ret = MonoUsbApi.GetDescriptor((MonoUsbDeviceHandle) mUsbHandle, descriptorType, index, buffer, (ushort) bufferLength);
+
+ if (ret < 0)
+ {
+ UsbError.Error(ErrorCode.MonoApiError, ret, "GetDescriptor Failed", this);
+ }
+ else
+ {
+ bSuccess = true;
+ transferLength = ret;
+ }
+
+ if (!wasOpen && IsOpen) Close();
+
+ return bSuccess;
+ }
+
+ ///<summary>
+ /// Opens the USB device handle.
+ ///</summary>
+ ///<returns>
+ ///True if the device is already opened or was opened successfully.
+ ///False if the device does not exists or is no longer valid.
+ ///</returns>
+ public override bool Open()
+ {
+ if (IsOpen) return true;
+ MonoUsbDeviceHandle handle = new MonoUsbDeviceHandle(mMonoUSBProfile.ProfileHandle);
+ if (handle.IsInvalid)
+ {
+ UsbError.Error(ErrorCode.MonoApiError, (int) MonoUsbDeviceHandle.LastErrorCode, "MonoUsbDevice.Open Failed", this);
+ mUsbHandle = null;
+ return false;
+ }
+ mUsbHandle = handle;
+ if (IsOpen) return true;
+
+ mUsbHandle.Close();
+ return false;
+ }
+
+ /// <summary>
+ /// Gets the <see cref="MonoUsbProfile"/> for this usb device.
+ /// </summary>
+ public MonoUsbProfile Profile
+ {
+ get
+ {
+ return mMonoUSBProfile;
+ }
+ }
+ /// <summary>
+ /// Opens an endpoint for reading
+ /// </summary>
+ /// <param name="readEndpointID">Endpoint number for read operations.</param>
+ /// <param name="readBufferSize">Size of the read buffer allocated for the <see cref="UsbEndpointReader.DataReceived"/> event.</param>
+ /// <param name="endpointType">The type of endpoint to open.</param>
+ /// <returns>A <see cref="UsbEndpointReader"/> class ready for reading. If the specified endpoint is already been opened, the original <see cref="UsbEndpointReader"/> class is returned.</returns>
+ public override UsbEndpointReader OpenEndpointReader(ReadEndpointID readEndpointID, int readBufferSize, EndpointType endpointType)
+ {
+ foreach (UsbEndpointBase activeEndpoint in mActiveEndpoints)
+ if (activeEndpoint.EpNum == (byte)readEndpointID)
+ return (UsbEndpointReader)activeEndpoint;
+
+ UsbEndpointReader epNew = new MonoUsbEndpointReader(this, readBufferSize, readEndpointID, endpointType);
+ return (UsbEndpointReader) ActiveEndpoints.Add(epNew);
+ }
+
+ /// <summary>
+ /// Opens an endpoint for writing
+ /// </summary>
+ /// <param name="writeEndpointID">Endpoint number for read operations.</param>
+ /// <param name="endpointType">The type of endpoint to open.</param>
+ /// <returns>A <see cref="UsbEndpointWriter"/> class ready for writing. If the specified endpoint is already been opened, the original <see cref="UsbEndpointWriter"/> class is returned.</returns>
+ public override UsbEndpointWriter OpenEndpointWriter(WriteEndpointID writeEndpointID, EndpointType endpointType)
+ {
+ foreach (UsbEndpointBase activeEndpoint in ActiveEndpoints)
+ if (activeEndpoint.EpNum == (byte)writeEndpointID)
+ return (UsbEndpointWriter)activeEndpoint;
+
+ UsbEndpointWriter epNew = new MonoUsbEndpointWriter(this, writeEndpointID, endpointType);
+ return (UsbEndpointWriter) mActiveEndpoints.Add(epNew);
+ }
+
+ /// <summary>
+ /// Sets the USB devices active configuration value.
+ /// </summary>
+ /// <param name="config">The active configuration value. A zero value means the device is not configured and a non-zero value indicates the device is configured.</param>
+ /// <returns>True on success.</returns>
+ /// <remarks>
+ /// A USB device can have several different configurations, but only one active configuration.
+ /// </remarks>
+ public bool SetConfiguration(byte config)
+ {
+ int ret = MonoUsbApi.SetConfiguration((MonoUsbDeviceHandle) mUsbHandle, config);
+ if (ret != 0)
+ {
+ UsbError.Error(ErrorCode.MonoApiError, ret, "SetConfiguration Failed", this);
+ return false;
+ }
+ mCurrentConfigValue = config;
+ return true;
+ }
+
+ /// <summary>
+ /// Gets the USB devices active configuration value.
+ /// </summary>
+ /// <param name="config">The active configuration value. A zero value means the device is not configured and a non-zero value indicates the device is configured.</param>
+ /// <returns>True on success.</returns>
+ public override bool GetConfiguration(out byte config)
+ {
+ config = 0;
+ int iconfig = 0;
+ int ret = MonoUsbApi.GetConfiguration((MonoUsbDeviceHandle) mUsbHandle, ref iconfig);
+ if (ret != 0)
+ {
+ UsbError.Error(ErrorCode.MonoApiError, ret, "GetConfiguration Failed", this);
+ return false;
+ }
+ config = (byte) iconfig;
+ mCurrentConfigValue = config;
+
+ return true;
+ }
+
+ /// <summary>
+ /// Gets the <see cref="UsbRegistry"/> class that opened the device, or null if the device was not opened by the <see cref="UsbRegistry"/> class.
+ /// </summary>
+ public override UsbRegistry UsbRegistryInfo
+ {
+ get { return null; }
+ }
+
+ ///<summary>
+ /// Gets the available configurations for this <see cref="UsbDevice"/>
+ ///</summary>
+ /// <remarks>
+ /// The first time this property is accessed it will query the <see cref="UsbDevice"/> for all configurations. Subsequent request will return a cached copy of all configurations.
+ /// </remarks>
+ public override ReadOnlyCollection<UsbConfigInfo> Configs
+ {
+ get
+ {
+ if (ReferenceEquals(mConfigs, null))
+ {
+ if (!IsOpen)
+ {
+ //Console.WriteLine("Device Not Opened!");
+ return null;
+ }
+ GetConfigs(this, out mConfigs);
+ }
+
+ return mConfigs.AsReadOnly();
+ }
+ }
+
+ /// <summary>
+ /// Gets the actual device descriptor the the current <see cref="UsbDevice"/>.
+ /// </summary>
+ public override UsbDeviceInfo Info
+ {
+ get
+ {
+ if (ReferenceEquals(mDeviceInfo, null))
+ {
+ mDeviceInfo = new UsbDeviceInfo(this, mMonoUSBProfile.DeviceDescriptor);
+ }
+ return mDeviceInfo;
+ }
+ }
+
+ /// <summary>
+ /// Claims the specified interface of the device.
+ /// </summary>
+ /// <param name="interfaceID">The interface to claim.</param>
+ /// <returns>True on success.</returns>
+ public bool ClaimInterface(int interfaceID)
+ {
+ int ret = MonoUsbApi.ClaimInterface((MonoUsbDeviceHandle) mUsbHandle, interfaceID);
+ if (ret != 0)
+ {
+ UsbError.Error(ErrorCode.MonoApiError, ret, "ClaimInterface Failed", this);
+ return false;
+ }
+ mClaimedInteface = interfaceID;
+ return true;
+ }
+
+ /// <summary>
+ /// Releases an interface that was previously claimed with <see cref="ClaimInterface"/>.
+ /// </summary>
+ /// <param name="interfaceID">The interface to release.</param>
+ /// <returns>True on success.</returns>
+ public bool ReleaseInterface(int interfaceID)
+ {
+ int ret = MonoUsbApi.ReleaseInterface((MonoUsbDeviceHandle) mUsbHandle, interfaceID);
+ if (ret != 0)
+ {
+ UsbError.Error(ErrorCode.MonoApiError, ret, "ReleaseInterface Failed", this);
+ return false;
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Sets an alternate interface for the most recent claimed interface.
+ /// </summary>
+ /// <param name="alternateID">The alternate interface to select for the most recent claimed interface See <see cref="ClaimInterface"/>.</param>
+ /// <returns>True on success.</returns>
+ public bool SetAltInterface(int alternateID)
+ {
+ int ret = MonoUsbApi.SetInterfaceAltSetting((MonoUsbDeviceHandle) mUsbHandle, mClaimedInteface, alternateID);
+ if (ret != 0)
+ {
+ UsbError.Error(ErrorCode.MonoApiError, ret, "SetAltInterface Failed", this);
+ return false;
+ }
+ return true;
+ }
+
+ #endregion
+
+ #region IDisposable implementation
+
+ #endregion
+
+ private static ErrorCode GetConfigs(MonoUsbDevice usbDevice, out List<UsbConfigInfo> configInfoListRtn)
+ {
+ configInfoListRtn = new List<UsbConfigInfo>();
+ UsbError usbError = null;
+ List<MonoUsbConfigDescriptor> configList = new List<MonoUsbConfigDescriptor>();
+ int iConfigs = usbDevice.Info.Descriptor.ConfigurationCount;
+
+ for (int iConfig = 0; iConfig < iConfigs; iConfig++)
+ {
+ MonoUsbConfigHandle nextConfigHandle;
+ int ret = MonoUsbApi.GetConfigDescriptor(usbDevice.mMonoUSBProfile.ProfileHandle, (byte) iConfig, out nextConfigHandle);
+ Debug.Print("GetConfigDescriptor:{0}", ret);
+ if (ret != 0 || nextConfigHandle.IsInvalid)
+ {
+ usbError = UsbError.Error(ErrorCode.MonoApiError,
+ ret,
+ String.Format("GetConfigDescriptor Failed at index:{0}", iConfig),
+ usbDevice);
+ return usbError.ErrorCode;
+ }
+ try
+ {
+ MonoUsbConfigDescriptor nextConfig = new MonoUsbConfigDescriptor();
+ Marshal.PtrToStructure(nextConfigHandle.DangerousGetHandle(), nextConfig);
+
+ UsbConfigInfo nextConfigInfo = new UsbConfigInfo(usbDevice, nextConfig);
+ configInfoListRtn.Add(nextConfigInfo);
+ }
+ catch (Exception ex)
+ {
+ UsbError.Error(ErrorCode.InvalidConfig, Marshal.GetLastWin32Error(), ex.ToString(), usbDevice);
+ }
+ finally
+ {
+ if (!nextConfigHandle.IsInvalid)
+ nextConfigHandle.Close();
+ }
+ }
+
+ return ErrorCode.Success;
+ }
+
+ internal static int RefreshProfileList()
+ {
+ lock (OLockDeviceList)
+ {
+ MonoUsbApi.InitAndStart();
+ if (mMonoUSBProfileList == null)
+ {
+ mMonoUSBProfileList = new MonoUsbProfileList();
+ }
+ return (int) mMonoUSBProfileList.Refresh(MonoUsbEventHandler.SessionHandle);
+ }
+ }
+
+ /// <summary>
+ /// Initializes the <see cref="MonoUsbEventHandler.SessionHandle"/> with <see cref="MonoUsbEventHandler.Init()"/> and starts the static handle events thread with <see cref="MonoUsbEventHandler.Start"/>.
+ /// </summary>
+ /// <remarks>
+ /// This is done automatically when needed.
+ /// <para>Usually there is no need to call this functions externally.</para>
+ /// </remarks>
+ public static void Init() { MonoUsbApi.InitAndStart(); }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/MonoUsbDeviceHandle.cs b/LibWinUsb/MonoLibUsb/MonoUsbDeviceHandle.cs
new file mode 100644
index 00000000..a9b977df
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/MonoUsbDeviceHandle.cs
@@ -0,0 +1,136 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Main;
+using MonoLibUsb.Profile;
+
+namespace MonoLibUsb
+{
+ /// <summary>
+ /// Represents a Libusb-1.0 device handle.
+ /// </summary>
+ /// <remarks>
+ /// <para>To close a device, see the <see cref="Close"/> method.</para>
+ /// <note title="Libusb-1.0 API Note:" type="cpp">A <see cref="MonoUsbDeviceHandle"/> is roughly equivalent to a <a href="http://libusb.sourceforge.net/api-1.0/group__dev.html#ga7df95821d20d27b5597f1d783749d6a4">libusb_device_handle</a>.</note>
+ /// </remarks>
+ /// <code>
+ /// MonoUsbDeviceHandle deviceHandle = new MonoUsbDeviceHandle(profileHandle);
+ /// if (deviceHandle.IsInvalid) throw new Exception("Invalid device context.");
+ /// </code>
+ public class MonoUsbDeviceHandle : SafeContextHandle
+ {
+ private static Object handleLOCK = new object();
+ private static MonoUsbError mLastReturnCode;
+ private static String mLastReturnString = String.Empty;
+
+ /// <summary>
+ /// If the device handle is <see cref="SafeContextHandle.IsInvalid"/>, gets a descriptive string for the <see cref="LastErrorCode"/>.
+ /// </summary>
+ public static string LastErrorString
+ {
+ get
+ {
+ lock (handleLOCK)
+ {
+ return mLastReturnString;
+ }
+ }
+ }
+ /// <summary>
+ /// If the device handle is <see cref="SafeContextHandle.IsInvalid"/>, gets the <see cref="MonoUsbError"/> status code indicating the reason.
+ /// </summary>
+ public static MonoUsbError LastErrorCode
+ {
+ get
+ {
+ lock (handleLOCK)
+ {
+ return mLastReturnCode;
+ }
+ }
+ }
+ /// <summary>Open a device handle from <paramref name="profileHandle"/>.</summary>
+ /// <remarks>
+ /// <para>A handle allows you to perform I/O on the device in question.</para>
+ /// <para>To close a device handle call its <see cref="SafeHandle.Close"/> method.</para>
+ /// <para>This is a non-blocking function; no requests are sent over the bus.</para>
+ /// <note title="Libusb-1.0 API Note:" type="cpp">The <see cref="MonoUsbDeviceHandle(MonoUsbProfileHandle)"/> constructor is roughly equivalent to <a href="http://libusb.sourceforge.net/api-1.0/group__dev.html#ga8163100afdf933fabed0db7fa81c89d1">libusb_open()</a>.</note>
+ /// </remarks>
+ /// <param name="profileHandle">A device profile handle.</param>
+ public MonoUsbDeviceHandle(MonoUsbProfileHandle profileHandle)
+ : base(IntPtr.Zero)
+ {
+ IntPtr pDeviceHandle = IntPtr.Zero;
+ int ret = MonoUsbApi.Open(profileHandle, ref pDeviceHandle);
+ if (ret < 0 || pDeviceHandle==IntPtr.Zero)
+ {
+ lock (handleLOCK)
+ {
+ mLastReturnCode = (MonoUsbError) ret;
+ mLastReturnString = MonoUsbApi.StrError(mLastReturnCode);
+ }
+ SetHandleAsInvalid();
+ }
+ else
+ {
+ SetHandle(pDeviceHandle);
+ }
+
+ }
+
+ internal MonoUsbDeviceHandle(IntPtr pDeviceHandle)
+ : base(pDeviceHandle)
+ {
+ }
+ ///<summary>
+ ///Closes the <see cref="MonoUsbDeviceHandle"/>.
+ ///</summary>
+ ///<returns>
+ ///true if the <see cref="MonoUsbDeviceHandle"/> is released successfully; otherwise, in the event of a catastrophic failure, false. In this case, it generates a ReleaseHandleFailed Managed Debugging Assistant.
+ ///</returns>
+ protected override bool ReleaseHandle()
+ {
+ if (!IsInvalid)
+ {
+ Debug.WriteLine(GetType().Name + ".ReleaseHandle() Before", "Libusb-1.0");
+ MonoUsbApi.Close(handle);
+ Debug.WriteLine(GetType().Name + ".ReleaseHandle() After", "Libusb-1.0");
+ SetHandleAsInvalid();
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Closes the <see cref="MonoUsbDeviceHandle"/> reference. When all references are no longer is use, the device
+ /// is closed in the <see cref="ReleaseHandle"/> finalizer.
+ /// </summary>
+ /// <remarks>
+ /// <note title="Libusb-1.0 API Note:" type="cpp">The <see cref="Close"/> method is roughly equivalent to <a href="http://libusb.sourceforge.net/api-1.0/group__dev.html#ga779bc4f1316bdb0ac383bddbd538620e">libusb_close()</a>.</note>
+ /// </remarks>
+ public new void Close()
+ {
+ base.Close();
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/MonoUsbEndpointReader.cs b/LibWinUsb/MonoLibUsb/MonoUsbEndpointReader.cs
new file mode 100644
index 00000000..079411d6
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/MonoUsbEndpointReader.cs
@@ -0,0 +1,81 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using LibUsbDotNet.Internal;
+using LibUsbDotNet.Main;
+using LibUsbDotNet.LudnMonoLibUsb.Internal;
+using MonoLibUsb;
+
+namespace LibUsbDotNet.LudnMonoLibUsb
+{
+ /// <summary>
+ /// Implements mono-linux libusb 1.x methods for reading data from a <see cref="EndpointType.Bulk"/> or <see cref="EndpointType.Interrupt"/> endpoints.
+ /// </summary>
+ public class MonoUsbEndpointReader : UsbEndpointReader
+ {
+ private MonoUsbTransferContext mMonoTransferContext;
+
+ internal MonoUsbEndpointReader(UsbDevice usbDevice, int readBufferSize, ReadEndpointID readEndpointID, EndpointType endpointType)
+ : base(usbDevice, readBufferSize, readEndpointID, endpointType) { }
+
+ /// <summary>
+ /// Frees resources associated with the endpoint. Once disposed this class cannot be used.
+ /// </summary>
+ public override void Dispose()
+ {
+ base.Dispose();
+ if (ReferenceEquals(mMonoTransferContext, null)) return;
+ mMonoTransferContext.Dispose();
+ mMonoTransferContext = null;
+ }
+
+ /// <summary>
+ /// Calling this methods is that same as calling <see cref="UsbEndpointReader.ReadFlush"/>
+ /// </summary>
+ /// <returns>True an success.</returns>
+ public override bool Flush()
+ {
+ if (IsDisposed) throw new ObjectDisposedException(GetType().Name);
+ return ReadFlush() == ErrorCode.Success;
+ }
+
+ /// <summary>
+ /// Cancels pending transfers and clears the halt condition on an enpoint.
+ /// </summary>
+ /// <returns>True on success.</returns>
+ public override bool Reset()
+ {
+ if (IsDisposed) throw new ObjectDisposedException(GetType().Name);
+ Abort();
+ int ret = MonoUsbApi.ClearHalt((MonoUsbDeviceHandle) Device.Handle, EpNum);
+ if (ret < 0)
+ {
+ UsbError.Error(ErrorCode.MonoApiError, ret, "Endpoint Reset Failed", this);
+ return false;
+ }
+ return true;
+ }
+
+
+ internal override UsbTransfer CreateTransferContext() { return new MonoUsbTransferContext(this); }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/MonoUsbEndpointWriter.cs b/LibWinUsb/MonoLibUsb/MonoUsbEndpointWriter.cs
new file mode 100644
index 00000000..b9d9f2ba
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/MonoUsbEndpointWriter.cs
@@ -0,0 +1,76 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using LibUsbDotNet.Internal;
+using LibUsbDotNet.Main;
+using LibUsbDotNet.LudnMonoLibUsb.Internal;
+using MonoLibUsb;
+
+namespace LibUsbDotNet.LudnMonoLibUsb
+{
+ /// <summary>
+ /// Implements mono-linux libusb 1.x methods for writing to methods for writing data to a <see cref="EndpointType.Bulk"/> or <see cref="EndpointType.Interrupt"/> endpoints.
+ /// </summary>
+ public class MonoUsbEndpointWriter : UsbEndpointWriter
+ {
+ private MonoUsbTransferContext mMonoTransferContext;
+
+ internal MonoUsbEndpointWriter(UsbDevice usbDevice, WriteEndpointID writeEndpointID,EndpointType endpointType)
+ : base(usbDevice, writeEndpointID, endpointType) { }
+
+ /// <summary>
+ /// Frees resources associated with the endpoint. Once disposed this class cannot be used.
+ /// </summary>
+ public override void Dispose()
+ {
+ base.Dispose();
+ if (ReferenceEquals(mMonoTransferContext, null)) return;
+ mMonoTransferContext.Dispose();
+ mMonoTransferContext = null;
+ }
+
+ /// <summary>
+ /// This method has no effect on write endpoints, andalways returs true.
+ /// </summary>
+ /// <returns>True</returns>
+ public override bool Flush() { return true; }
+
+ /// <summary>
+ /// Cancels pending transfers and clears the halt condition on an enpoint.
+ /// </summary>
+ /// <returns>True on success.</returns>
+ public override bool Reset()
+ {
+ if (IsDisposed) throw new ObjectDisposedException(GetType().Name);
+ Abort();
+ int ret = MonoUsbApi.ClearHalt((MonoUsbDeviceHandle) Device.Handle, EpNum);
+ if (ret < 0)
+ {
+ UsbError.Error(ErrorCode.MonoApiError, ret, "Endpoint Reset Failed", this);
+ return false;
+ }
+ return true;
+ }
+
+ internal override UsbTransfer CreateTransferContext() { return new MonoUsbTransferContext(this); }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/MonoUsbError.cs b/LibWinUsb/MonoLibUsb/MonoUsbError.cs
new file mode 100644
index 00000000..3079f8ff
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/MonoUsbError.cs
@@ -0,0 +1,106 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+
+namespace MonoLibUsb
+{
+ /// <summary>
+ /// Error codes.
+ /// Most libusb functions return 0 on success or one of these codes on failure.
+ /// </summary>
+ public enum MonoUsbError
+ {
+ /// <summary>
+ /// Success (no error)
+ /// </summary>
+ Success = 0,
+
+ /// <summary>
+ /// Input/output error
+ /// </summary>
+ ErrorIO = -1,
+
+ /// <summary>
+ /// Invalid parameter
+ /// </summary>
+ ErrorInvalidParam = -2,
+
+ /// <summary>
+ /// Access denied (insufficient permissions)
+ /// </summary>
+ ErrorAccess = -3,
+
+ /// <summary>
+ /// No such device (it may have been disconnected)
+ /// </summary>
+ ErrorNoDevice = -4,
+
+ /// <summary>
+ /// Entity not found
+ /// </summary>
+ ErrorNotFound = -5,
+
+ /// <summary>
+ /// Resource busy
+ /// </summary>
+ ErrorBusy = -6,
+
+ /// <summary>
+ /// Operation timed out
+ /// </summary>
+ ErrorTimeout = -7,
+
+ /// <summary>
+ /// Overflow
+ /// </summary>
+ ErrorOverflow = -8,
+
+ /// <summary>
+ /// Pipe error
+ /// </summary>
+ ErrorPipe = -9,
+
+ /// <summary>
+ /// System call interrupted (perhaps due to signal)
+ /// </summary>
+ ErrorInterrupted = -10,
+
+ /// <summary>
+ /// Insufficient memory
+ /// </summary>
+ ErrorNoMem = -11,
+
+ /// <summary>
+ /// Operation not supported or unimplemented on this platform
+ /// </summary>
+ ErrorNotSupported = -12,
+
+ /// <summary>
+ /// Cancel IO failed.
+ /// </summary>
+ ErrorIOCancelled = -13,
+
+ /// <summary>
+ /// Other error
+ /// </summary>
+ ErrorOther = -99,
+ } ;
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/MonoUsbEventHandler.cs b/LibWinUsb/MonoLibUsb/MonoUsbEventHandler.cs
new file mode 100644
index 00000000..3b5a272a
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/MonoUsbEventHandler.cs
@@ -0,0 +1,192 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Threading;
+using LibUsbDotNet.Main;
+
+namespace MonoLibUsb
+{
+ /// <summary>
+ /// Manages a static Libusb-1.0 <see cref="MonoUsbSessionHandle"/> and "handle_events" thread for simplified asynchronous IO.
+ /// </summary>
+ /// <remarks>
+ /// <para>This class contains its own <see cref="MonoUsbSessionHandle"/> that is initialized with one of the overloaded <see cref="MonoUsbEventHandler.Init()">MonoUsbEventHandler.Init()</see> functions.</para>
+ /// <para>This class contains a static thread that execute <see cref="MonoUsbApi.HandleEventsTimeout"/>. See the <see cref="Start"/> and <see cref="Stop"/> methods.</para>
+ /// </remarks>
+ public static class MonoUsbEventHandler
+ {
+ private static readonly ManualResetEvent mIsStoppedEvent = new ManualResetEvent(true);
+ private static bool mRunning;
+ private static MonoUsbSessionHandle mSessionHandle;
+ internal static Thread mUsbEventThread;
+ private static ThreadPriority mPriority = ThreadPriority.Normal;
+
+ private static UnixNativeTimeval mWaitUnixNativeTimeval;
+
+ /// <summary>
+ /// Gets the session handle.
+ /// </summary>
+ /// <remarks>
+ /// Used for MonoLibUsb members that require the <see cref="MonoUsbSessionHandle"/> parameter.
+ /// </remarks>
+ public static MonoUsbSessionHandle SessionHandle
+ {
+ get { return mSessionHandle; }
+ }
+
+ /// <summary>
+ /// False if the handle events thread is running.
+ /// </summary>
+ public static bool IsStopped
+ {
+ get { return mIsStoppedEvent.WaitOne(0, false); }
+ }
+
+ /// <summary>
+ /// Thread proirity to use for the handle events thread.
+ /// </summary>
+ public static ThreadPriority Priority
+ {
+ get { return mPriority; }
+ set {mPriority=value;}
+ }
+
+ /// <summary>
+ /// Stops the handle events thread and closes the session handle.
+ /// </summary>
+ public static void Exit()
+ {
+ Stop(true);
+ if (mSessionHandle == null) return;
+
+ if (mSessionHandle.IsInvalid) return;
+ mSessionHandle.Close();
+ mSessionHandle = null;
+ }
+
+ private static void HandleEventFn(object oHandle)
+ {
+ MonoUsbSessionHandle sessionHandle = oHandle as MonoUsbSessionHandle;
+
+ mIsStoppedEvent.Reset();
+
+ while (mRunning)
+ MonoUsbApi.HandleEventsTimeout(sessionHandle, ref mWaitUnixNativeTimeval);
+
+ mIsStoppedEvent.Set();
+ }
+
+
+ /// <summary>
+ /// Initializes the <see cref="SessionHandle"/> and sets a custom polling interval.
+ /// </summary>
+ /// <param name="tvSec">polling interval seconds</param>
+ /// <param name="tvUsec">polling interval milliseconds</param>
+ /// <seealso cref="Init()"/>
+ /// <seealso cref="SessionHandle"/>
+ public static void Init(long tvSec, long tvUsec) { Init(new UnixNativeTimeval(tvSec, tvUsec)); }
+
+ /// <summary>
+ /// Initializes the <see cref="SessionHandle"/>.
+ /// </summary>
+ /// <remarks>
+ /// <para>If the session has already been initialized, this method does nothing.</para>
+ /// <para>The handle events thread is not started until the <see cref="Start"/> method is called.</para>
+ /// <para>Uses the MonoLibUsb <see cref="UnixNativeTimeval.Default"/> polling interval for <see cref="MonoUsbApi.HandleEventsTimeout"/>.</para>
+ /// </remarks>
+ public static void Init() { Init(UnixNativeTimeval.Default); }
+
+ private static void Init(UnixNativeTimeval unixNativeTimeval)
+ {
+ if (IsStopped && !mRunning && mSessionHandle==null)
+ {
+ mWaitUnixNativeTimeval = unixNativeTimeval;
+ mSessionHandle=new MonoUsbSessionHandle();
+ if (mSessionHandle.IsInvalid)
+ {
+ mSessionHandle = null;
+ throw new UsbException(typeof (MonoUsbApi), String.Format("Init:libusb_init Failed:Invalid Session Handle"));
+ }
+ }
+ }
+
+ /// <summary>
+ /// Starts the handle events thread.
+ /// </summary>
+ /// <remarks>
+ /// <para>If the thread is already running, this method does nothing.</para>
+ /// <para>
+ /// Using a seperate thread which executes <see cref="MonoUsbApi.HandleEventsTimeout"/> can simplify asynchronous I/O
+ /// and improve performance in multi-threaded applications which use multiple endpoints.
+ /// </para>
+ /// </remarks>
+ /// <returns>
+ /// True if the thread is started or is already running.
+ /// </returns>
+ public static bool Start()
+ {
+ if (IsStopped && !mRunning && mSessionHandle!=null)
+ {
+ mRunning = true;
+ mUsbEventThread = new Thread(HandleEventFn);
+ mUsbEventThread.Priority = mPriority;
+ mUsbEventThread.Start(mSessionHandle);
+
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Stops the handle events thread.
+ /// </summary>
+ /// <remarks>
+ /// <para>Calling this method when the thread is not running will have no affect.</para>
+ /// <note type="warning">
+ /// If the thread is running, this method must be called before the application exits.
+ /// Failure to do so will cause the application to hang.
+ /// </note>
+ /// </remarks>
+ /// <param name="bWait">If true, wait for the thread to exit before returning.</param>
+ public static void Stop(bool bWait)
+ {
+ if (!IsStopped && mRunning)
+ {
+ mRunning = false;
+
+ if (bWait)
+ {
+ bool bSuccess = mUsbEventThread.Join((int)((mWaitUnixNativeTimeval.tv_sec * 1000 + mWaitUnixNativeTimeval.tv_usec) * 1.2));
+ //bool bSuccess = mIsStoppedEvent.WaitOne((int)((mWaitUnixNativeTimeval.tv_sec * 1000 + mWaitUnixNativeTimeval.tv_usec) * 1.2), false);
+ if (!bSuccess)
+ {
+ mUsbEventThread.Abort();
+ throw new UsbException(typeof(MonoUsbEventHandler), "Critical timeout failure! MonoUsbApi.HandleEventsTimeout did not return within the allotted time.");
+ //LibUsbDotNet.UsbError.Error(ErrorCode.UnknownError, 0, "Critical timeout failure!", typeof(MonoUsbEventHandler));
+ //mIsStoppedEvent.Set();
+ }
+ }
+ mUsbEventThread = null;
+
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/MonoUsbSessionHandle.cs b/LibWinUsb/MonoLibUsb/MonoUsbSessionHandle.cs
new file mode 100644
index 00000000..ef1e0cdb
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/MonoUsbSessionHandle.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Main;
+
+namespace MonoLibUsb
+{
+ /// <summary>
+ /// Class representing a Libusb-1.0 session session handle.
+ /// Session handled are wrapped in a <see cref="System.Runtime.ConstrainedExecution.CriticalFinalizerObject"/>.
+ /// </summary>
+ /// <remarks>
+ /// <para>The concept of individual Libusb-1.0 sessions allows for your program to use two libraries
+ /// (or dynamically load two modules) which both independently use libusb. This will prevent interference between the
+ /// individual libusb users - for example <see cref="MonoUsbApi.SetDebug"/> will not affect the other
+ /// user of the library, and <see cref="SafeHandle.Close"/> will not destroy resources that the
+ /// other user is still using.</para>
+ /// <para>Sessions are created when a new <see cref="MonoUsbSessionHandle"/> instance is created and destroyed through <see cref="SafeHandle.Close"/>.</para>
+ /// <para>A <see cref="MonoUsbSessionHandle"/> instance must be created before calling any other <a href="http://libusb.sourceforge.net/api-1.0/index.html">Libusb-1.0 API</a> function.</para>
+ /// <para>Session handles are equivalent to a <a href="http://libusb.sourceforge.net/api-1.0/group__lib.html#ga4ec088aa7b79c4a9599e39bf36a72833">libusb_context</a>.</para>
+ /// </remarks>
+ public class MonoUsbSessionHandle:SafeContextHandle
+ {
+ private static Object sessionLOCK = new object();
+ private static MonoUsbError mLastReturnCode;
+ private static String mLastReturnString=String.Empty;
+ private static int mSessionCount;
+ private static string DLL_NOT_FOUND_LINUX = "libusb-1.0 library not found. This is often an indication that libusb-1.0 was installed to '/usr/local/lib' and mono.net is not looking for it there. To resolve this, add the path '/usr/local/lib' to '/etc/ld.so.conf' and run 'ldconfig' as root. (http://www.mono-project.com/DllNotFoundException)";
+ private static string DLL_NOT_FOUND_WINDOWS = "libusb-1.0.dll not found. If this is a 64bit operating system, ensure that the 64bit version of libusb-1.0.dll exists in the '\\Windows\\System32' directory.";
+
+ /// <summary>
+ /// If the session handle is <see cref="SafeContextHandle.IsInvalid"/>, gets the <see cref="MonoUsbError"/> status code indicating the reason.
+ /// </summary>
+ public static MonoUsbError LastErrorCode
+ {
+ get
+ {
+ lock (sessionLOCK)
+ {
+ return mLastReturnCode;
+ }
+ }
+ }
+ /// <summary>
+ /// If the session handle is <see cref="SafeContextHandle.IsInvalid"/>, gets a descriptive string for the <see cref="LastErrorCode"/>.
+ /// </summary>
+ public static string LastErrorString
+ {
+ get
+ {
+ lock (sessionLOCK)
+ {
+ return mLastReturnString;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Creates and initialize a <a href="http://libusb.sourceforge.net/api-1.0/index.html">Libusb-1.0</a> USB session handle.
+ /// </summary>
+ /// <remarks>
+ /// <para>A <see cref="MonoUsbSessionHandle"/> instance must be created before calling any other <a href="http://libusb.sourceforge.net/api-1.0/index.html">Libusb-1.0 API</a> function.</para>
+ /// </remarks>
+ public MonoUsbSessionHandle() : base(IntPtr.Zero, true)
+ {
+ lock (sessionLOCK)
+ {
+ IntPtr pNewSession = IntPtr.Zero;
+ try
+ {
+ mLastReturnCode = (MonoUsbError)MonoUsbApi.Init(ref pNewSession);
+ }
+ catch (DllNotFoundException dllNotFound)
+ {
+ if (Helper.IsLinux)
+ {
+ throw new DllNotFoundException(DLL_NOT_FOUND_LINUX, dllNotFound);
+ }
+ else
+ {
+ throw new DllNotFoundException(DLL_NOT_FOUND_WINDOWS, dllNotFound);
+ }
+ }
+ if ((int)mLastReturnCode < 0)
+ {
+ mLastReturnString = MonoUsbApi.StrError(mLastReturnCode);
+ SetHandleAsInvalid();
+ }
+ else
+ {
+ SetHandle(pNewSession);
+ mSessionCount++;
+ }
+ }
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <returns></returns>
+ protected override bool ReleaseHandle()
+ {
+ if (!IsInvalid)
+ {
+ lock (sessionLOCK)
+ {
+ MonoUsbApi.Exit(handle);
+ SetHandleAsInvalid();
+ mSessionCount--;
+ Debug.Print(GetType().Name + " : ReleaseHandle #{0}", mSessionCount);
+
+ }
+ }
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Profile/AddRemoveEventArgs.cs b/LibWinUsb/MonoLibUsb/Profile/AddRemoveEventArgs.cs
new file mode 100644
index 00000000..3f6f2d06
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Profile/AddRemoveEventArgs.cs
@@ -0,0 +1,34 @@
+using System;
+
+namespace MonoLibUsb.Profile
+{
+ /// <summary>
+ /// Describes a device arrival/removal notification event
+ /// </summary>
+ public class AddRemoveEventArgs : EventArgs
+ {
+ private readonly AddRemoveType mAddRemoveType;
+ private readonly MonoUsbProfile mMonoUSBProfile;
+
+ internal AddRemoveEventArgs(MonoUsbProfile monoUSBProfile, AddRemoveType addRemoveType)
+ {
+ mMonoUSBProfile = monoUSBProfile;
+ mAddRemoveType = addRemoveType;
+ }
+ /// <summary>
+ /// The <see cref ="MonoUsbProfile"/> that was added or removed.
+ /// </summary>
+ public MonoUsbProfile MonoUSBProfile
+ {
+ get { return mMonoUSBProfile; }
+ }
+
+ /// <summary>
+ /// The type of event that occured.
+ /// </summary>
+ public AddRemoveType EventType
+ {
+ get { return mAddRemoveType; }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Profile/AddRemoveType.cs b/LibWinUsb/MonoLibUsb/Profile/AddRemoveType.cs
new file mode 100644
index 00000000..b9bbbbf6
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Profile/AddRemoveType.cs
@@ -0,0 +1,38 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace MonoLibUsb.Profile
+{
+ /// <summary>
+ /// Event type.
+ /// </summary>
+ public enum AddRemoveType
+ {
+ /// <summary>
+ /// A usb device was attached.
+ /// </summary>
+ Added,
+ /// <summary>
+ /// A usb device was detached.
+ /// </summary>
+ Removed
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Profile/MonoUsbConfigHandle.cs b/LibWinUsb/MonoLibUsb/Profile/MonoUsbConfigHandle.cs
new file mode 100644
index 00000000..4c4ea936
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Profile/MonoUsbConfigHandle.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Main;
+using MonoLibUsb.Descriptors;
+
+namespace MonoLibUsb.Profile
+{
+ /// <summary>
+ /// The <see cref="MonoUsbConfigHandle"/> class hold the internal pointer to a libusb <see cref="MonoUsbConfigDescriptor"/>.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// To acquire a <see cref="MonoUsbConfigHandle"/> use:
+ /// <list type="bullet">
+ /// <item><see cref="MonoUsbApi.GetActiveConfigDescriptor"/></item>
+ /// <item><see cref="MonoUsbApi.GetConfigDescriptor"/></item>
+ /// <item><see cref="MonoUsbApi.GetConfigDescriptorByValue"/></item>
+ /// </list>
+ /// </para>
+ /// <para>To access configuration information see <see cref="MonoUsbConfigDescriptor(MonoUsbConfigHandle)"/>.</para>
+ /// <example><code source="..\MonoLibUsb\MonoUsb.ShowConfig\ShowConfig.cs" lang="cs"/></example>
+ /// </remarks>
+ public class MonoUsbConfigHandle:SafeContextHandle
+ {
+ private MonoUsbConfigHandle() : base(IntPtr.Zero,true) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <returns></returns>
+ protected override bool ReleaseHandle()
+ {
+ if (!IsInvalid)
+ {
+ MonoUsbApi.FreeConfigDescriptor(handle);
+ SetHandleAsInvalid();
+ }
+ return true;
+ }
+ }
+}
diff --git a/LibWinUsb/MonoLibUsb/Profile/MonoUsbProfile.cs b/LibWinUsb/MonoLibUsb/Profile/MonoUsbProfile.cs
new file mode 100644
index 00000000..d82b58e8
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Profile/MonoUsbProfile.cs
@@ -0,0 +1,186 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+
+using LibUsbDotNet;
+using LibUsbDotNet.Main;
+using MonoLibUsb.Descriptors;
+
+namespace MonoLibUsb.Profile
+{
+ /// <summary>
+ /// Representing a USB device that can be opened and used by Libusb-1.0.
+ /// </summary>
+ public class MonoUsbProfile
+ {
+ private readonly byte mBusNumber;
+ private readonly byte mDeviceAddress;
+ private readonly MonoUsbDeviceDescriptor mMonoUsbDeviceDescriptor = new MonoUsbDeviceDescriptor();
+ private readonly MonoUsbProfileHandle mMonoUSBProfileHandle;
+ internal bool mDiscovered;
+
+ internal MonoUsbProfile(MonoUsbProfileHandle monoUSBProfileHandle)
+ {
+ mMonoUSBProfileHandle = monoUSBProfileHandle;
+ mBusNumber = MonoUsbApi.GetBusNumber(mMonoUSBProfileHandle);
+ mDeviceAddress = MonoUsbApi.GetDeviceAddress(mMonoUSBProfileHandle);
+ GetDeviceDescriptor(out mMonoUsbDeviceDescriptor);
+
+//#if DEBUG
+// Console.WriteLine("Vid:{0:X4} Pid:{1:X4} BusNumber:{2} DeviceAddress:{3}",
+// mMonoUsbDeviceDescriptor.VendorID,
+// mMonoUsbDeviceDescriptor.ProductID,
+// mBusNumber,
+// mDeviceAddress);
+//#endif
+ }
+
+ /// <summary>
+ /// Gets the standard usb device descriptor.
+ /// </summary>
+ public MonoUsbDeviceDescriptor DeviceDescriptor
+ {
+ get { return mMonoUsbDeviceDescriptor; }
+ }
+
+ /// <summary>
+ /// Gets the bus number the is resides on.
+ /// </summary>
+ public byte BusNumber
+ {
+ get { return mBusNumber; }
+ }
+
+ /// <summary>
+ /// Gets the device address that belongs to the usb device this profile represents.
+ /// </summary>
+ public byte DeviceAddress
+ {
+ get { return mDeviceAddress; }
+ }
+
+ /// <summary>
+ /// Gets the internal profile handle need for some api calls.
+ /// </summary>
+ public MonoUsbProfileHandle ProfileHandle
+ {
+ get { return mMonoUSBProfileHandle; }
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
+ /// </summary>
+ /// <returns>
+ /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
+ /// </returns>
+ /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>. </param><exception cref="T:System.NullReferenceException">The <paramref name="obj"/> parameter is null.</exception><filterpriority>2</filterpriority>
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != typeof (MonoUsbProfile)) return false;
+ return Equals((MonoUsbProfile) obj);
+ }
+
+ /// <summary>
+ /// Serves as a hash function for a particular type.
+ /// </summary>
+ /// <returns>
+ /// A hash code for the current <see cref="T:System.Object"/>.
+ /// </returns>
+ /// <filterpriority>2</filterpriority>
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return (mBusNumber.GetHashCode()*397) ^ mDeviceAddress.GetHashCode();
+ }
+ }
+
+ ///<summary>
+ /// <c>true</c> if the <see cref="MonoUsbProfile"/> types are equal.
+ ///</summary>
+ /// <remarks>
+ /// <see cref="MonoUsbProfile"/> types are considered equal they have the same <see cref="BusNumber"/> and <see cref="DeviceAddress"/>.
+ /// </remarks>
+ ///<param name="left"><see cref="MonoUsbProfile"/> on the left.</param>
+ ///<param name="right"><see cref="MonoUsbProfile"/> on the right.</param>
+ ///<returns>True if the <see cref="MonoUsbProfile"/> types are equal.</returns>
+ public static bool operator ==(MonoUsbProfile left, MonoUsbProfile right) { return Equals(left, right); }
+
+ ///<summary>
+ /// <c>true</c> if the <see cref="MonoUsbProfile"/> types are not equal.
+ ///</summary>
+ /// <remarks>
+ /// <see cref="MonoUsbProfile"/> types are considered equal they have the same <see cref="BusNumber"/> and <see cref="DeviceAddress"/>.
+ /// </remarks>
+ ///<param name="left"><see cref="MonoUsbProfile"/> on the left.</param>
+ ///<param name="right"><see cref="MonoUsbProfile"/> on the right.</param>
+ ///<returns>True if the <see cref="MonoUsbProfile"/> types are not equal.</returns>
+ public static bool operator !=(MonoUsbProfile left, MonoUsbProfile right) { return !Equals(left, right); }
+
+ private MonoUsbError GetDeviceDescriptor(out MonoUsbDeviceDescriptor monoUsbDeviceDescriptor)
+ {
+ MonoUsbError ec = MonoUsbError.Success;
+
+ monoUsbDeviceDescriptor = new MonoUsbDeviceDescriptor();
+ //Console.WriteLine("MonoUsbProfile:GetDeviceDescriptor");
+ ec = (MonoUsbError) MonoUsbApi.GetDeviceDescriptor(mMonoUSBProfileHandle, monoUsbDeviceDescriptor);
+ if (ec != MonoUsbError.Success)
+ {
+#if LIBUSBDOTNET
+ UsbError.Error(ErrorCode.MonoApiError, (int) ec, "GetDeviceDescriptor Failed", this);
+#endif
+ monoUsbDeviceDescriptor = null;
+ }
+ return ec;
+ }
+
+ /// <summary>
+ /// Closes the internal <see cref="MonoUsbProfileHandle"/>.
+ /// </summary>
+ public void Close()
+ {
+ if (!mMonoUSBProfileHandle.IsClosed)
+ mMonoUSBProfileHandle.Close();
+ }
+
+ /// <summary>
+ /// Convenience function to open the device handle this profile handle represents.
+ /// </summary>
+ /// <returns>
+ /// A new <see cref="MonoUsbDeviceHandle"/> instance. Created with <see cref="MonoUsbDeviceHandle(MonoUsbProfileHandle)"/> constructor.
+ /// </returns>
+ public MonoUsbDeviceHandle OpenDeviceHandle() { return new MonoUsbDeviceHandle(ProfileHandle); }
+
+ /// <summary>
+ /// Compares a <see cref="MonoUsbProfile"/> with this one.
+ /// </summary>
+ /// <param name="other">The other <see cref="MonoUsbProfile"/>.</param>
+ /// <returns>True if the <see cref="BusNumber"/> and <see cref="DeviceAddress"/> are equal.</returns>
+ public bool Equals(MonoUsbProfile other)
+ {
+ if (ReferenceEquals(null, other)) return false;
+ if (ReferenceEquals(this, other)) return true;
+ return other.mBusNumber == mBusNumber && other.mDeviceAddress == mDeviceAddress;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Profile/MonoUsbProfileHandle.cs b/LibWinUsb/MonoLibUsb/Profile/MonoUsbProfileHandle.cs
new file mode 100644
index 00000000..3d939001
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Profile/MonoUsbProfileHandle.cs
@@ -0,0 +1,110 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Main;
+
+namespace MonoLibUsb.Profile
+{
+ /// <summary>
+ /// Wraps a profile handle into a <see cref="System.Runtime.ConstrainedExecution.CriticalFinalizerObject"/>.
+ /// Profile handles are used for getting device descriptor information and opening the device. Profile handles
+ /// are known connected and usually supported usb device that can be opened and used.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// When a <see cref="MonoUsbProfileHandle"/> instance is created and wrapped around the
+ /// <a href="http://libusb.sourceforge.net/api-1.0/group__dev.html#ga77eedd00d01eb7569b880e861a971c2b">libusb_device</a>
+ /// pointer, <see cref="MonoUsbApi.RefDevice"/> is called. When all references to this
+ /// <see cref="MonoUsbProfileHandle"/> instance are out-of-scope or have all been closed, this profile handle is de-referenced with
+ /// <see cref="MonoUsbApi.UnrefDevice"/>.
+ /// When the reference count equals zero, memory is freed and resources are released.
+ /// </para>
+ /// <para>
+ /// The <see cref="MonoUsbProfileHandle"/> class ensures all device profiles get closed and freed
+ /// regardless of abnormal program terminations or coding errors.
+ /// </para>
+ /// <para>
+ /// Certain operations can be performed using just the <see cref="MonoUsbProfileHandle"/>, but in order to do
+ /// any I/O you will have to first obtain a <see cref="MonoUsbDeviceHandle"/> using <see cref="MonoUsbApi.Open"/>.
+ /// </para>
+ /// </remarks>
+ public class MonoUsbProfileHandle : SafeContextHandle
+ {
+
+
+ /// <summary>
+ /// Wraps a raw usb device profile handle pointer in a <see cref="MonoUsbProfileHandle"/> class.
+ /// </summary>
+ /// <param name="pProfileHandle">the profile handle to wrap.</param>
+ public MonoUsbProfileHandle(IntPtr pProfileHandle) : base(pProfileHandle,true)
+ {
+ lock (oDeviceProfileRefLock)
+ {
+ MonoUsbApi.RefDevice(pProfileHandle);
+ mDeviceProfileRefCount++;
+ }
+ }
+
+ #region Overridden Members
+
+ /// <summary>
+ /// When overridden in a derived class, executes the code required to free the handle.
+ /// </summary>
+ /// <returns>
+ /// true if the handle is released successfully; otherwise, in the event of a catastrophic failure, false. In this case, it generates a ReleaseHandleFailed Managed Debugging Assistant.
+ /// </returns>
+ protected override bool ReleaseHandle()
+ {
+ lock (oDeviceProfileRefLock)
+ {
+ if (!IsInvalid)
+ {
+ MonoUsbApi.UnrefDevice(handle);
+ mDeviceProfileRefCount--;
+ SetHandleAsInvalid();
+ Debug.Print(GetType().Name + " : ReleaseHandle #{0}", mDeviceProfileRefCount);
+ }
+ return true;
+ }
+ }
+
+ #endregion
+
+ #region STATIC Members
+
+ internal static int DeviceProfileRefCount
+ {
+ get
+ {
+ lock (oDeviceProfileRefLock)
+ return mDeviceProfileRefCount;
+ }
+ }
+
+ private static int mDeviceProfileRefCount;
+ private static readonly object oDeviceProfileRefLock = new object();
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Profile/MonoUsbProfileHandleEnumerator.cs b/LibWinUsb/MonoLibUsb/Profile/MonoUsbProfileHandleEnumerator.cs
new file mode 100644
index 00000000..6c654174
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Profile/MonoUsbProfileHandleEnumerator.cs
@@ -0,0 +1,111 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace MonoLibUsb.Profile
+{
+ /// <summary>
+ /// A forward-only enumerator for iterating a device lists.
+ /// </summary>
+ internal class MonoUsbProfileHandleEnumerator : IEnumerator<MonoUsbProfileHandle>
+ {
+ private readonly MonoUsbProfileListHandle mProfileListHandle;
+ private MonoUsbProfileHandle mCurrentProfile;
+ private int mNextDeviceProfilePos;
+
+
+ internal MonoUsbProfileHandleEnumerator(MonoUsbProfileListHandle profileListHandle)
+ {
+ mProfileListHandle = profileListHandle;
+ Reset();
+ }
+
+ #region IEnumerator<MonoUsbProfileHandle> Members
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ /// <filterpriority>2</filterpriority>
+ public void Dispose() { Reset(); }
+
+
+ /// <summary>
+ /// Advances the enumerator to the next <see cref="MonoUsbProfileHandle"/> element of the collection.
+ /// </summary>
+ /// <returns>
+ /// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.
+ /// </returns>
+ /// <exception cref="T:System.InvalidOperationException">The collection was modified after the enumerator was created. </exception><filterpriority>2</filterpriority>
+ public bool MoveNext()
+ {
+ IntPtr pNextProfileHandle =
+ Marshal.ReadIntPtr(new IntPtr(mProfileListHandle.DangerousGetHandle().ToInt64() + (mNextDeviceProfilePos*IntPtr.Size)));
+ if (pNextProfileHandle != IntPtr.Zero)
+ {
+ mCurrentProfile = new MonoUsbProfileHandle(pNextProfileHandle);
+ mNextDeviceProfilePos++;
+ return true;
+ }
+ mCurrentProfile = null;
+ return false;
+ }
+
+
+ /// <summary>
+ /// Sets the enumerator to its initial position, which is before the first element in the collection.
+ /// </summary>
+ /// <exception cref="T:System.InvalidOperationException">The collection was modified after the enumerator was created. </exception><filterpriority>2</filterpriority>
+ public void Reset()
+ {
+ mNextDeviceProfilePos = 0;
+ mCurrentProfile = null;
+ }
+
+ /// <summary>
+ /// Gets the element in the <see cref="MonoUsbProfileHandle"/> collection at the current position of the enumerator.
+ /// </summary>
+ /// <returns>
+ /// The current <see cref="MonoUsbProfileHandle"/> element.
+ /// </returns>
+ public MonoUsbProfileHandle Current
+ {
+ get { return mCurrentProfile; }
+ }
+
+ /// <summary>
+ /// Gets the current element in the <see cref="MonoUsbProfileHandle"/> collection.
+ /// </summary>
+ /// <returns>
+ /// The current <see cref="MonoUsbProfileHandle"/> element.
+ /// </returns>
+ /// <exception cref="T:System.InvalidOperationException">The enumerator is positioned before the first element of the collection or after the last element.-or- The collection was modified after the enumerator was created.</exception><filterpriority>2</filterpriority>
+ object IEnumerator.Current
+ {
+ get { return Current; }
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Profile/MonoUsbProfileList.cs b/LibWinUsb/MonoLibUsb/Profile/MonoUsbProfileList.cs
new file mode 100644
index 00000000..05d4fc7e
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Profile/MonoUsbProfileList.cs
@@ -0,0 +1,259 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using LibUsbDotNet;
+using LibUsbDotNet.Main;
+
+namespace MonoLibUsb.Profile
+{
+ /// <summary>
+ /// Manages the device list. This class is thread safe.
+ /// </summary>
+ public class MonoUsbProfileList : IEnumerable<MonoUsbProfile>
+ {
+ private object LockProfileList = new object();
+
+ private static bool FindDiscoveredFn(MonoUsbProfile check) { return check.mDiscovered; }
+ private static bool FindUnDiscoveredFn(MonoUsbProfile check) { return !check.mDiscovered; }
+
+ private List<MonoUsbProfile> mList=new List<MonoUsbProfile>();
+ private void FireAddRemove(MonoUsbProfile monoUSBProfile, AddRemoveType addRemoveType)
+ {
+ EventHandler<AddRemoveEventArgs> temp = AddRemoveEvent;
+ if (!ReferenceEquals(temp, null))
+ {
+ temp(this, new AddRemoveEventArgs(monoUSBProfile, addRemoveType));
+ }
+ }
+
+ private void SetDiscovered(bool discovered)
+ {
+ foreach (MonoUsbProfile deviceProfile in this)
+ {
+ deviceProfile.mDiscovered = discovered;
+ }
+ }
+
+ private void syncWith(MonoUsbProfileList newList)
+ {
+ SetDiscovered(false);
+ newList.SetDiscovered(true);
+
+ int iNewProfiles = newList.mList.Count;
+ for (int iNewProfile = 0; iNewProfile < iNewProfiles; iNewProfile++)
+ {
+ MonoUsbProfile newProfile = newList.mList[iNewProfile];
+ int iFoundOldIndex;
+ if ((iFoundOldIndex = mList.IndexOf(newProfile)) == -1)
+ {
+ //Console.WriteLine("DeviceDiscovery: Added: {0}", newProfile.ProfileHandle.DangerousGetHandle());
+ newProfile.mDiscovered = true;
+ mList.Add(newProfile);
+ FireAddRemove(newProfile, AddRemoveType.Added);
+ }
+ else
+ {
+ //Console.WriteLine("DeviceDiscovery: Unchanged: Orig:{0} New:{1}", mList[iFoundOldIndex].ProfileHandle.DangerousGetHandle(), newProfile.ProfileHandle.DangerousGetHandle());
+ mList[iFoundOldIndex].mDiscovered = true;
+ newProfile.mDiscovered = false;
+
+ }
+ }
+
+ newList.mList.RemoveAll(FindDiscoveredFn);
+ newList.Close();
+
+ foreach (MonoUsbProfile deviceProfile in mList)
+ {
+ if (!deviceProfile.mDiscovered)
+ {
+ // Close Unplugged device profiles.
+ //Console.WriteLine("DeviceDiscovery: Removed: {0}", deviceProfile.ProfileHandle.DangerousGetHandle());
+ FireAddRemove(deviceProfile, AddRemoveType.Removed);
+ deviceProfile.Close();
+ }
+ }
+
+ // Remove Unplugged device profiles.
+ mList.RemoveAll(FindUnDiscoveredFn);
+ }
+
+
+ /// <summary>
+ /// Refreshes the <see cref="MonoUsbProfile"/> list.
+ /// </summary>
+ /// <remarks>
+ /// <para>This is your entry point into finding a USB device to operate.</para>
+ /// <para>This return value of this function indicates the number of devices in the resultant list.</para>
+ /// <para>The <see cref="MonoUsbProfileList"/> has a crude form of built-in device notification that works on all platforms. By adding an event handler to the <see cref="AddRemoveEvent"/> changes in the device profile list are reported when <see cref="Refresh"/> is called.</para>
+ /// </remarks>
+ /// <param name="sessionHandle">A valid <see cref="MonoUsbSessionHandle"/>.</param>
+ /// <returns>The number of devices in the outputted list, or <see cref="MonoUsbError.ErrorNoMem"/> on memory allocation failure.</returns>
+ /// <example>
+ /// <code source="..\MonoLibUsb\MonoUsb.ShowInfo\ShowInfo.cs" lang="cs"/>
+ /// </example>
+ public int Refresh(MonoUsbSessionHandle sessionHandle)
+ {
+ lock (LockProfileList)
+ {
+ MonoUsbProfileList newList = new MonoUsbProfileList();
+ MonoUsbProfileListHandle monoUSBProfileListHandle;
+
+ int ret = MonoUsbApi.GetDeviceList(sessionHandle, out monoUSBProfileListHandle);
+ if (ret < 0 || monoUSBProfileListHandle.IsInvalid)
+ {
+#if LIBUSBDOTNET
+ UsbError.Error(ErrorCode.MonoApiError, ret, "Refresh:GetDeviceList Failed", this);
+#else
+ System.Diagnostics.Debug.Print("libusb_get_device_list failed:{0} {1}",
+ (MonoUsbError) ret,
+ MonoUsbApi.StrError((MonoUsbError) ret));
+#endif
+ return ret;
+ }
+ int stopCount = ret;
+ foreach (MonoUsbProfileHandle deviceProfileHandle in monoUSBProfileListHandle)
+ {
+ newList.mList.Add(new MonoUsbProfile(deviceProfileHandle));
+ stopCount--;
+ if (stopCount <= 0) break;
+ }
+ syncWith(newList);
+ monoUSBProfileListHandle.Close();
+
+ return ret;
+ }
+ }
+
+ /// <summary>
+ /// Frees all unreferenced profiles contained in the list.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// <see cref="MonoUsbProfileHandle"/>s that are in-use are never closed until all reference(s) have gone
+ /// out-of-scope or specifically been closed with the <see cref="SafeHandle.Close"/> method.
+ /// </para>
+ /// </remarks>
+ public void Close()
+ {
+ lock (LockProfileList)
+ {
+ foreach (MonoUsbProfile profile in mList)
+ profile.Close();
+
+ mList.Clear();
+ }
+ }
+
+ /// <summary>
+ /// Usb device arrival/removal notification handler.
+ /// This event only reports when the <see cref="Refresh"/> method is called.
+ /// </summary>
+ /// <remarks>
+ /// <see cref="AddRemoveEvent"/> could be used for a crude form for receiving usb
+ /// device arrival/removal notification.
+ /// </remarks>
+ /// <example>
+ /// <code>
+ /// // Startup code
+ /// MonoUsbProfileList profileList = new MonoUsbProfileList();
+ /// profileList.AddRemoveEvent += OnDeviceAddRemove;
+ ///
+ /// // Device AddRemove event template
+ /// private void OnDeviceAddRemove(object sender, AddRemoveEventArgs addRemoveArgs)
+ /// {
+ /// // This method will only report when Refresh() is called.
+ /// }
+ ///
+ /// // Refresh profile list.
+ /// // Any devices added or removed since the last call to Refresh() will be returned
+ /// // in the OnDeviceAddRemove method.
+ /// profileList.Refresh();
+ /// </code>
+ /// </example>
+ public event EventHandler<AddRemoveEventArgs> AddRemoveEvent;
+
+ /// <summary>
+ /// Returns an enumerator that iterates through the collection.
+ /// </summary>
+ /// <returns>
+ /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
+ /// </returns>
+ /// <filterpriority>1</filterpriority>
+ public IEnumerator<MonoUsbProfile> GetEnumerator()
+ {
+ lock(LockProfileList)
+ return mList.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
+
+ /// <summary>
+ /// Returns the number of <see cref="MonoUsbProfile"/> instances in the list.
+ /// </summary>
+ public int Count
+ {
+ get
+ {
+ lock (LockProfileList)
+ return mList.Count;
+ }
+ }
+ /// <summary>
+ /// Gets a <see cref="List{T}"/> of <see cref="MonoUsbProfile"/> instances.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The <see cref="MonoUsbProfileList"/> uses an internal list that is locked when changes must be made.
+ /// The <see cref="GetList"/> method returns a copy of this list that can be searched and modified as needed by the user.
+ /// </para>
+ /// <para>
+ /// The returned generic <see cref="List{T}"/> contains many more functions for finding devices.
+ /// It may be desirable to use these members, such as <see cref="List{T}.FindAll"/> or <see cref="List{T}.ForEach"/> to find a <see cref="MonoUsbProfile"/> instead of iterating through the <see cref="MonoUsbProfileList"/> one-by-one.
+ /// </para>
+ /// </remarks>
+ /// <returns>A <see cref="List{T}"/> of <see cref="MonoUsbProfile"/> instances.</returns>
+ public List<MonoUsbProfile> GetList()
+ {
+ lock (LockProfileList)
+ return new List<MonoUsbProfile>(mList);
+ }
+
+ /// <summary>
+ /// Gets the <see cref="MonoUsbProfile"/> at the specfied index.
+ /// </summary>
+ /// <param name="index">The index of the <see cref="MonoUsbProfile"/> to retrieve.</param>
+ /// <returns>The <see cref="MonoUsbProfile"/> instance at the specified <paramref name="index"/>.</returns>
+ /// <exception cref="ArgumentOutOfRangeException">If index is invalid.</exception>
+ public MonoUsbProfile this[int index]
+ {
+ get
+ {
+ lock (LockProfileList)
+ return mList[index];
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Profile/MonoUsbProfileListHandle.cs b/LibWinUsb/MonoLibUsb/Profile/MonoUsbProfileListHandle.cs
new file mode 100644
index 00000000..e1c56c7a
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Profile/MonoUsbProfileListHandle.cs
@@ -0,0 +1,74 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using LibUsbDotNet.Main;
+
+namespace MonoLibUsb.Profile
+{
+ /// <summary>
+ /// Used to iterate through the <see cref="MonoUsbProfileHandle"/> collection contained in the <see cref="MonoUsbProfileListHandle"/>.
+ /// </summary>
+ /// <remarks>
+ /// <para>Wraps a device list handle into a <see cref="System.Runtime.ConstrainedExecution.CriticalFinalizerObject"/></para>
+ /// </remarks>
+ /// <seealso cref="MonoUsbProfileList"/>
+ public class MonoUsbProfileListHandle : SafeContextHandle, IEnumerable<MonoUsbProfileHandle>
+ {
+ private MonoUsbProfileListHandle()
+ : base(IntPtr.Zero) { }
+
+ internal MonoUsbProfileListHandle(IntPtr pHandleToOwn)
+ : base(pHandleToOwn) { }
+
+ #region IEnumerable<MonoUsbProfileHandle> Members
+
+ /// <summary>
+ /// Gets a forward-only device list enumerator.
+ /// </summary>
+ /// <returns>A profile handle enumerator used iterating through the <see cref="MonoUsbProfileHandle"/> classes.</returns>
+ public IEnumerator<MonoUsbProfileHandle> GetEnumerator() { return new MonoUsbProfileHandleEnumerator(this); }
+
+ IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
+
+ #endregion
+
+ /// <summary>
+ /// When overridden in a derived class, executes the code required to free the handle.
+ /// </summary>
+ /// <returns>
+ /// true if the handle is released successfully; otherwise, in the event of a catastrophic failure, false. In this case, it generates a ReleaseHandleFailed Managed Debugging Assistant.
+ /// </returns>
+ protected override bool ReleaseHandle()
+ {
+ if (!IsInvalid)
+ {
+ MonoUsbApi.FreeDeviceList(handle, 1);
+ //Console.WriteLine("FreeDeviceList:{0}", handle);
+ SetHandleAsInvalid();
+ }
+
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Profile/PollfdItem.cs b/LibWinUsb/MonoLibUsb/Profile/PollfdItem.cs
new file mode 100644
index 00000000..901c29d3
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Profile/PollfdItem.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace MonoLibUsb.Profile
+{
+ /// <summary>
+ /// File descriptor for polling. <a href="http://libusb.sourceforge.net/api-1.0/structlibusb__pollfd.html#_details">More..</a>
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential)]
+ public class PollfdItem
+ {
+ internal PollfdItem(IntPtr pPollfd)
+ {
+ Marshal.PtrToStructure(pPollfd, this);
+ }
+ /// <summary>
+ /// Numeric file descriptor.
+ /// </summary>
+ public readonly int fd;
+
+ /// <summary>
+ /// Event flags to poll for from poll.h.
+ /// </summary>
+ public readonly short events;
+ }
+}
diff --git a/LibWinUsb/MonoLibUsb/Transfer/Internal/libusb_control_setup.cs b/LibWinUsb/MonoLibUsb/Transfer/Internal/libusb_control_setup.cs
new file mode 100644
index 00000000..1066eb3f
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Transfer/Internal/libusb_control_setup.cs
@@ -0,0 +1,35 @@
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Main;
+
+namespace MonoLibUsb.Transfer.Internal
+{
+ [StructLayout(LayoutKind.Sequential)]
+ internal class libusb_control_setup
+ {
+
+ /** Request type. Bits 0:4 determine recipient, see
+ * \ref libusb_request_recipient. Bits 5:6 determine type, see
+ * \ref libusb_request_type. Bit 7 determines data transfer direction, see
+ * \ref libusb_endpoint_direction.
+ */
+ public readonly byte bmRequestType;
+
+ /** Request. If the type bits of bmRequestType are equal to
+ * \ref libusb_request_type::LIBUSB_REQUEST_TYPE_STANDARD
+ * "LIBUSB_REQUEST_TYPE_STANDARD" then this field refers to
+ * \ref libusb_standard_request. For other cases, use of this field is
+ * application-specific. */
+ public readonly byte bRequest;
+
+ /** Value. Varies according to request */
+ public readonly short wValue;
+
+ /** Index. Varies according to request, typically used to pass an index
+ * or offset */
+ public readonly short wIndex;
+
+ /** Number of bytes to transfer */
+ public readonly short wLength;
+
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Transfer/Internal/libusb_iso_packet_descriptor.cs b/LibWinUsb/MonoLibUsb/Transfer/Internal/libusb_iso_packet_descriptor.cs
new file mode 100644
index 00000000..58a12554
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Transfer/Internal/libusb_iso_packet_descriptor.cs
@@ -0,0 +1,29 @@
+using System.Runtime.InteropServices;
+
+namespace MonoLibUsb.Transfer.Internal
+{
+ /// <remarks>
+ /// This class is never instantiated in .NET. Instead it is used as a template by the <see cref="MonoUsbIsoPacket"/> class.
+ /// </remarks>
+ [StructLayout(LayoutKind.Sequential, Pack = MonoUsbApi.LIBUSB_PACK)]
+ internal class libusb_iso_packet_descriptor
+ {
+ /// <summary>
+ /// Length of data to request in this packet
+ /// </summary>
+ uint length;
+
+ /// <summary>
+ /// Amount of data that was actually transferred
+ /// </summary>
+ uint actual_length;
+
+ /// <summary>
+ /// Status code for this packet
+ /// </summary>
+ MonoUsbTansferStatus status;
+
+ private libusb_iso_packet_descriptor() { }
+
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Transfer/Internal/libusb_transfer.cs b/LibWinUsb/MonoLibUsb/Transfer/Internal/libusb_transfer.cs
new file mode 100644
index 00000000..49ddeeba
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Transfer/Internal/libusb_transfer.cs
@@ -0,0 +1,52 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+
+using LibUsbDotNet.Main;
+
+namespace MonoLibUsb.Transfer.Internal
+{
+ /// <remarks>
+ /// This class is never instantiated in .NET. Instead it is used as a template by the <see cref="MonoUsbTransfer"/> class.
+ /// </remarks>
+ [StructLayout(LayoutKind.Sequential, Pack = MonoUsbApi.LIBUSB_PACK)]
+ internal class libusb_transfer
+ {
+ IntPtr deviceHandle;
+ MonoUsbTransferFlags flags;
+ byte endpoint;
+ EndpointType type;
+ uint timeout;
+ MonoUsbTansferStatus status;
+ int length;
+ int actual_length;
+ IntPtr pCallbackFn;
+ IntPtr pUserData;
+ IntPtr pBuffer;
+ int num_iso_packets;
+ IntPtr iso_packets;
+
+ private libusb_transfer() { }
+
+ } ;
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Transfer/MonoUsbControlSetup.cs b/LibWinUsb/MonoLibUsb/Transfer/MonoUsbControlSetup.cs
new file mode 100644
index 00000000..d5c5438d
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Transfer/MonoUsbControlSetup.cs
@@ -0,0 +1,145 @@
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Main;
+using MonoLibUsb.Transfer.Internal;
+
+namespace MonoLibUsb.Transfer
+{
+ /// <summary>
+ /// Reads/writes a Libusb-1.0 control setup packet pointer. Control setup packets should be allocated with <see cref="MonoUsbControlSetupHandle"/>.
+ /// </summary>
+ /// <remarks>
+ /// <para>This class that reads and writes values directly from/to the setup packet <see cref="IntPtr"/> using <see cref="Marshal"/>.</para>
+ /// <note type="tip">This type is used for asynchronous control transfers only.</note>
+ /// </remarks>
+ /// <seealso cref="MonoUsbControlSetupHandle"/>
+ [StructLayout(LayoutKind.Sequential)]
+ public class MonoUsbControlSetup
+ {
+ /// <summary>
+ /// Size of a Libusb-1.0 setup packet.
+ /// </summary>
+ public static int SETUP_PACKET_SIZE = Marshal.SizeOf(typeof(libusb_control_setup));
+
+ private static readonly int OfsRequestType = Marshal.OffsetOf(typeof(libusb_control_setup), "bmRequestType").ToInt32();
+ private static readonly int OfsRequest = Marshal.OffsetOf(typeof(libusb_control_setup), "bRequest").ToInt32();
+ private static readonly int OfsValue = Marshal.OffsetOf(typeof(libusb_control_setup), "wValue").ToInt32();
+ private static readonly int OfsIndex = Marshal.OffsetOf(typeof(libusb_control_setup), "wIndex").ToInt32();
+ private static readonly int OfsLength = Marshal.OffsetOf(typeof(libusb_control_setup), "wLength").ToInt32();
+ private static readonly int OfsPtrData = SETUP_PACKET_SIZE;
+
+
+ private IntPtr handle;
+
+ /// <summary>
+ /// Creates a <see cref="MonoUsbControlSetup"/> structure for a control setup packet pointer.
+ /// </summary>
+ /// <remarks>
+ /// The <paramref name="pControlSetup"/> pointer must be a pointer in memory to a valid Libusb-1.0 <a href="http://libusb.sourceforge.net/api-1.0/structlibusb__control__setup.html">libusb__control__setup</a> that was allocated with <see cref="MonoUsbControlSetupHandle"/>.
+ /// </remarks>
+ /// <param name="pControlSetup">Pointer to the setup packet. This will usually be <see cref="MonoUsbTransfer.PtrBuffer">MonoUsbTransfer.PtrBuffer</see></param>
+ public MonoUsbControlSetup(IntPtr pControlSetup)
+ {
+ handle = pControlSetup;
+ }
+
+ /// <summary>
+ /// The request type.
+ /// </summary>
+ public byte RequestType
+ {
+ get { return Marshal.ReadByte(handle, OfsRequestType); }
+ set { Marshal.WriteByte(handle, OfsRequestType, value); }
+ }
+
+ /// <summary>
+ /// The request.
+ /// </summary>
+ public byte Request
+ {
+ get { return Marshal.ReadByte(handle, OfsRequest); }
+ set { Marshal.WriteByte(handle, OfsRequest, value); }
+ }
+ /// <summary>
+ /// The wValue.
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip">The get/set accessors automatically manage the little-endian to host-endian/host-endian to little-endian conversions using the <see cref="Helper.HostEndianToLE16"/> method.</note>
+ /// </remarks>
+ public short Value
+ {
+ get { return Helper.HostEndianToLE16(Marshal.ReadInt16(handle, OfsValue)); }
+ set { Marshal.WriteInt16(handle, OfsValue, Helper.HostEndianToLE16(value)); }
+
+ }
+ /// <summary>
+ /// The wIndex.
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip">The get/set accessors automatically manage the little-endian to host-endian/host-endian to little-endian conversions using the <see cref="Helper.HostEndianToLE16"/> method.</note>
+ /// </remarks>
+ public short Index
+ {
+ get { return Helper.HostEndianToLE16(Marshal.ReadInt16(handle, OfsIndex)); }
+ set { Marshal.WriteInt16(handle, OfsIndex, Helper.HostEndianToLE16(value)); }
+ }
+ /// <summary>
+ /// Number of bytes to transfer.
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip">The get/set accessors automatically manage the little-endian to host-endian/host-endian to little-endian conversions using the <see cref="Helper.HostEndianToLE16"/> method.</note>
+ /// </remarks>
+ public short Length
+ {
+ get { return Helper.HostEndianToLE16(Marshal.ReadInt16(handle, OfsLength)); }
+ set { Marshal.WriteInt16(handle, OfsLength, Helper.HostEndianToLE16(value)); }
+ }
+
+ /// <summary>
+ /// Gets a pointer to the control data buffer.
+ /// </summary>
+ /// <remarks>This is the <see cref="IntPtr"/> to the control data inside of the setup packet, not to the setup packet itself.</remarks>
+ public IntPtr PtrData
+ {
+ get
+ {
+ return new IntPtr(handle.ToInt64() + OfsPtrData);
+ }
+ }
+ /// <summary>
+ /// Copies data into <see cref="PtrData"/>.
+ /// </summary>
+ /// <param name="data">
+ /// <para>Data buffer to copy into <see cref="PtrData"/>for an output control transfer.</para>
+ /// This value can be:
+ /// <list type="bullet">
+ /// <item>An <see cref="Array"/> of bytes or other <a href="http://msdn.microsoft.com/en-us/library/75dwhxf7.aspx">blittable</a> types.</item>
+ /// <item>An already allocated, pinned <see cref="GCHandle"/>. In this case <see cref="GCHandle.AddrOfPinnedObject"/> is used for the buffer address.</item>
+ /// <item>An <see cref="IntPtr"/>.</item>
+ /// </list>
+ /// </param>
+ /// <param name="offset">The offset in <paramref name="data"/> to begin copying.</param>
+ /// <param name="length">Number of to copy.</param>
+ public void SetData(object data, int offset, int length)
+ {
+ PinnedHandle p = new PinnedHandle(data);
+ Byte[] temp = new byte[length];
+ Marshal.Copy(p.Handle, temp, offset, length);
+ p.Dispose();
+ Marshal.Copy(temp, 0, PtrData, length);
+ }
+
+ /// <summary>
+ /// Gets control data as bytes.
+ /// </summary>
+ /// <param name="transferLength">The number of bytes to copy out of <see cref="PtrData"/>. This will usually come from <see cref="MonoUsbTransfer.ActualLength">MonoUsbTransfer.ActualLength</see>.</param>
+ /// <returns>A new byte array of control data.</returns>
+ public Byte[] GetData(int transferLength)
+ {
+ byte[] data = new byte[transferLength];
+ Marshal.Copy(PtrData,data,0,data.Length);
+ return data;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Transfer/MonoUsbControlSetupHandle.cs b/LibWinUsb/MonoLibUsb/Transfer/MonoUsbControlSetupHandle.cs
new file mode 100644
index 00000000..9f72127c
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Transfer/MonoUsbControlSetupHandle.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Main;
+
+namespace MonoLibUsb.Transfer
+{
+ /// <summary>
+ /// Allocates memory and fills an asynchronous control setup packet.
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip">This type is used for asynchronous control transfers only.</note>
+ /// </remarks>
+ /// <seealso cref="MonoUsbControlSetup"/>
+ public class MonoUsbControlSetupHandle:SafeContextHandle
+ {
+ private MonoUsbControlSetup mSetupPacket;
+ /// <summary>
+ /// Allocates memory and sets up a control setup packet. Copies control data into the control data buffer
+ /// </summary>
+ /// <remarks>
+ /// <para>This constructor is used when <paramref name="requestType"/> has the <see cref="UsbCtrlFlags.Direction_In"/> flag and this request will contain control data (more than just the setup packet).</para>
+ /// <para>Allocates <see cref="MonoUsbControlSetup.SETUP_PACKET_SIZE"/> + <paramref name="data"/>.Length for the setup packet. The setup packet is stored first then the control data.</para>
+ /// <para>The <paramref name="data"/> array is copied into the setup packet starting at <see cref="MonoUsbControlSetup.SETUP_PACKET_SIZE"/>.</para>
+ /// <note title="Libusb-1.0 API Note:" type="cpp">
+ /// This contructor is similar to
+ /// <a href="http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga5447311149ec2bd954b5f1a640a8e231">libusb_fill_control_setup()</a>.
+ /// </note>
+ /// </remarks>
+ /// <param name="requestType">The request type field for the setup packet.</param>
+ /// <param name="request">The request field for the setup packet.</param>
+ /// <param name="value">The value field for the setup packet</param>
+ /// <param name="index">The index field for the setup packet.</param>
+ /// <param name="data">The control data buffer to copy into the setup packet.</param>
+ /// <param name="length">Size of <paramref name="data"/> in bytes. This value is also used for the wLength field of the setup packet.</param>
+ public MonoUsbControlSetupHandle(byte requestType, byte request, short value, short index, object data, int length)
+ : this(requestType, request, value, index, (short)(ushort)length)
+ {
+ if (data != null)
+ mSetupPacket.SetData(data, 0, length);
+ }
+
+ /// <summary>
+ /// Allocates memory and sets up a control setup packet.
+ /// </summary>
+ /// <remarks>
+ /// <para>This constructor is used when:
+ /// <list type="bullet">
+ /// <item><paramref name="requestType"/> has the <see cref="UsbCtrlFlags.Direction_In"/> flag and this request will not contain extra data (just the setup packet).</item>
+ /// <item><paramref name="requestType"/> does not have the <see cref="UsbCtrlFlags.Direction_In"/> flag.</item>
+ /// </list>
+ /// </para>
+ /// <note title="Libusb-1.0 API Note:" type="cpp">
+ /// This contructor is similar to
+ /// <a href="http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga5447311149ec2bd954b5f1a640a8e231">libusb_fill_control_setup()</a>.
+ /// </note>
+ /// <para>Allocates <see cref="MonoUsbControlSetup.SETUP_PACKET_SIZE"/> + <paramref name="length"/> for the setup packet. The setup packet is stored first then the control data.</para>
+ /// </remarks>
+ /// <param name="requestType">The request type field for the setup packet.</param>
+ /// <param name="request">The request field for the setup packet.</param>
+ /// <param name="value">The value field for the setup packet</param>
+ /// <param name="index">The index field for the setup packet.</param>
+ /// <param name="length">The length to allocate for the data portion of the setup packet.</param>
+ public MonoUsbControlSetupHandle(byte requestType, byte request, short value, short index, short length)
+ :base(IntPtr.Zero,true)
+ {
+ ushort wlength = (ushort) length;
+ int packetSize;
+ if (wlength > 0)
+ packetSize = MonoUsbControlSetup.SETUP_PACKET_SIZE + wlength + (IntPtr.Size - (wlength % IntPtr.Size));
+ else
+ packetSize = MonoUsbControlSetup.SETUP_PACKET_SIZE;
+
+ IntPtr pConfigMem = Marshal.AllocHGlobal(packetSize);
+ if (pConfigMem == IntPtr.Zero) throw new OutOfMemoryException(String.Format("Marshal.AllocHGlobal failed allocating {0} bytes", packetSize));
+ SetHandle(pConfigMem);
+
+ mSetupPacket = new MonoUsbControlSetup(pConfigMem);
+
+ mSetupPacket.RequestType = requestType;
+ mSetupPacket.Request = request;
+ mSetupPacket.Value = value;
+ mSetupPacket.Index = index;
+ mSetupPacket.Length = (short) wlength;
+
+ }
+
+ /// <summary>
+ /// Returns the <see cref="MonoUsbControlSetup"/> for this handle.
+ /// </summary>
+ public MonoUsbControlSetup ControlSetup
+ {
+ get
+ {
+ return mSetupPacket;
+ }
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <returns></returns>
+ protected override bool ReleaseHandle()
+ {
+ if (!IsInvalid)
+ {
+ Marshal.FreeHGlobal(handle);
+ SetHandleAsInvalid();
+ Debug.Print(GetType().Name + " : ReleaseHandle");
+ }
+ return true;
+ }
+ }
+}
diff --git a/LibWinUsb/MonoLibUsb/Transfer/MonoUsbIsoPacket.cs b/LibWinUsb/MonoLibUsb/Transfer/MonoUsbIsoPacket.cs
new file mode 100644
index 00000000..ff2e8774
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Transfer/MonoUsbIsoPacket.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Runtime.InteropServices;
+using MonoLibUsb.Transfer.Internal;
+
+namespace MonoLibUsb.Transfer
+{
+ /// <summary>
+ /// Wraps an iso packet structure
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential)]
+ public class MonoUsbIsoPacket
+ {
+ private static readonly int OfsActualLength = Marshal.OffsetOf(typeof(libusb_iso_packet_descriptor), "actual_length").ToInt32();
+ private static readonly int OfsLength = Marshal.OffsetOf(typeof(libusb_iso_packet_descriptor), "length").ToInt32();
+ private static readonly int OfsStatus = Marshal.OffsetOf(typeof(libusb_iso_packet_descriptor), "status").ToInt32();
+
+ private IntPtr mpMonoUsbIsoPacket = IntPtr.Zero;
+
+ /// <summary>
+ /// Creates a structure that wraps an iso packet.
+ /// </summary>
+ /// <param name="isoPacketPtr">The pointer to the iso packet to wrap.</param>
+ public MonoUsbIsoPacket(IntPtr isoPacketPtr) { mpMonoUsbIsoPacket = isoPacketPtr; }
+
+ /// <summary>
+ /// Returns the location in memory of this iso packet.
+ /// </summary>
+ public IntPtr PtrIsoPacket
+ {
+ get { return mpMonoUsbIsoPacket; }
+ }
+ /// <summary>
+ /// Amount of data that was actually transferred.
+ /// </summary>
+ public int ActualLength
+ {
+ get { return Marshal.ReadInt32(mpMonoUsbIsoPacket, OfsActualLength); }
+ set { Marshal.WriteInt32(mpMonoUsbIsoPacket, OfsActualLength, value); }
+ }
+ /// <summary>
+ /// Length of data to request in this packet.
+ /// </summary>
+ public int Length
+ {
+ get { return Marshal.ReadInt32(mpMonoUsbIsoPacket, OfsLength); }
+ set { Marshal.WriteInt32(mpMonoUsbIsoPacket, OfsLength, value); }
+ }
+ /// <summary>
+ /// Status code for this packet.
+ /// </summary>
+ public MonoUsbTansferStatus Status
+ {
+ get { return (MonoUsbTansferStatus)Marshal.ReadInt32(mpMonoUsbIsoPacket, OfsStatus); }
+ set { Marshal.WriteInt32(mpMonoUsbIsoPacket, OfsStatus, (int)value); }
+ }
+
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Transfer/MonoUsbTansferStatus.cs b/LibWinUsb/MonoLibUsb/Transfer/MonoUsbTansferStatus.cs
new file mode 100644
index 00000000..36e35136
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Transfer/MonoUsbTansferStatus.cs
@@ -0,0 +1,65 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+
+namespace MonoLibUsb.Transfer
+{
+ /// <summary>
+ /// Transfer status codes.
+ /// </summary>
+ public enum MonoUsbTansferStatus
+ {
+ /// <summary>
+ /// Transfer completed without error. Note that this does not indicate that the entire amount of requested data was transferred.
+ /// </summary>
+ TransferCompleted,
+
+ /// <summary>
+ /// Transfer failed
+ /// </summary>
+ TransferError,
+
+ /// <summary>
+ /// Transfer timed out
+ /// </summary>
+ TransferTimedOut,
+
+ /// <summary>
+ /// Transfer was cancelled
+ /// </summary>
+ TransferCancelled,
+
+ /// <summary>
+ /// For bulk/interrupt endpoints: halt condition detected (endpoint stalled). For control endpoints: control request not supported.
+ /// </summary>
+ TransferStall,
+
+ /// <summary>
+ /// Device was disconnected
+ /// </summary>
+ TransferNoDevice,
+
+ /// <summary>
+ /// Device sent more data than requested
+ /// </summary>
+ TransferOverflow
+ } ;
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Transfer/MonoUsbTransfer.cs b/LibWinUsb/MonoLibUsb/Transfer/MonoUsbTransfer.cs
new file mode 100644
index 00000000..df555406
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Transfer/MonoUsbTransfer.cs
@@ -0,0 +1,519 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+
+using LibUsbDotNet.Main;
+using MonoLibUsb.Transfer.Internal;
+
+namespace MonoLibUsb.Transfer
+{
+ /// <summary>
+ /// Reads/writes a Libusb-1.0 transfer pointer. Transfer should be allocated with <see cref="Alloc"/>.
+ /// </summary>
+ /// <remarks>
+ /// The user populates this structure and then submits it in order to request a transfer.
+ /// After the transfer has completed, the library populates the transfer with the results
+ /// and passes it back to the user.
+ /// <note title="Libusb-1.0 API Note:" type="cpp">
+ /// The <see cref="MonoUsbTransfer"/> structure is roughly equivalent to
+ /// the <a href="http://libusb.sourceforge.net/api-1.0/structlibusb__transfer.html">struct libusb_transfer</a>.
+ /// </note>
+ /// </remarks>
+ [StructLayout(LayoutKind.Sequential)]
+ public struct MonoUsbTransfer
+ {
+ private static readonly int OfsActualLength = Marshal.OffsetOf(typeof (libusb_transfer), "actual_length").ToInt32();
+ private static readonly int OfsEndpoint = Marshal.OffsetOf(typeof (libusb_transfer), "endpoint").ToInt32();
+ private static readonly int OfsFlags = Marshal.OffsetOf(typeof (libusb_transfer), "flags").ToInt32();
+ private static readonly int OfsLength = Marshal.OffsetOf(typeof (libusb_transfer), "length").ToInt32();
+ private static readonly int OfsPtrBuffer = Marshal.OffsetOf(typeof (libusb_transfer), "pBuffer").ToInt32();
+ private static readonly int OfsPtrCallbackFn = Marshal.OffsetOf(typeof (libusb_transfer), "pCallbackFn").ToInt32();
+ private static readonly int OfsPtrDeviceHandle = Marshal.OffsetOf(typeof (libusb_transfer), "deviceHandle").ToInt32();
+ private static readonly int OfsPtrUserData = Marshal.OffsetOf(typeof (libusb_transfer), "pUserData").ToInt32();
+ private static readonly int OfsStatus = Marshal.OffsetOf(typeof (libusb_transfer), "status").ToInt32();
+ private static readonly int OfsTimeout = Marshal.OffsetOf(typeof (libusb_transfer), "timeout").ToInt32();
+ private static readonly int OfsType = Marshal.OffsetOf(typeof (libusb_transfer), "type").ToInt32();
+ private static readonly int OfsNumIsoPackets = Marshal.OffsetOf(typeof (libusb_transfer), "num_iso_packets").ToInt32();
+ private static readonly int OfsIsoPackets = Marshal.OffsetOf(typeof (libusb_transfer), "iso_packets").ToInt32();
+
+ private IntPtr handle;
+ /// <summary>
+ /// Allocate a libusb transfer with a specified number of isochronous packet descriptors
+ /// </summary>
+ /// <remarks>
+ /// <para>The transfer is pre-initialized for you. When the new transfer is no longer needed, it should be freed with <see cref="Free"/>.</para>
+ /// <para>Transfers intended for non-isochronous endpoints (e.g. control, bulk, interrupt) should specify an iso_packets count of zero.</para>
+ /// <para>For transfers intended for isochronous endpoints, specify an appropriate number of packet descriptors to be allocated as part of the transfer. The returned transfer is not specially initialized for isochronous I/O; you are still required to set the <see cref="MonoUsbTransfer.NumIsoPackets"/> and <see cref="MonoUsbTransfer.Type"/> fields accordingly.</para>
+ /// <para>It is safe to allocate a transfer with some isochronous packets and then use it on a non-isochronous endpoint. If you do this, ensure that at time of submission, <see cref="MonoUsbTransfer.NumIsoPackets"/> is 0 and that type is set appropriately.</para>
+ /// </remarks>
+ /// <param name="numIsoPackets">number of isochronous packet descriptors to allocate.</param>
+ public MonoUsbTransfer(int numIsoPackets)
+ {
+ handle = MonoUsbApi.AllocTransfer(numIsoPackets);
+ }
+
+ /// <summary>
+ /// Creates a new wrapper for transfers allocated by <see cref="MonoUsbApi.AllocTransfer"/>,
+ /// </summary>
+ /// <param name="pTransfer">The pointer to the transfer that was previously allocated with<see cref="MonoUsbApi.AllocTransfer"/>. </param>
+ internal MonoUsbTransfer(IntPtr pTransfer)
+ {
+ handle = pTransfer;
+ }
+
+ /// <summary>
+ /// Gets the buffer data pointer.
+ /// </summary>
+ public IntPtr PtrBuffer
+ {
+ get { return Marshal.ReadIntPtr(handle, OfsPtrBuffer); }
+ set { Marshal.WriteIntPtr(handle, OfsPtrBuffer, value); }
+ }
+
+ /// <summary>
+ /// User context data to pass to the callback function.
+ /// </summary>
+ public IntPtr PtrUserData
+ {
+ get { return Marshal.ReadIntPtr(handle, OfsPtrUserData); }
+ set { Marshal.WriteIntPtr(handle, OfsPtrUserData, value); }
+ }
+
+ /// <summary>
+ /// Callback function pointer.
+ /// </summary>
+ /// <remarks>
+ /// The callback function must be declared as a <see cref="MonoUsbTransferDelegate"/>.
+ /// </remarks>
+ public IntPtr PtrCallbackFn
+ {
+ get { return Marshal.ReadIntPtr(handle, OfsPtrCallbackFn); }
+ set { Marshal.WriteIntPtr(handle, OfsPtrCallbackFn, value); }
+ }
+
+ /// <summary>
+ /// Actual length of data that was transferred.
+ /// </summary>
+ public int ActualLength
+ {
+ get { return Marshal.ReadInt32(handle, OfsActualLength); }
+ set { Marshal.WriteInt32(handle, OfsActualLength, value); }
+ }
+
+ /// <summary>
+ /// Length of the data buffer.
+ /// </summary>
+ public int Length
+ {
+ get { return Marshal.ReadInt32(handle, OfsLength); }
+ set { Marshal.WriteInt32(handle, OfsLength, value); }
+ }
+
+ /// <summary>
+ /// The status of the transfer.
+ /// </summary>
+ public MonoUsbTansferStatus Status
+ {
+ get { return (MonoUsbTansferStatus)Marshal.ReadInt32(handle, OfsStatus); }
+ set { Marshal.WriteInt32(handle, OfsStatus, (int)value); }
+ }
+
+ /// <summary>
+ /// Timeout for this transfer in millseconds.
+ /// </summary>
+ public int Timeout
+ {
+ get { return Marshal.ReadInt32(handle, OfsTimeout); }
+ set { Marshal.WriteInt32(handle, OfsTimeout, value); }
+ }
+
+ /// <summary>
+ /// Type of the endpoint.
+ /// </summary>
+ public EndpointType Type
+ {
+ get { return (EndpointType)Marshal.ReadByte(handle, OfsType); }
+ set { Marshal.WriteByte(handle, OfsType, (byte)value); }
+ }
+
+ /// <summary>
+ /// Enpoint address.
+ /// </summary>
+ public byte Endpoint
+ {
+ get { return Marshal.ReadByte(handle, OfsEndpoint); }
+ set { Marshal.WriteByte(handle, OfsEndpoint, value); }
+ }
+
+ /// <summary>
+ /// A bitwise OR combination of <see cref="MonoUsbTransferFlags"/>.
+ /// </summary>
+ public MonoUsbTransferFlags Flags
+ {
+ get { return (MonoUsbTransferFlags)Marshal.ReadByte(handle, OfsFlags); }
+ set { Marshal.WriteByte(handle, OfsFlags, (byte)value); }
+ }
+
+ /// <summary>
+ /// Raw device handle pointer.
+ /// </summary>
+ public IntPtr PtrDeviceHandle
+ {
+ get { return Marshal.ReadIntPtr(handle, OfsPtrDeviceHandle); }
+ set { Marshal.WriteIntPtr(handle, OfsPtrDeviceHandle, value); }
+ }
+
+ /// <summary>
+ /// Number of isochronous packets.
+ /// </summary>
+ public int NumIsoPackets
+ {
+ get { return Marshal.ReadInt32(handle, OfsNumIsoPackets); }
+ set { Marshal.WriteInt32(handle, OfsNumIsoPackets, value); }
+ }
+
+ /// <summary>
+ /// Frees this transfer.
+ /// </summary>
+ ///<remarks>
+ /// <note title="Libusb-1.0 API Note:" type="cpp">
+ /// <see cref="Free"/> is roughly equivalent to
+ /// <a href="http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga6ab8b2cff4de9091298a06b2f4b86cd6">libusb_free_transfer()</a>.
+ /// </note>
+ /// <note type="warning">
+ /// Calling <see cref="Free"/> on a transfer that has already been freed will result in a double free.
+ /// </note>
+ /// </remarks>
+ public void Free()
+ {
+ if (handle!=IntPtr.Zero)
+ {
+ MonoUsbApi.FreeTransfer(handle);
+ handle = IntPtr.Zero;
+ }
+ }
+
+ /// <summary>
+ /// Gets a unqiue name for this transfer.
+ /// </summary>
+ /// <returns>A unqiue name for this transfer.</returns>
+ public String UniqueName()
+ {
+ String guidString = String.Format("_-EP[{0}]EP-_", handle);
+ return guidString;
+ }
+
+ /// <summary>
+ /// Gets a <see cref="MonoUsbIsoPacket"/> that represents the specified iso packet descriptor.
+ /// </summary>
+ /// <param name="packetNumber">The iso packet descriptor to return.</param>
+ /// <returns>The <see cref="MonoUsbIsoPacket"/> that represents <paramref name="packetNumber"/>.</returns>
+ public MonoUsbIsoPacket IsoPacket(int packetNumber)
+ {
+ if (packetNumber > NumIsoPackets) throw new ArgumentOutOfRangeException("packetNumber");
+ IntPtr pIsoPacket =
+ new IntPtr(handle.ToInt64() + OfsIsoPackets + (packetNumber * Marshal.SizeOf(typeof(libusb_iso_packet_descriptor))));
+
+ return new MonoUsbIsoPacket(pIsoPacket);
+ }
+
+ /// <summary>
+ /// True if the transfer is allocated.
+ /// </summary>
+ public bool IsInvalid
+ {
+ get
+ {
+ return (handle == IntPtr.Zero);
+ }
+ }
+ /// <summary>
+ /// Cancels this transfer.
+ /// </summary>
+ /// <remarks>
+ /// <note title="Libusb-1.0 API Note:" type="cpp">
+ /// <see cref="Cancel"/> is roughly equivalent to
+ /// <a href="http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga685eb7731f9a0593f75beb99727bbe54">libusb_cancel_transfer()</a>.
+ /// </note>
+ /// </remarks>
+ /// <returns><see cref="MonoUsbError.Success"/> if the cancel succeeds, otherwise one of the other <see cref="MonoUsbError"/> codes.</returns>
+ public MonoUsbError Cancel()
+ {
+ if (IsInvalid) return MonoUsbError.ErrorNoMem;
+
+ return (MonoUsbError) MonoUsbApi.CancelTransfer(handle);
+ }
+ /// <summary>
+ /// Helper function to populate the required <see cref="MonoUsbTransfer"/> properties for a bulk transfer.
+ /// </summary>
+ /// <remarks>
+ /// <note title="Libusb-1.0 API Note:" type="cpp">
+ /// <see cref="FillBulk"/> is similar to
+ /// <a href="http://libusb.sourceforge.net/api-1.0/group__asyncio.html#gad4ddb1a5c6c7fefc979a44d7300b95d7">libusb_fill_bulk_transfer()</a>.
+ /// </note>
+ /// </remarks>
+ /// <param name="devHandle">handle of the device that will handle the transfer</param>
+ /// <param name="endpoint">address of the endpoint where this transfer will be sent</param>
+ /// <param name="buffer">data buffer</param>
+ /// <param name="length">length of data buffer</param>
+ /// <param name="callback">callback function to be invoked on transfer completion</param>
+ /// <param name="userData">user data to pass to callback function</param>
+ /// <param name="timeout">timeout for the transfer in milliseconds</param>
+ public void FillBulk(MonoUsbDeviceHandle devHandle,
+ byte endpoint,
+ IntPtr buffer,
+ int length,
+ Delegate callback,
+ IntPtr userData,
+ int timeout)
+ {
+ PtrDeviceHandle = devHandle.DangerousGetHandle();
+ Endpoint = endpoint;
+ PtrBuffer = buffer;
+ Length = length;
+ PtrCallbackFn = Marshal.GetFunctionPointerForDelegate(callback);
+ PtrUserData = userData;
+ Timeout = timeout;
+ Type = EndpointType.Bulk;
+ Flags = MonoUsbTransferFlags.None;
+ NumIsoPackets = 0;
+ ActualLength = 0;
+
+
+ }
+
+ /// <summary>
+ /// Helper function to populate the required <see cref="MonoUsbTransfer"/> properties for an interrupt transfer.
+ /// </summary>
+ /// <remarks>
+ /// <note title="Libusb-1.0 API Note:" type="cpp">
+ /// <see cref="FillInterrupt"/> is roughly equivalent to
+ /// <a href="http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga90f53cea1124a7566df1aa1202b77510">libusb_fill_interrupt_transfer()</a>.
+ /// </note>
+ /// </remarks>
+ /// <param name="devHandle">handle of the device that will handle the transfer</param>
+ /// <param name="endpoint">address of the endpoint where this transfer will be sent</param>
+ /// <param name="buffer">data buffer</param>
+ /// <param name="length">length of data buffer</param>
+ /// <param name="callback">callback function to be invoked on transfer completion</param>
+ /// <param name="userData">user data to pass to callback function</param>
+ /// <param name="timeout">timeout for the transfer in milliseconds</param>
+ public void FillInterrupt(MonoUsbDeviceHandle devHandle,
+ byte endpoint,
+ IntPtr buffer,
+ int length,
+ Delegate callback,
+ IntPtr userData,
+ int timeout)
+ {
+ PtrDeviceHandle = devHandle.DangerousGetHandle();
+ Endpoint = endpoint;
+ PtrBuffer = buffer;
+ Length = length;
+ PtrCallbackFn = Marshal.GetFunctionPointerForDelegate(callback);
+ PtrUserData = userData;
+ Timeout = timeout;
+ Type = EndpointType.Interrupt;
+ Flags = MonoUsbTransferFlags.None;
+ }
+
+ /// <summary>
+ /// Helper function to populate the required <see cref="MonoUsbTransfer"/> properties for an isochronous transfer.
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip">
+ /// <para>Isochronous transfers are not supported on windows.</para>
+ /// </note>
+ /// <note title="Libusb-1.0 API Note:" type="cpp">
+ /// <see cref="FillIsochronous"/> is similar to
+ /// <a href="http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga30fdce8c461e851f0aa4c851014e1aa7">libusb_fill_iso_transfer()</a>.
+ /// </note>
+ /// </remarks>
+ /// <param name="devHandle">handle of the device that will handle the transfer</param>
+ /// <param name="endpoint">address of the endpoint where this transfer will be sent</param>
+ /// <param name="buffer">data buffer</param>
+ /// <param name="length">length of data buffer</param>
+ /// <param name="numIsoPackets">the number of isochronous packets</param>
+ /// <param name="callback">callback function to be invoked on transfer completion</param>
+ /// <param name="userData">user data to pass to callback function</param>
+ /// <param name="timeout">timeout for the transfer in milliseconds</param>
+ public void FillIsochronous(MonoUsbDeviceHandle devHandle,
+ byte endpoint,
+ IntPtr buffer,
+ int length,int numIsoPackets,
+ Delegate callback,
+ IntPtr userData,
+ int timeout)
+ {
+ PtrDeviceHandle = devHandle.DangerousGetHandle();
+ Endpoint = endpoint;
+ PtrBuffer = buffer;
+ Length = length;
+ PtrCallbackFn = Marshal.GetFunctionPointerForDelegate(callback);
+ PtrUserData = userData;
+ Timeout = timeout;
+ Type = EndpointType.Isochronous;
+ Flags = MonoUsbTransferFlags.None;
+ NumIsoPackets = numIsoPackets;
+ }
+
+ /// <summary>
+ /// Convenience function to locate the position of an isochronous packet within the buffer of an isochronous transfer.
+ /// </summary>
+ /// <remarks>
+ /// <para>This is a thorough function which loops through all preceding packets, accumulating their lengths to find the position of the specified packet. Typically you will assign equal lengths to each packet in the transfer, and hence the above method is sub-optimal. You may wish to use <see cref="GetIsoPacketBufferSimple"/> instead.</para>
+ /// <note title="Libusb-1.0 API Note:" type="cpp">
+ /// <see cref="GetIsoPacketBuffer"/> is roughly equivalent to
+ /// <a href="http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga7f6ea0eb35a216d19d984977e454a7b3">libusb_get_iso_packet_buffer()</a>.
+ /// </note>
+ /// </remarks>
+ /// <param name="packet">The packet to return the address of.</param>
+ /// <returns>the base address of the packet buffer inside the transfer buffer.</returns>
+ /// <exception cref="ArgumentOutOfRangeException">This exception is thrown if the packet requested is >= <see cref="NumIsoPackets"/>.</exception>
+ public IntPtr GetIsoPacketBuffer(int packet)
+ {
+ if (packet >= NumIsoPackets) throw new ArgumentOutOfRangeException("packet", "GetIsoPacketBuffer: packet must be < NumIsoPackets");
+ long offset = PtrBuffer.ToInt64();
+
+ for (int i = 0; i < packet; i++)
+ offset += IsoPacket(i).Length;
+
+ return new IntPtr(offset);
+ }
+
+ /// <summary>
+ /// Convenience function to locate the position of an isochronous packet within the buffer of an isochronous transfer, for transfers where each packet is of identical size.
+ /// </summary>
+ /// <remarks>
+ /// <para>This function relies on the assumption that every packet within the transfer is of identical size to the first packet. Calculating the location of the packet buffer is then just a simple calculation: buffer + (packet_size * packet)</para>
+ /// <para>Do not use this function on transfers other than those that have identical packet lengths for each packet.</para>
+ /// <note title="Libusb-1.0 API Note:" type="cpp">
+ /// <see cref="GetIsoPacketBufferSimple"/> is roughly equivalent to
+ /// <a href="http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga3df9a28c4f5c8f1850181ddb5efd12fd">libusb_get_iso_packet_buffer_simple()</a>.
+ /// </note>
+ /// </remarks>
+ /// <param name="packet">The packet to return the address of.</param>
+ /// <returns>the base address of the packet buffer inside the transfer buffer.</returns>
+ /// <exception cref="ArgumentOutOfRangeException">This exception is thrown if the packet requested is >= <see cref="NumIsoPackets"/>.</exception>
+ public IntPtr GetIsoPacketBufferSimple(int packet)
+ {
+ if (packet >= NumIsoPackets) throw new ArgumentOutOfRangeException("packet", "GetIsoPacketBufferSimple: packet must be < NumIsoPackets");
+
+ return new IntPtr((PtrBuffer.ToInt64() + (IsoPacket(0).Length * packet)));
+
+ }
+
+ /// <summary>
+ /// Convenience function to set the length of all packets in an isochronous transfer, based on the num_iso_packets field in the transfer structure.
+ /// </summary>
+ /// <remarks>
+ /// <note title="Libusb-1.0 API Note:" type="cpp">
+ /// <see cref="SetIsoPacketLengths"/> is roughly equivalent to
+ /// <a href="http://libusb.sourceforge.net/api-1.0/group__asyncio.html#gacbdecd6f50093f0c1d0e72ee35ace274">libusb_set_iso_packet_lengths()</a>.
+ /// </note>
+ /// </remarks>
+ /// <param name="length">The length to set in each isochronous packet descriptor.</param>
+ public void SetIsoPacketLengths(int length)
+ {
+ int packetCount = NumIsoPackets;
+ for (int i = 0; i < packetCount; i++)
+ IsoPacket(i).Length = length;
+
+ }
+ /// <summary>
+ /// Submits this transfer.
+ /// </summary>
+ /// <remarks>
+ /// This functions submits the USB transfer and return immediately.
+ /// <note>
+ /// <see cref="Submit"/> is roughly equivalent to
+ /// <a href="http://libusb.sourceforge.net/api-1.0/group__asyncio.html#gabb0932601f2c7dad2fee4b27962848ce">libusb_submit_transfer()</a>.
+ /// </note>
+ /// </remarks>
+ /// <returns>
+ /// <see cref="MonoUsbError.Success"/> if the submit succeeds,
+ /// otherwise one of the other <see cref="MonoUsbError"/> codes.
+ /// </returns>
+ public MonoUsbError Submit()
+ {
+ if (IsInvalid) return MonoUsbError.ErrorNoMem;
+ return (MonoUsbError)MonoUsbApi.SubmitTransfer(handle);
+ }
+
+ /// <summary>
+ /// Allocate a libusb transfer with a specified number of isochronous packet descriptors
+ /// </summary>
+ /// <remarks>
+ /// <para>The returned transfer is pre-initialized for you. When the new transfer is no longer needed, it should be freed with <see cref="Free"/>.</para>
+ /// <para>Transfers intended for non-isochronous endpoints (e.g. control, bulk, interrupt) should specify an iso_packets count of zero.</para>
+ /// <para>For transfers intended for isochronous endpoints, specify an appropriate number of packet descriptors to be allocated as part of the transfer. The returned transfer is not specially initialized for isochronous I/O; you are still required to set the <see cref="MonoUsbTransfer.NumIsoPackets"/> and <see cref="MonoUsbTransfer.Type"/> fields accordingly.</para>
+ /// <para>It is safe to allocate a transfer with some isochronous packets and then use it on a non-isochronous endpoint. If you do this, ensure that at time of submission, <see cref="MonoUsbTransfer.NumIsoPackets"/> is 0 and that type is set appropriately.</para>
+ /// <note title="Libusb-1.0 API Note:" type="cpp">
+ /// <see cref="Alloc"/> is roughly equivalent to
+ /// <a href="http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga13cc69ea40c702181c430c950121c000">libusb_alloc_transfer()</a>.
+ /// </note>
+ /// </remarks>
+ /// <param name="numIsoPackets">number of isochronous packet descriptors to allocate.</param>
+ /// <returns>A newly allocated <see cref="MonoUsbTransfer"/>.</returns>
+ /// <exception cref="OutOfMemoryException">If the transfer was not allocated.</exception>
+ public static MonoUsbTransfer Alloc(int numIsoPackets)
+ {
+ IntPtr p = MonoUsbApi.AllocTransfer(numIsoPackets);
+ if (p == IntPtr.Zero) throw new OutOfMemoryException("AllocTransfer");
+ return new MonoUsbTransfer(p);
+ }
+
+ /// <summary>
+ /// Helper function to populate the required <see cref="MonoUsbTransfer"/> properties for a control transfer.
+ /// </summary>
+ /// <remarks>
+ /// <note type="tip">
+ /// <para>Isochronous transfers are not supported on windows.</para>
+ /// </note>
+ /// <note title="Libusb-1.0 API Note:" type="cpp">
+ /// <see cref="FillControl"/> is similar to
+ /// <a href="http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga3a8513ed87229fe2c9771ef0bf17206e">libusb_fill_control_transfer()</a>.
+ /// </note>
+ /// </remarks>
+ /// <param name="devHandle">handle of the device that will handle the transfer</param>
+ /// <param name="controlSetupHandle">the setup packet/control data to transfer.</param>
+ /// <param name="callback">callback function to be invoked on transfer completion</param>
+ /// <param name="userData">user data to pass to callback function</param>
+ /// <param name="timeout">timeout for the transfer in milliseconds</param>
+ public void FillControl(MonoUsbDeviceHandle devHandle, MonoUsbControlSetupHandle controlSetupHandle, Delegate callback, IntPtr userData, int timeout)
+ {
+ PtrDeviceHandle = devHandle.DangerousGetHandle();
+ Endpoint = 0;
+ PtrCallbackFn = Marshal.GetFunctionPointerForDelegate(callback);
+ PtrUserData = userData;
+ Timeout = timeout;
+ Type = EndpointType.Control;
+ Flags = MonoUsbTransferFlags.None;
+
+ IntPtr pSetupPacket = controlSetupHandle.DangerousGetHandle();
+ PtrBuffer = pSetupPacket;
+ MonoUsbControlSetup w = new MonoUsbControlSetup(pSetupPacket);
+ Length = MonoUsbControlSetup.SETUP_PACKET_SIZE + w.Length;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Transfer/MonoUsbTransferContext.cs b/LibWinUsb/MonoLibUsb/Transfer/MonoUsbTransferContext.cs
new file mode 100644
index 00000000..c8b466bf
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Transfer/MonoUsbTransferContext.cs
@@ -0,0 +1,232 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+using LibUsbDotNet.Main;
+using MonoLibUsb;
+using MonoLibUsb.Transfer;
+
+namespace LibUsbDotNet.LudnMonoLibUsb.Internal
+{
+ internal class MonoUsbTransferContext : UsbTransfer, IDisposable
+ {
+ private bool mOwnsTransfer;
+
+ private static readonly MonoUsbTransferDelegate mMonoUsbTransferCallbackDelegate = TransferCallback;
+ private GCHandle mCompleteEventHandle;
+ private MonoUsbTransfer mTransfer;
+
+ public MonoUsbTransferContext(UsbEndpointBase endpointBase)
+ : base(endpointBase)
+ {
+ }
+
+ #region IDisposable Members
+
+ public new void Dispose()
+ {
+ freeTransfer();
+ }
+
+ #endregion
+ private void allocTransfer(UsbEndpointBase endpointBase, bool ownsTransfer, int isoPacketSize, int count)
+ {
+ int numIsoPackets = 0;
+ if (isoPacketSize > 0)
+ numIsoPackets = count/isoPacketSize;
+ freeTransfer();
+ mTransfer = MonoUsbTransfer.Alloc(numIsoPackets);
+ mOwnsTransfer = ownsTransfer;
+ mTransfer.Type = endpointBase.Type;
+ mTransfer.Endpoint = endpointBase.EpNum;
+ mTransfer.NumIsoPackets = numIsoPackets;
+
+ if (!mCompleteEventHandle.IsAllocated)
+ mCompleteEventHandle = GCHandle.Alloc(mTransferCompleteEvent);
+ mTransfer.PtrUserData = GCHandle.ToIntPtr(mCompleteEventHandle);
+
+ if (numIsoPackets > 0)
+ mTransfer.SetIsoPacketLengths(isoPacketSize);
+
+
+ }
+ private void freeTransfer()
+ {
+ if (mTransfer.IsInvalid || mOwnsTransfer == false) return;
+ mTransferCancelEvent.Set();
+ mTransferCompleteEvent.WaitOne(200, UsbConstants.EXIT_CONTEXT);
+ mTransfer.Free();
+
+ if (mCompleteEventHandle.IsAllocated)
+ mCompleteEventHandle.Free();
+
+
+ }
+
+ /// <summary>
+ /// Fills the transfer with the data to <see cref="UsbTransfer.Submit"/>.
+ /// </summary>
+ /// <param name="buffer">The buffer.</param>
+ /// <param name="offset">The offset on the buffer where the transfer should read/write.</param>
+ /// <param name="count">The number of bytes to transfer.</param>
+ /// <param name="timeout">Time (milliseconds) to wait before the transfer times out.</param>
+ public override void Fill(IntPtr buffer, int offset, int count, int timeout)
+ {
+ allocTransfer(EndpointBase, true, 0, count);
+
+ base.Fill(buffer, offset, count, timeout);
+
+ mTransfer.Timeout = timeout;
+ mTransfer.PtrDeviceHandle = EndpointBase.Handle.DangerousGetHandle();
+
+ mTransfer.PtrCallbackFn = Marshal.GetFunctionPointerForDelegate(mMonoUsbTransferCallbackDelegate);
+
+ mTransfer.Type = EndpointBase.Type;
+ mTransfer.Endpoint = EndpointBase.EpNum;
+
+ mTransfer.ActualLength = 0;
+ mTransfer.Status = 0;
+ mTransfer.Flags = MonoUsbTransferFlags.None;
+ }
+
+ /// <summary>
+ /// Fills the transfer with the data to <see cref="UsbTransfer.Submit"/> an isochronous transfer.
+ /// </summary>
+ /// <param name="buffer">The buffer.</param>
+ /// <param name="offset">The offset on the buffer where the transfer should read/write.</param>
+ /// <param name="count">The number of bytes to transfer.</param>
+ /// <param name="timeout">Time (milliseconds) to wait before the transfer times out.</param>
+ /// <param name="isoPacketSize">Size of each isochronous packet.</param>
+ public override void Fill(IntPtr buffer, int offset, int count, int timeout, int isoPacketSize)
+ {
+ allocTransfer(EndpointBase, true, isoPacketSize, count);
+
+ base.Fill(buffer, offset, count, timeout, isoPacketSize);
+
+ mTransfer.Timeout = timeout;
+ mTransfer.PtrDeviceHandle = EndpointBase.Handle.DangerousGetHandle();
+
+ mTransfer.PtrCallbackFn = Marshal.GetFunctionPointerForDelegate(mMonoUsbTransferCallbackDelegate);
+
+ mTransfer.Type = EndpointBase.Type;
+ mTransfer.Endpoint = EndpointBase.EpNum;
+
+ mTransfer.ActualLength = 0;
+ mTransfer.Status = 0;
+ mTransfer.Flags = MonoUsbTransferFlags.None;
+ }
+ // Clean up the globally allocated memory.
+
+ ~MonoUsbTransferContext() { Dispose(); }
+
+ /// <summary>
+ /// Submits the transfer.
+ /// </summary>
+ /// <remarks>
+ /// This functions submits the USB transfer and return immediately.
+ /// </remarks>
+ /// <returns>
+ /// <see cref="ErrorCode.Success"/> if the submit succeeds,
+ /// otherwise one of the other <see cref="ErrorCode"/> codes.
+ /// </returns>
+ public override ErrorCode Submit()
+ {
+ if (mTransferCancelEvent.WaitOne(0, false)) return ErrorCode.IoCancelled;
+
+ if (!mTransferCompleteEvent.WaitOne(0, UsbConstants.EXIT_CONTEXT)) return ErrorCode.ResourceBusy;
+
+ mTransfer.PtrBuffer = NextBufPtr;
+ mTransfer.Length = RequestCount;
+
+ mTransferCompleteEvent.Reset();
+
+ int ret = (int)mTransfer.Submit();
+ if (ret < 0)
+ {
+ mTransferCompleteEvent.Set();
+ UsbError usbErr = UsbError.Error(ErrorCode.MonoApiError, ret, "SubmitTransfer", EndpointBase);
+ return usbErr.ErrorCode;
+ }
+
+ return ErrorCode.Success;
+ }
+
+ /// <summary>
+ /// Wait for the transfer to complete, timeout, or get cancelled.
+ /// </summary>
+ /// <param name="transferredCount">The number of bytes transferred on <see cref="ErrorCode.Success"/>.</param>
+ /// <param name="cancel">Not used for libusb-1.0. Transfers are always cancelled on timeout or error.</param>
+ /// <returns><see cref="ErrorCode.Success"/> if the transfer completes successfully, otherwise one of the other <see cref="ErrorCode"/> codes.</returns>
+ public override ErrorCode Wait(out int transferredCount, bool cancel)
+ {
+ transferredCount = 0;
+ int ret = 0;
+ MonoUsbError monoError;
+ ErrorCode ec;
+
+ int iWait = WaitHandle.WaitAny(new WaitHandle[] {mTransferCompleteEvent, mTransferCancelEvent},
+ Timeout.Infinite,
+ UsbConstants.EXIT_CONTEXT);
+ switch (iWait)
+ {
+ case 0: // TransferCompleteEvent
+
+ if (mTransfer.Status == MonoUsbTansferStatus.TransferCompleted)
+ {
+ transferredCount = mTransfer.ActualLength;
+ return ErrorCode.Success;
+ }
+
+ string s;
+ monoError = MonoUsbApi.MonoLibUsbErrorFromTransferStatus(mTransfer.Status);
+ ec = MonoUsbApi.ErrorCodeFromLibUsbError((int)monoError, out s);
+ UsbError.Error(ErrorCode.MonoApiError, (int)monoError, "Wait:" + s, EndpointBase);
+ return ec;
+ case 1: // TransferCancelEvent
+ ret = (int)mTransfer.Cancel();
+ bool bTransferComplete = mTransferCompleteEvent.WaitOne(100, UsbConstants.EXIT_CONTEXT);
+ mTransferCompleteEvent.Set();
+
+ if (ret != 0 || !bTransferComplete)
+ {
+ ec = ret == 0 ? ErrorCode.CancelIoFailed : ErrorCode.MonoApiError;
+ UsbError.Error(ec, ret, String.Format("Wait:Unable to cancel transfer or the transfer did not return after it was cancelled. Cancelled:{0} TransferCompleted:{1}", (MonoUsbError)ret, bTransferComplete), EndpointBase);
+ return ec;
+ }
+ return ErrorCode.IoCancelled;
+ default: // Critical failure timeout
+ mTransfer.Cancel();
+ ec = ((EndpointBase.mEpNum & (byte)UsbCtrlFlags.Direction_In) > 0) ? ErrorCode.ReadFailed : ErrorCode.WriteFailed;
+ mTransferCompleteEvent.Set();
+ UsbError.Error(ec, ret, String.Format("Wait:Critical timeout failure! The transfer callback function was not called within the allotted time."), EndpointBase);
+ return ec;
+ }
+ }
+
+ private static void TransferCallback(MonoUsbTransfer pTransfer)
+ {
+ ManualResetEvent completeEvent = GCHandle.FromIntPtr(pTransfer.PtrUserData).Target as ManualResetEvent;
+ completeEvent.Set();
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/Transfer/MonoUsbTransferFlags.cs b/LibWinUsb/MonoLibUsb/Transfer/MonoUsbTransferFlags.cs
new file mode 100644
index 00000000..e4b7c554
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/Transfer/MonoUsbTransferFlags.cs
@@ -0,0 +1,51 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace MonoLibUsb.Transfer
+{
+ /// <summary>
+ /// Transfer flags.
+ /// </summary>
+ public enum MonoUsbTransferFlags : byte
+ {
+ /// <summary>
+ /// No transfer flags.
+ /// </summary>
+ None = 0,
+ /// <summary>
+ /// Report short frames as errors
+ /// </summary>
+ TransferShortNotOk = 1 << 0,
+
+ /// <summary>
+ /// Automatically free() transfer buffer during <see cref ="MonoUsbTransfer.Free">MonoUsbTransfer.Free()</see>.
+ /// </summary>
+ TransferFreeBuffer = 1 << 1,
+
+ /// <summary>
+ /// Automatically call <see cref ="MonoUsbTransfer.Free">MonoUsbTransfer.Free()</see> after callback returns.
+ /// </summary>
+ /// <remakrks>
+ /// <para>If this flag is set, it is illegal to call <see cref ="MonoUsbTransfer.Free"/> from your transfer callback, as this will result in a double-free when this flag is acted upon.</para>
+ /// </remakrks>
+ TransferFreeTransfer = 1 << 2,
+ } ;
+} \ No newline at end of file
diff --git a/LibWinUsb/MonoLibUsb/UnixNativeTimeval.cs b/LibWinUsb/MonoLibUsb/UnixNativeTimeval.cs
new file mode 100644
index 00000000..94860906
--- /dev/null
+++ b/LibWinUsb/MonoLibUsb/UnixNativeTimeval.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Main;
+
+namespace MonoLibUsb
+{
+ /// <summary>
+ /// Unix mono.net timeval structure.
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential)]
+ public struct UnixNativeTimeval
+ {
+ private IntPtr mTvSecInternal;
+ private IntPtr mTvUSecInternal;
+
+ /// <summary>
+ /// Default <see cref="UnixNativeTimeval"/> used by the <see cref="MonoUsbEventHandler"/> on windows platforms.
+ /// </summary>
+ public static UnixNativeTimeval WindowsDefault
+ {
+ get { return new UnixNativeTimeval(2, 0); }
+ }
+
+ /// <summary>
+ /// Default <see cref="UnixNativeTimeval"/> used by the <see cref="MonoUsbEventHandler"/> on unix-like platforms.
+ /// </summary>
+ public static UnixNativeTimeval LinuxDefault
+ {
+ get { return new UnixNativeTimeval(2, 0); }
+ }
+
+ /// <summary>
+ /// Default <see cref="UnixNativeTimeval"/>.
+ /// </summary>
+ public static UnixNativeTimeval Default
+ {
+ get { return Helper.IsLinux ? LinuxDefault : WindowsDefault; }
+ }
+
+ /// <summary>
+ /// Timeval seconds property.
+ /// </summary>
+ public long tv_sec
+ {
+ get { return mTvSecInternal.ToInt64(); }
+ set { mTvSecInternal = new IntPtr(value); }
+ }
+
+ /// <summary>
+ /// Timeval milliseconds property.
+ /// </summary>
+ public long tv_usec
+ {
+ get { return mTvUSecInternal.ToInt64(); }
+ set { mTvUSecInternal = new IntPtr(value); }
+ }
+
+ /// <summary>
+ /// Timeval constructor.
+ /// </summary>
+ /// <param name="tvSec">seconds</param>
+ /// <param name="tvUsec">milliseconds</param>
+ public UnixNativeTimeval(long tvSec, long tvUsec)
+ {
+ mTvSecInternal = new IntPtr(tvSec);
+ mTvUSecInternal = new IntPtr(tvUsec);
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/UsbDevice.Common.cs b/LibWinUsb/UsbDevice.Common.cs
new file mode 100644
index 00000000..95ba24ee
--- /dev/null
+++ b/LibWinUsb/UsbDevice.Common.cs
@@ -0,0 +1,249 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using LibUsbDotNet.Internal.LibUsb;
+using LibUsbDotNet.LibUsb;
+using LibUsbDotNet.Main;
+using LibUsbDotNet.LudnMonoLibUsb;
+using LibUsbDotNet.WinUsb.Internal;
+using Debug=System.Diagnostics.Debug;
+
+namespace LibUsbDotNet
+{
+ public abstract partial class UsbDevice
+ {
+ private static LibUsbAPI _libUsbApi;
+ private static WinUsbAPI _winUsbApi;
+ private static object mHasWinUsbDriver;
+ private static object mHasLibUsbWinBackDriver;
+
+ private static LibUsbKernelType mLibUsbKernelType;
+ private static UsbKernelVersion mUsbKernelVersion;
+
+ /// <summary>
+ /// Gets a list of all available USB devices (WinUsb, LibUsb, Linux LibUsb v1.x).
+ /// </summary>
+ /// <remarks>
+ /// Use this property to get a list of USB device that can be accessed by LibUsbDotNet.
+ /// Using this property as opposed to <see cref="AllLibUsbDevices"/> and <see cref="AllWinUsbDevices"/>
+ /// will ensure your source code is platform-independent.
+ /// </remarks>
+ public static UsbRegDeviceList AllDevices
+ {
+ get
+ {
+ UsbRegDeviceList regDevReturnList = new UsbRegDeviceList();
+
+ UsbRegDeviceList winUsbList = AllWinUsbDevices;
+ foreach (UsbRegistry winUsbRegistry in winUsbList)
+ regDevReturnList.Add(winUsbRegistry);
+
+ UsbRegDeviceList libUsbList = AllLibUsbDevices;
+ foreach (UsbRegistry libUsbRegistry in libUsbList)
+ regDevReturnList.Add(libUsbRegistry);
+
+ return regDevReturnList;
+ }
+ }
+
+ /// <summary>
+ /// Gets a list of all available libusb-win32 USB devices.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// On windows, gets a list of libusb-win32 USB devices . If <see cref="ForceLibUsbWinBack"/>
+ /// is true, gets a list of libusb-1.0 devices.
+ /// </para>
+ /// <para>
+ /// On linux/mac, gets a list of libusb-1.0 devices.
+ /// </para>
+ /// </remarks>
+ public static UsbRegDeviceList AllLibUsbDevices
+ {
+ get
+ {
+ UsbRegDeviceList regDevList = new UsbRegDeviceList();
+ if (HasLibUsbWinBackDriver && ForceLibUsbWinBack)
+ {
+ List<MonoUsbDevice> deviceList = MonoUsbDevice.MonoUsbDeviceList;
+ foreach (MonoUsbDevice usbDevice in deviceList)
+ {
+ regDevList.Add(new LegacyUsbRegistry(usbDevice));
+ }
+ }
+ else
+ {
+ if (!ForceLegacyLibUsb && KernelType == LibUsbKernelType.NativeLibUsb)
+ {
+ List<LibUsbRegistry> libUsbRegistry = LibUsbRegistry.DeviceList;
+ foreach (LibUsbRegistry usbRegistry in libUsbRegistry)
+ regDevList.Add(usbRegistry);
+ }
+ else
+ {
+ List<LegacyUsbRegistry> libUsbRegistry = LegacyUsbRegistry.DeviceList;
+ foreach (LegacyUsbRegistry usbRegistry in libUsbRegistry)
+ regDevList.Add(usbRegistry);
+ }
+ }
+ return regDevList;
+ }
+ }
+
+ /// <summary>
+ /// Returns the last error number reported by LibUsbDotNet.
+ /// </summary>
+ public static int LastErrorNumber
+ {
+ get { return UsbError.mLastErrorNumber; }
+ }
+
+ /// <summary>
+ /// Returns the last error string reported by LibUsbDotNet.
+ /// </summary>
+ public static string LastErrorString
+ {
+ get { return UsbError.mLastErrorString; }
+ }
+
+ internal static LibUsbAPI LibUsbApi
+ {
+ get
+ {
+ if (ReferenceEquals(_libUsbApi, null))
+ _libUsbApi = new LibUsbAPI();
+ return _libUsbApi;
+ }
+ }
+
+ internal static WinUsbAPI WinUsbApi
+ {
+ get
+ {
+ if (ReferenceEquals(_winUsbApi, null))
+ _winUsbApi = new WinUsbAPI();
+ return _winUsbApi;
+ }
+ }
+
+
+
+ /// <summary>
+ /// Opens the usb device that matches the <see cref="UsbDeviceFinder"/>.
+ /// </summary>
+ /// <param name="usbDeviceFinder">The <see cref="UsbDeviceFinder"/> class used to find the usb device.</param>
+ /// <returns>An valid/open usb device class if the device was found or Null if the device was not found.</returns>
+ public static UsbDevice OpenUsbDevice(UsbDeviceFinder usbDeviceFinder)
+ {
+ return OpenUsbDevice((Predicate<UsbRegistry>) usbDeviceFinder.Check);
+ }
+
+ /// <summary>
+ /// Opens the usb device that matches the find predicate.
+ /// </summary>
+ /// <param name="findDevicePredicate">The predicate function used to find the usb device.</param>
+ /// <returns>An valid/open usb device class if the device was found or Null if the device was not found.</returns>
+ public static UsbDevice OpenUsbDevice(Predicate<UsbRegistry> findDevicePredicate)
+ {
+ UsbDevice usbDeviceFound;
+
+ UsbRegDeviceList allDevices = AllDevices;
+ UsbRegistry regDeviceFound = allDevices.Find(findDevicePredicate);
+
+ if (ReferenceEquals(regDeviceFound, null)) return null;
+
+ usbDeviceFound = regDeviceFound.Device;
+
+ return usbDeviceFound;
+ }
+
+ /// <summary>
+ /// Opens a WinUsb device by its DeviceInterfaceGUID.
+ /// </summary>
+ /// <remarks>
+ /// This is the Microsoft-recommended way for opening a WinUsb device.
+ /// LibUsb device can be opened in this way as well. In order to open
+ /// LibUsb devices in this manner, an entry must be added to the driver
+ /// inf file:
+ /// <para>[Install.HW]</para>
+ /// <para>Addreg=Add_LibUsb_Guid_Reg</para>
+ /// <para>[Add_LibUsb_Guid_Reg]</para>
+ /// <para>HKR,,LibUsbInterfaceGUIDs,0x10000,"{Your-Unique-Guid-String}"</para>
+ /// </remarks>
+ /// <param name="devInterfaceGuid">Device Interface GUID of the usb device to open.</param>
+ /// <param name="usbDevice">On success, a new <see cref="UsbDevice"/> instance.</param>
+ /// <returns>True on success.</returns>
+ public static bool OpenUsbDevice(ref Guid devInterfaceGuid, out UsbDevice usbDevice)
+ {
+ usbDevice = null;
+ UsbRegDeviceList usbRegDevices = AllDevices;
+ foreach (UsbRegistry usbRegistry in usbRegDevices)
+ {
+ foreach (Guid guid in usbRegistry.DeviceInterfaceGuids)
+ {
+ if (guid == devInterfaceGuid)
+ {
+ usbDevice = usbRegistry.Device;
+ if (usbDevice != null) return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Global static error event for all Usb errors.
+ /// </summary>
+ /// <example>
+ /// Sample code to reset an endpoint if a critical error occurs.
+ /// <code>
+ /// // Hook the usb error handler function
+ /// UsbGlobals.UsbErrorEvent += UsbErrorEvent;
+ ///private void UsbErrorEvent(object sender, UsbError e)
+ ///{
+ /// // If the error is from a usb endpoint
+ /// if (sender is UsbEndpointBase)
+ /// {
+ /// // If the endpoint transfer failed
+ /// if (e.Win32ErrorNumber == 31)
+ /// {
+ /// // If the USB device is still open, connected, and valid
+ /// if (usb.IsOpen)
+ /// {
+ /// // Try to reset then endpoint
+ /// if (((UsbEndpointBase) sender).Reset())
+ /// {
+ /// // Endpoint reset successful.
+ /// // Tell LibUsbDotNet to ignore this error and continue.
+ /// e.Handled = true;
+ /// }
+ /// }
+ /// }
+ /// }
+ /// }
+ /// </code>
+ /// </example>
+ public static event EventHandler<UsbError> UsbErrorEvent;
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/UsbDevice.Error.cs b/LibWinUsb/UsbDevice.Error.cs
new file mode 100644
index 00000000..733660f6
--- /dev/null
+++ b/LibWinUsb/UsbDevice.Error.cs
@@ -0,0 +1,166 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using LibUsbDotNet.Internal;
+using LibUsbDotNet.Main;
+using MonoLibUsb;
+
+namespace LibUsbDotNet
+{
+ partial class UsbDevice
+ {
+ internal static void FireUsbError(object sender, UsbError usbError)
+ {
+ EventHandler<UsbError> temp = UsbErrorEvent;
+ if (!ReferenceEquals(null, temp))
+ temp(sender, usbError);
+ }
+ }
+
+ /// <summary> Describes a Usb error or setup API error.
+ /// </summary>
+ public class UsbError : EventArgs
+ {
+ internal static int mLastErrorNumber;
+ internal static string mLastErrorString = String.Empty;
+
+ ///// <summary>
+ ///// The the error is <see cref="Handled"/> field is set to true for errors resulting from endpoint read/write errors. The operation will retry instead of exiting with an error code.
+ ///// </summary>
+ //public bool Handled;
+
+ internal string mDescription;
+
+ internal ErrorCode mErrorCode;
+ private object mSender;
+ internal int mWin32ErrorNumber;
+ internal string mWin32ErrorString = "None";
+
+ internal UsbError(ErrorCode errorCode, int win32ErrorNumber, string win32ErrorString, string description, object sender)
+ {
+ mSender = sender;
+ string senderText = String.Empty;
+ if ((mSender is UsbEndpointBase)|| (mSender is UsbTransfer))
+ {
+ UsbEndpointBase ep;
+ if (mSender is UsbTransfer)
+ ep = ((UsbTransfer)mSender).EndpointBase;
+ else
+ ep = mSender as UsbEndpointBase;
+
+ if (ep.mEpNum != 0)
+ {
+
+ senderText = senderText+=string.Format(" Ep 0x{0:X2} ", ep.mEpNum);
+ }
+ }
+ else if (mSender is Type)
+ {
+ Type t = mSender as Type;
+ senderText = senderText += string.Format(" {0} ", t.Name);
+ }
+ mErrorCode = errorCode;
+ mWin32ErrorNumber = win32ErrorNumber;
+ mWin32ErrorString = win32ErrorString;
+ mDescription = description + senderText;
+ }
+
+ /// <summary>
+ /// The sender of the exception.
+ /// </summary>
+ public object Sender
+ {
+ get { return mSender; }
+ }
+
+ /// <summary>
+ /// Gets the general errorcode.
+ /// </summary>
+ public ErrorCode ErrorCode
+ {
+ get { return mErrorCode; }
+ }
+
+ /// <summary>
+ /// Gets the Windows specific error number. Only valid when <see cref="ErrorCode"/> is set to <see cref="Main.ErrorCode"/>.<see cref="Main.ErrorCode.Win32Error"/>.
+ /// </summary>
+ public int Win32ErrorNumber
+ {
+ get { return mWin32ErrorNumber; }
+ }
+
+ /// <summary>
+ /// Gets the general description for the error.
+ /// </summary>
+ public string Description
+ {
+ get { return mDescription; }
+ }
+
+ /// <summary>
+ /// Gets the Windows specific error string. Only valid when <see cref="ErrorCode"/> is set to <see cref="Main.ErrorCode"/>.<see cref="Main.ErrorCode.Win32Error"/>.
+ /// </summary>
+ public string Win32ErrorString
+ {
+ get { return mWin32ErrorString; }
+ }
+
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="UsbError"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="UsbError"/>.
+ ///</returns>
+ public override string ToString()
+ {
+ if (Win32ErrorNumber != 0)
+ {
+ return String.Format("{0}:{1}\r\n{2}:{3}", ErrorCode, Description, Win32ErrorNumber, mWin32ErrorString);
+ }
+ return String.Format("{0}:{1}", ErrorCode, Description);
+ }
+
+ internal static UsbError Error(ErrorCode errorCode, int ret, string description, object sender)
+ {
+ string win32Error = String.Empty;
+ if (errorCode == ErrorCode.Win32Error && !UsbDevice.IsLinux && ret != 0)
+ {
+ win32Error = Kernel32.FormatSystemMessage(ret);
+ }
+ else if (errorCode == ErrorCode.MonoApiError && ret != 0)
+ {
+ win32Error = ((MonoUsbError) ret) + ":" + MonoUsbApi.StrError((MonoUsbError) ret);
+ }
+ UsbError err = new UsbError(errorCode, ret, win32Error, description, sender);
+ lock (mLastErrorString)
+ {
+ mLastErrorNumber = (int) err.ErrorCode;
+ mLastErrorString = err.ToString();
+ }
+ UsbDevice.FireUsbError(sender, err);
+
+ return err;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/UsbDevice.OS.Specific.cs b/LibWinUsb/UsbDevice.OS.Specific.cs
new file mode 100644
index 00000000..f8120d0f
--- /dev/null
+++ b/LibWinUsb/UsbDevice.OS.Specific.cs
@@ -0,0 +1,291 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Internal.LibUsb;
+using LibUsbDotNet.LibUsb;
+using LibUsbDotNet.Main;
+using LibUsbDotNet.LudnMonoLibUsb;
+using LibUsbDotNet.WinUsb;
+using MonoLibUsb;
+
+namespace LibUsbDotNet
+{
+ public abstract partial class UsbDevice
+ {
+ /// <summary>
+ ///
+ /// </summary>
+ private static readonly bool ForceLegacyLibUsb = IsLinux;
+
+ /// <summary>
+ /// Setting this field to <see langword="true"/> will force <see cref="LibUsbDotNet"/> to use the <a href="http://www.libusb.org/wiki/windows_backend">Libusb-1.0 Windows-backend driver.</a> For platforms other than windows, this setting has no effect.
+ /// </summary>
+ /// <remarks>
+ /// If this is <see langword="true"/>, <see cref="AllDevices"/> will return only <see cref="MonoUsbDevice"/>s in the list.
+ /// </remarks>
+ public static bool ForceLibUsbWinBack = false;
+
+
+ /// <summary>
+ /// Gets a list of all available WinUSB USB devices.
+ /// </summary>
+ /// <remarks>
+ /// On windows, gets a list of WinUSB devices. On linux always returns null.
+ /// <para>
+ /// Using the <see cref="AllDevices"/> property instead will ensure your source code is platform-independent.
+ /// </para>
+ /// </remarks>
+ public static UsbRegDeviceList AllWinUsbDevices
+ {
+ get
+ {
+ UsbRegDeviceList regDevList = new UsbRegDeviceList();
+ if (IsLinux || ForceLibUsbWinBack) return regDevList;
+
+ if (HasWinUsbDriver)
+ {
+ List<WinUsbRegistry> winUsbRegistry = WinUsbRegistry.DeviceList;
+ foreach (WinUsbRegistry usbRegistry in winUsbRegistry)
+ regDevList.Add(usbRegistry);
+ }
+
+ return regDevList;
+ }
+ }
+
+ /// <summary>
+ /// True if the LibUsb driver is found on the system.
+ /// </summary>
+ [Obsolete("Always returns true")]
+ public static bool HasLibUsbDriver
+ {
+ get
+ {
+ return true;
+ }
+ }
+ /*
+ public static bool HasLibUsbDriver
+ {
+ get
+ {
+ if (mHasLibUsbDriver == null)
+ {
+ if (IsLinux)
+ {
+ mHasLibUsbDriver = true;
+ }
+ else
+ {
+ mHasLibUsbDriver = false;
+ string sysDriver = Path.Combine(Environment.SystemDirectory, "drivers");
+ DirectoryInfo diSysDriver = new DirectoryInfo(sysDriver);
+ if (diSysDriver.Exists)
+ {
+ FileInfo[] libUsbSysFileInfo = diSysDriver.GetFiles(LIBUSB_SYS);
+ if (libUsbSysFileInfo.Length > 0)
+ mHasLibUsbDriver = true;
+ }
+ }
+ }
+ return (bool) mHasLibUsbDriver;
+ }
+ }
+ */
+
+ /// <summary>
+ /// True if the WinUSB API is available.
+ /// </summary>
+ /// <remarks>
+ /// </remarks>
+ public static bool HasWinUsbDriver
+ {
+ get
+ {
+ if (mHasWinUsbDriver == null)
+ {
+ if (IsLinux)
+ {
+ mHasWinUsbDriver = false;
+ }
+ else
+ {
+ try
+ {
+ WinUsb.Internal.WinUsbAPI.WinUsb_Free(IntPtr.Zero);
+ mHasWinUsbDriver = true;
+ }
+ catch (Exception)
+ {
+ mHasWinUsbDriver = false;
+
+ }
+ }
+ }
+ return (bool) mHasWinUsbDriver;
+ }
+ }
+
+ /// <summary>
+ /// True if the libusb-1.0 API is available.
+ /// </summary>
+ public static bool HasLibUsbWinBackDriver
+ {
+ get
+ {
+ if (mHasLibUsbWinBackDriver == null)
+ {
+ if (IsLinux)
+ {
+ mHasLibUsbWinBackDriver = false;
+ }
+ else
+ {
+ try
+ {
+ MonoUsbApi.StrError(MonoUsbError.Success);
+ mHasLibUsbWinBackDriver = true;
+ }
+ catch(Exception)
+ {
+ mHasLibUsbWinBackDriver = false;
+
+ }
+ }
+ }
+ return (bool)mHasLibUsbWinBackDriver;
+ }
+ }
+ ///<summary>
+ /// Returns true if the system is a linux/unix-like operating system.
+ ///</summary>
+ ///<exception cref="NotSupportedException"></exception>
+ public static bool IsLinux
+ {
+ get
+ {
+ return Helper.IsLinux;
+
+ }
+ }
+
+ /// <summary>
+ /// Gets the kernel driver type in use by LibUsbDotNet.
+ /// If <see cref="LibUsbKernelType.NativeLibUsb"/> is returned, LibUsbDotNet using using its
+ /// native kernel driver. Basic usb device information is retreived from the windows registry
+ /// which reduces USB IO overhead.
+ /// If <see cref="LibUsbKernelType.LegacyLibUsb"/> is returned, LibUsbDotNet is using the orginal kernel
+ /// available at the libusb-win32.sourceforge.net page and true windows registry support
+ /// is unavailable.
+ /// Under linux, <see cref="LibUsbKernelType.MonoLibUsb"/> is always returned.
+ /// </summary>
+ public static LibUsbKernelType KernelType
+ {
+ get
+ {
+ if (mLibUsbKernelType == LibUsbKernelType.Unknown)
+ {
+ if (IsLinux)
+ {
+ mLibUsbKernelType = LibUsbKernelType.MonoLibUsb;
+ }
+ else
+ {
+ UsbKernelVersion libUsbVersion = KernelVersion;
+ if (!libUsbVersion.IsEmpty)
+ {
+ mLibUsbKernelType = libUsbVersion.BcdLibUsbDotNetKernelMod != 0
+ ? LibUsbKernelType.NativeLibUsb
+ : LibUsbKernelType.LegacyLibUsb;
+ }
+ }
+ }
+
+ return mLibUsbKernelType;
+ }
+ }
+
+ /// <summary>
+ /// Gets the kernel driver version in use by LibUsbDotNet.
+ /// <alert class="note"><para>
+ /// if <see cref="UsbKernelVersion.BcdLibUsbDotNetKernelMod"/> is non-zero then the kernel driver is native.
+ /// </para></alert>
+ /// </summary>
+ public static UsbKernelVersion KernelVersion
+ {
+ get
+ {
+ if (mUsbKernelVersion.IsEmpty)
+ {
+ if (IsLinux)
+ {
+ mUsbKernelVersion = new UsbKernelVersion(1, 0, 0, 0, 0);
+ }
+ else
+ {
+ for (int i = 1; i < UsbConstants.MAX_DEVICES; i++)
+ {
+ LibUsbDevice newLibUsbDevice;
+ string deviceFileName = LibUsbDriverIO.GetDeviceNameString(i);
+ if (!LibUsbDevice.Open(deviceFileName, out newLibUsbDevice)) continue;
+ LibUsbRequest request = new LibUsbRequest();
+ GCHandle gcReq = GCHandle.Alloc(request, GCHandleType.Pinned);
+
+ int transferred;
+ bool bSuccess = newLibUsbDevice.UsbIoSync(LibUsbIoCtl.GET_VERSION,
+ request,
+ LibUsbRequest.Size,
+ gcReq.AddrOfPinnedObject(),
+ LibUsbRequest.Size,
+ out transferred);
+
+ gcReq.Free();
+ newLibUsbDevice.Close();
+ if (bSuccess && transferred == LibUsbRequest.Size)
+ {
+ mUsbKernelVersion = request.Version;
+ break;
+ }
+ }
+ }
+ }
+
+ return mUsbKernelVersion;
+ }
+ }
+
+
+ ///<summary>
+ /// Gets a <see cref="System.OperatingSystem"/> object that contains the current platform identifier and version number.
+ ///</summary>
+ public static OperatingSystem OSVersion
+ {
+ get
+ {
+ return Helper.OSVersion;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/UsbDevice.cs b/LibWinUsb/UsbDevice.cs
new file mode 100644
index 00000000..c4f1dfcc
--- /dev/null
+++ b/LibWinUsb/UsbDevice.cs
@@ -0,0 +1,495 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Descriptors;
+using LibUsbDotNet.Info;
+using LibUsbDotNet.Internal;
+using LibUsbDotNet.LudnMonoLibUsb;
+using LibUsbDotNet.Main;
+using MonoLibUsb;
+
+namespace LibUsbDotNet
+{
+ /// <summary>Contains non-driver specific USB device communication members.</summary>
+ /// <remarks>
+ /// This class is compatible with WinUSB, LibUsb-Win32, and linux libusb v1.x.
+ /// Platform independent applications should only use usb device members from this class.
+ /// If more functionality is required, it is up to the application to handle multi-driver
+ /// and/or multi-platfrom requirements.
+ /// </remarks>
+ public abstract partial class UsbDevice
+ {
+ #region Enumerations
+
+ /// <summary>
+ /// Driver modes enumeration. See the UsbDevice.<see cref="UsbDevice.DriverMode"/> property.
+ /// </summary>
+ public enum DriverModeType
+ {
+ /// <summary>
+ /// Not yet determined.
+ /// </summary>
+ Unknown,
+ /// <summary>
+ /// Using LibUsb kernel driver (Legacy or Native) on windows.
+ /// </summary>
+ LibUsb,
+ /// <summary>
+ /// Using WinUsb user-mode driver on windows.
+ /// </summary>
+ WinUsb,
+ /// <summary>
+ /// Using Libusb 1.0 driver on linux.
+ /// </summary>
+ MonoLibUsb,
+ /// <summary>
+ /// Using Libusb 1.0 windows backend driver on windows.
+ /// </summary>
+ LibUsbWinBack
+ }
+
+ #endregion
+
+ internal readonly UsbEndpointList mActiveEndpoints;
+ internal readonly UsbApiBase mUsbApi;
+ internal UsbDeviceDescriptor mCachedDeviceDescriptor;
+ internal List<UsbConfigInfo> mConfigs;
+ internal int mCurrentConfigValue = -1;
+ internal UsbDeviceInfo mDeviceInfo;
+ internal SafeHandle mUsbHandle;
+ internal UsbRegistry mUsbRegistry;
+
+ internal UsbDevice(UsbApiBase usbApi, SafeHandle usbHandle)
+ {
+ mUsbApi = usbApi;
+ mUsbHandle = usbHandle;
+ mActiveEndpoints = new UsbEndpointList();
+ }
+
+ ///<summary>
+ /// Gets all available configurations for this <see cref="UsbDevice"/>
+ ///</summary>
+ /// <remarks>
+ /// The first time this property is accessed it will query the <see cref="UsbDevice"/> for all configurations.
+ /// Subsequent request will return a cached copy of all configurations.
+ /// </remarks>
+ public virtual ReadOnlyCollection<UsbConfigInfo> Configs
+ {
+ get
+ {
+ if ((ReferenceEquals(mConfigs, null)))
+ {
+ mConfigs = GetDeviceConfigs(this);
+ }
+ return mConfigs.AsReadOnly();
+ }
+ }
+
+ /// <summary>
+ /// Gets the actual device descriptor the the current <see cref="UsbDevice"/>.
+ /// </summary>
+ public virtual UsbDeviceInfo Info
+ {
+ get
+ {
+ if (ReferenceEquals(mDeviceInfo, null))
+ {
+ mDeviceInfo = new UsbDeviceInfo(this);
+ }
+ return mDeviceInfo;
+ }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="UsbRegistry"/> class that opened the device, or null if the device was not opened by the <see cref="UsbRegistry"/> class.
+ /// </summary>
+ public virtual UsbRegistry UsbRegistryInfo
+ {
+ get { return mUsbRegistry; }
+ }
+
+ /// <summary>
+ /// Gets a value indication if the device handle is valid.
+ /// </summary>
+ public bool IsOpen
+ {
+ get { return ((mUsbHandle != null) && !mUsbHandle.IsClosed) && !mUsbHandle.IsInvalid; }
+ }
+
+ /// <summary>
+ /// A list of endpoints that have beened opened by this <see cref="UsbDevice"/> class.
+ /// </summary>
+ public UsbEndpointList ActiveEndpoints
+ {
+ get { return mActiveEndpoints; }
+ }
+
+
+ internal SafeHandle Handle
+ {
+ get { return mUsbHandle; }
+ }
+
+ /// <summary>
+ /// Returns the DriverMode this USB device is using.
+ /// </summary>
+ public abstract DriverModeType DriverMode { get; }
+
+
+ /// <summary>
+ /// Closes the <see cref="UsbDevice"/> and disposes any <see cref="ActiveEndpoints"/>.
+ /// </summary>
+ /// <returns>True on success.</returns>
+ public abstract bool Close();
+
+ ///<summary>
+ /// Opens the USB device handle.
+ ///</summary>
+ ///<returns>
+ ///True if the device is already opened or was opened successfully.
+ ///False if the device does not exists or is no longer valid.
+ ///</returns>
+ public abstract bool Open();
+
+ /// <summary>
+ /// Transmits control data over a default control endpoint.
+ /// </summary>
+ /// <param name="setupPacket">An 8-byte setup packet which contains parameters for the control request.
+ /// See section 9.3 USB Device Requests of the Universal Serial Bus Specification Revision 2.0 for more information. </param>
+ /// <param name="buffer">Data to be sent/received from the device.</param>
+ /// <param name="bufferLength">Length of the buffer param.</param>
+ /// <param name="lengthTransferred">Number of bytes sent or received (depends on the direction of the control transfer).</param>
+ /// <returns>True on success.</returns>
+ public virtual bool ControlTransfer(ref UsbSetupPacket setupPacket, IntPtr buffer, int bufferLength, out int lengthTransferred)
+ {
+ bool bSuccess = mUsbApi.ControlTransfer(mUsbHandle, setupPacket, buffer, bufferLength, out lengthTransferred);
+
+ if (!bSuccess)
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "ControlTransfer", this);
+
+ return bSuccess;
+ }
+
+ /// <summary>
+ /// Transmits control data over a default control endpoint.
+ /// </summary>
+ /// <param name="setupPacket">An 8-byte setup packet which contains parameters for the control request.
+ /// See section 9.3 USB Device Requests of the Universal Serial Bus Specification Revision 2.0 for more information. </param>
+ /// <param name="buffer">Data to be sent/received from the device.</param>
+ /// <param name="bufferLength">Length of the buffer param.</param>
+ /// <param name="lengthTransferred">Number of bytes sent or received (depends on the direction of the control transfer).</param>
+ /// <returns>True on success.</returns>
+ public virtual bool ControlTransfer(ref UsbSetupPacket setupPacket, object buffer, int bufferLength, out int lengthTransferred)
+ {
+ PinnedHandle pinned = new PinnedHandle(buffer);
+ bool bSuccess = ControlTransfer(ref setupPacket, pinned.Handle, bufferLength, out lengthTransferred);
+ pinned.Dispose();
+
+ return bSuccess;
+ }
+
+ /// <summary>
+ /// Gets the USB devices active configuration value.
+ /// </summary>
+ /// <param name="config">The active configuration value. A zero value means the device is not configured and a non-zero value indicates the device is configured.</param>
+ /// <returns>True on success.</returns>
+ public virtual bool GetConfiguration(out byte config)
+ {
+ config = 0;
+ byte[] buf = new byte[1];
+ int uTransferLength;
+
+ UsbSetupPacket setupPkt = new UsbSetupPacket();
+ setupPkt.RequestType = (byte) UsbEndpointDirection.EndpointIn | (byte) UsbRequestType.TypeStandard |
+ (byte) UsbRequestRecipient.RecipDevice;
+ setupPkt.Request = (byte) UsbStandardRequest.GetConfiguration;
+ setupPkt.Value = 0;
+ setupPkt.Index = 0;
+ setupPkt.Length = 1;
+
+ bool bSuccess = ControlTransfer(ref setupPkt, buf, buf.Length, out uTransferLength);
+ if (bSuccess && uTransferLength == 1)
+ {
+ config = buf[0];
+ mCurrentConfigValue = config;
+ return true;
+ }
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "GetConfiguration", this);
+ return false;
+ }
+
+ /// <summary>
+ /// Gets a descriptor from the device. See <see cref="DescriptorType"/> for more information.
+ /// </summary>
+ /// <param name="descriptorType">The descriptor type ID to retrieve; this is usually one of the <see cref="DescriptorType"/> enumerations.</param>
+ /// <param name="index">Descriptor index.</param>
+ /// <param name="langId">Descriptor language id.</param>
+ /// <param name="buffer">Memory to store the returned descriptor in.</param>
+ /// <param name="bufferLength">Length of the buffer parameter in bytes.</param>
+ /// <param name="transferLength">The number of bytes transferred to buffer upon success.</param>
+ /// <returns>True on success.</returns>
+ public virtual bool GetDescriptor(byte descriptorType, byte index, short langId, IntPtr buffer, int bufferLength, out int transferLength)
+ {
+ transferLength = 0;
+
+ bool wasOpen = IsOpen;
+ if (!wasOpen) Open();
+ if (!IsOpen) return false;
+
+ bool bSuccess = mUsbApi.GetDescriptor(mUsbHandle, descriptorType, index, (ushort) langId, buffer, bufferLength, out transferLength);
+
+ if (!bSuccess)
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "GetDescriptor", this);
+
+ if (!wasOpen && IsOpen) Close();
+
+ return bSuccess;
+ }
+
+
+ /// <summary>
+ /// Opens a <see cref="EndpointType.Bulk"/> endpoint for writing
+ /// </summary>
+ /// <param name="writeEndpointID">Endpoint number for read operations.</param>
+ /// <returns>A <see cref="UsbEndpointWriter"/> class ready for writing. If the specified endpoint is already been opened, the original <see cref="UsbEndpointWriter"/> class is returned.</returns>
+ public virtual UsbEndpointWriter OpenEndpointWriter(WriteEndpointID writeEndpointID) { return OpenEndpointWriter(writeEndpointID, EndpointType.Bulk); }
+
+ /// <summary>
+ /// Opens an endpoint for writing
+ /// </summary>
+ /// <param name="writeEndpointID">Endpoint number for read operations.</param>
+ /// <param name="endpointType">The type of endpoint to open.</param>
+ /// <returns>A <see cref="UsbEndpointWriter"/> class ready for writing. If the specified endpoint is already been opened, the original <see cref="UsbEndpointWriter"/> class is returned.</returns>
+ public virtual UsbEndpointWriter OpenEndpointWriter(WriteEndpointID writeEndpointID, EndpointType endpointType)
+ {
+ foreach (UsbEndpointBase activeEndpoint in ActiveEndpoints)
+ if (activeEndpoint.EpNum == (byte) writeEndpointID)
+ return (UsbEndpointWriter) activeEndpoint;
+
+ UsbEndpointWriter epNew = new UsbEndpointWriter(this, writeEndpointID, endpointType);
+ return (UsbEndpointWriter) mActiveEndpoints.Add(epNew);
+ }
+
+ internal static List<UsbConfigInfo> GetDeviceConfigs(UsbDevice usbDevice)
+ {
+ List<UsbConfigInfo> rtnConfigs = new List<UsbConfigInfo>();
+
+ byte[] cfgBuffer = new byte[UsbConstants.MAX_CONFIG_SIZE];
+
+ int iConfigs = usbDevice.Info.Descriptor.ConfigurationCount;
+ for (int iConfig = 0; iConfig < iConfigs; iConfig++)
+ {
+ int iBytesTransmitted;
+ bool bSuccess = usbDevice.GetDescriptor((byte) DescriptorType.Configuration, 0, 0, cfgBuffer, cfgBuffer.Length, out iBytesTransmitted);
+ if (bSuccess)
+ {
+ if (iBytesTransmitted >= UsbConfigDescriptor.Size && cfgBuffer[1] == (byte) DescriptorType.Configuration)
+ {
+ UsbConfigDescriptor configDescriptor = new UsbConfigDescriptor();
+ Helper.BytesToObject(cfgBuffer, 0, Math.Min(UsbConfigDescriptor.Size, cfgBuffer[0]), configDescriptor);
+
+ if (configDescriptor.TotalLength == iBytesTransmitted)
+ {
+ 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 UsbException(usbDevice, "Descriptor length is out of range.");
+
+ Array.Copy(cfgBuffer, iRawLengthPosition, rawDescriptor, 0, rawDescriptor.Length);
+ rawDescriptorList.Add(rawDescriptor);
+ iRawLengthPosition += rawDescriptor.Length;
+ }
+ rtnConfigs.Add(new UsbConfigInfo(usbDevice, configDescriptor, ref rawDescriptorList));
+ }
+ else
+ UsbError.Error(ErrorCode.InvalidConfig,
+ 0,
+ "GetDeviceConfigs: USB config descriptor length doesn't match the length received.",
+ usbDevice);
+ }
+ else
+ UsbError.Error(ErrorCode.InvalidConfig, 0, "GetDeviceConfigs: USB config descriptor is invalid.", usbDevice);
+ }
+ else
+ UsbError.Error(ErrorCode.InvalidConfig, 0, "GetDeviceConfigs", usbDevice);
+ }
+ return rtnConfigs;
+ }
+
+ /// <summary>
+ /// Gets a descriptor from the device. See <see cref="DescriptorType"/> for more information.
+ /// </summary>
+ /// <param name="descriptorType">The descriptor type ID to retrieve; this is usually one of the <see cref="DescriptorType"/> enumerations.</param>
+ /// <param name="index">Descriptor index.</param>
+ /// <param name="langId">Descriptor language id.</param>
+ /// <param name="buffer">Memory to store the returned descriptor in.</param>
+ /// <param name="bufferLength">Length of the buffer parameter in bytes.</param>
+ /// <param name="transferLength">The number of bytes transferred to buffer upon success.</param>
+ /// <returns>True on success.</returns>
+ public bool GetDescriptor(byte descriptorType, byte index, short langId, object buffer, int bufferLength, out int transferLength)
+ {
+ PinnedHandle pinned = new PinnedHandle(buffer);
+ bool bSuccess = GetDescriptor(descriptorType, index, langId, pinned.Handle, bufferLength, out transferLength);
+ pinned.Dispose();
+
+ return bSuccess;
+ }
+
+
+ /// <summary>
+ /// Asking for the zero'th index is special - it returns a string
+ /// descriptor that contains all the language IDs supported by the
+ /// device. Typically there aren't many - often only one. The
+ /// language IDs are 16 bit numbers, and they start at the third byte
+ /// in the descriptor. See USB 2.0 specification, section 9.6.7, for
+ /// more information on this.
+ /// </summary>
+ /// <returns>A collection of LCIDs that the current <see cref="UsbDevice"/> supports.</returns>
+ public bool GetLangIDs(out short[] langIDs)
+ {
+ LangStringDescriptor sd = new LangStringDescriptor(UsbDescriptor.Size + (16*sizeof (short)));
+
+ int ret;
+ bool bSuccess = GetDescriptor((byte) DescriptorType.String, 0, 0, sd.Ptr, sd.MaxSize, out ret);
+ if (bSuccess && ret == sd.Length)
+ {
+ bSuccess = sd.Get(out langIDs);
+ }
+ else
+ {
+ langIDs = new short[0];
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "GetLangIDs", this);
+ }
+ sd.Free();
+ return bSuccess;
+ }
+
+ /// <summary>
+ /// Gets a <see cref="DescriptorType.String"/> descriptor from the device.
+ /// </summary>
+ /// <param name="stringData">Buffer to store the returned string in upon success.</param>
+ /// <param name="langId">The language ID to retrieve the string in. (0x409 for english).</param>
+ /// <param name="stringIndex">The string index to retrieve.</param>
+ /// <returns>True on success.</returns>
+ public bool GetString(out string stringData, short langId, byte stringIndex)
+ {
+ stringData = null;
+ int iTransferLength;
+ LangStringDescriptor sd = new LangStringDescriptor(255);
+ bool bSuccess = GetDescriptor((byte) DescriptorType.String, stringIndex, langId, sd.Ptr, sd.MaxSize, out iTransferLength);
+
+ if (bSuccess && iTransferLength > UsbDescriptor.Size && sd.Length == iTransferLength)
+ bSuccess = sd.Get(out stringData);
+ else if (!bSuccess)
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "GetString:GetDescriptor", this);
+ else
+ stringData = String.Empty;
+
+ return bSuccess;
+ }
+
+
+ /// <summary>
+ /// Opens a <see cref="EndpointType.Bulk"/> endpoint for reading
+ /// </summary>
+ /// <param name="readEndpointID">Endpoint number for read operations.</param>
+ /// <returns>A <see cref="UsbEndpointReader"/> class ready for reading. If the specified endpoint is already been opened, the original <see cref="UsbEndpointReader"/> class is returned.</returns>
+ public UsbEndpointReader OpenEndpointReader(ReadEndpointID readEndpointID) { return OpenEndpointReader(readEndpointID, UsbEndpointReader.DefReadBufferSize); }
+
+ /// <summary>
+ /// Opens a <see cref="EndpointType.Bulk"/> endpoint for reading
+ /// </summary>
+ /// <param name="readEndpointID">Endpoint number for read operations.</param>
+ /// <param name="readBufferSize">Size of the read buffer allocated for the <see cref="UsbEndpointReader.DataReceived"/> event.</param>
+ /// <returns>A <see cref="UsbEndpointReader"/> class ready for reading. If the specified endpoint is already been opened, the original <see cref="UsbEndpointReader"/> class is returned.</returns>
+ public UsbEndpointReader OpenEndpointReader(ReadEndpointID readEndpointID, int readBufferSize) { return OpenEndpointReader(readEndpointID, readBufferSize, EndpointType.Bulk); }
+
+ /// <summary>
+ /// Opens an endpoint for reading
+ /// </summary>
+ /// <param name="readEndpointID">Endpoint number for read operations.</param>
+ /// <param name="readBufferSize">Size of the read buffer allocated for the <see cref="UsbEndpointReader.DataReceived"/> event.</param>
+ /// <param name="endpointType">The type of endpoint to open.</param>
+ /// <returns>A <see cref="UsbEndpointReader"/> class ready for reading. If the specified endpoint is already been opened, the original <see cref="UsbEndpointReader"/> class is returned.</returns>
+ public virtual UsbEndpointReader OpenEndpointReader(ReadEndpointID readEndpointID, int readBufferSize, EndpointType endpointType)
+ {
+ foreach (UsbEndpointBase activeEndpoint in mActiveEndpoints)
+ if (activeEndpoint.EpNum == (byte) readEndpointID)
+ return (UsbEndpointReader) activeEndpoint;
+
+ UsbEndpointReader epNew = new UsbEndpointReader(this, readBufferSize, readEndpointID, endpointType);
+ return (UsbEndpointReader) mActiveEndpoints.Add(epNew);
+ }
+
+ /// <summary>
+ /// Gets the selected alternate interface of the specified interface.
+ /// </summary>
+ /// <param name="interfaceID">The interface settings number (index) to retrieve the selected alternate interface setting for.</param>
+ /// <param name="selectedAltInterfaceID">The alternate interface setting selected for use with the specified interface.</param>
+ /// <returns>True on success.</returns>
+ public bool GetAltInterfaceSetting(byte interfaceID, out byte selectedAltInterfaceID)
+ {
+ byte[] buf = new byte[1];
+ int uTransferLength;
+
+ UsbSetupPacket setupPkt = new UsbSetupPacket();
+ setupPkt.RequestType = (byte) UsbEndpointDirection.EndpointIn | (byte) UsbRequestType.TypeStandard |
+ (byte) UsbRequestRecipient.RecipInterface;
+ setupPkt.Request = (byte) UsbStandardRequest.GetInterface;
+ setupPkt.Value = 0;
+ setupPkt.Index = interfaceID;
+ setupPkt.Length = 1;
+
+ bool bSuccess = ControlTransfer(ref setupPkt, buf, buf.Length, out uTransferLength);
+ if (bSuccess && uTransferLength == 1)
+ selectedAltInterfaceID = buf[0];
+ else
+ selectedAltInterfaceID = 0;
+
+ return bSuccess;
+ }
+
+ /// <summary>
+ /// De-initializes the USB driver.
+ /// </summary>
+ /// <remarks>
+ /// If this method is not called before the application exits, it can cause it to hang indefinitely.
+ /// <para>Calling this method multiple times will have no effect.</para>
+ /// </remarks>
+ public static void Exit()
+ {
+ lock (MonoUsbDevice.OLockDeviceList)
+ {
+ if (MonoUsbDevice.mMonoUSBProfileList != null)
+ MonoUsbDevice.mMonoUSBProfileList.Close();
+ MonoUsbDevice.mMonoUSBProfileList = null;
+ }
+ MonoUsbApi.StopAndExit();
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/UsbEndpointReader.cs b/LibWinUsb/UsbEndpointReader.cs
new file mode 100644
index 00000000..0e12d2b9
--- /dev/null
+++ b/LibWinUsb/UsbEndpointReader.cs
@@ -0,0 +1,290 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Windows.Forms;
+using LibUsbDotNet.Internal;
+using LibUsbDotNet.Main;
+
+namespace LibUsbDotNet
+{
+ /// <summary>
+ /// Contains methods for retrieving data from a <see cref="EndpointType.Bulk"/> or <see cref="EndpointType.Interrupt"/> endpoint using the overloaded <see cref="Read(byte[],int,out int)"/> functions or a <see cref="DataReceived"/> event.
+ /// </summary>
+ /// <remarks>
+ /// <list type="bullet">
+ /// <item>Before using the <see cref="DataReceived"/> event, the <see cref="DataReceivedEnabled"/> property must be set to true.</item>
+ /// <item>While the <see cref="DataReceivedEnabled"/> property is True, the overloaded <see cref="Read(byte[],int,out int)"/> functions cannot be used.</item>
+ /// </list>
+ /// </remarks>
+ public class UsbEndpointReader : UsbEndpointBase
+ {
+ private static int mDefReadBufferSize = 4096;
+
+ private bool mDataReceivedEnabled;
+ private int mReadBufferSize;
+ private Thread mReadThread;
+ private ThreadPriority mReadThreadPriority = ThreadPriority.Normal;
+
+ internal UsbEndpointReader(UsbDevice usbDevice, int readBufferSize, ReadEndpointID readEndpointID, EndpointType endpointType)
+ : base(usbDevice, (Byte) readEndpointID, endpointType) { mReadBufferSize = readBufferSize; }
+
+ /// <summary>
+ /// Default read buffer size when using the <see cref="DataReceived"/> event.
+ /// </summary>
+ /// <remarks>
+ /// This value can be bypassed using the second parameter of the <see cref="UsbDevice.OpenEndpointReader(LibUsbDotNet.Main.ReadEndpointID,int)"/> method.
+ /// The default is 4096.
+ /// </remarks>
+ public static int DefReadBufferSize
+ {
+ get { return mDefReadBufferSize; }
+ set { mDefReadBufferSize = value; }
+ }
+
+ /// <summary>
+ /// Gets/Sets a value indicating if the <see cref="UsbEndpointReader.DataReceived"/> event should be used.
+ /// </summary>
+ /// <remarks>
+ /// If DataReceivedEnabled is true the <see cref="Read(byte[] , int , int , int, out int )"/> functions cannot be used.
+ /// </remarks>
+ public virtual bool DataReceivedEnabled
+ {
+ get { return mDataReceivedEnabled; }
+ set
+ {
+ if (value != mDataReceivedEnabled)
+ {
+ StartStopReadThread();
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// Size of the read buffer in bytes for the <see cref="UsbEndpointReader.DataReceived"/> event.
+ /// </summary>
+ /// <remarks>
+ /// Setting a large values, for example 64K will yield a lower number of <see cref="UsbEndpointReader.DataReceived"/> and a higher data rate.
+ /// </remarks>
+ public int ReadBufferSize
+ {
+ get { return mReadBufferSize; }
+ set { mReadBufferSize = value; }
+ }
+
+ /// <summary>
+ /// Gets/Sets the Priority level for the read thread when <see cref="DataReceivedEnabled"/> is true.
+ /// </summary>
+ public ThreadPriority ReadThreadPriority
+ {
+ get { return mReadThreadPriority; }
+ set { mReadThreadPriority = value; }
+ }
+
+
+ /// <summary>
+ /// Reads data from the current <see cref="UsbEndpointReader"/>.
+ /// </summary>
+ /// <param name="buffer">The buffer to store the recieved data in.</param>
+ /// <param name="timeout">Maximum time to wait for the transfer to complete. If the transfer times out, the IO operation will be cancelled.</param>
+ /// <param name="transferLength">Number of bytes actually transferred.</param>
+ /// <returns>
+ /// <see cref="ErrorCode"/>.<see cref="ErrorCode.None"/> on success.
+ /// </returns>
+ public virtual ErrorCode Read(byte[] buffer, int timeout, out int transferLength) { return Read(buffer, 0, buffer.Length, timeout, out transferLength); }
+
+ /// <summary>
+ /// Reads data from the current <see cref="UsbEndpointReader"/>.
+ /// </summary>
+ /// <param name="buffer">The buffer to store the recieved data in.</param>
+ /// <param name="offset">The position in buffer to start storing the data.</param>
+ /// <param name="count">The maximum number of bytes to receive.</param>
+ /// <param name="timeout">Maximum time to wait for the transfer to complete. If the transfer times out, the IO operation will be cancelled.</param>
+ /// <param name="transferLength">Number of bytes actually transferred.</param>
+ /// <returns>
+ /// <see cref="ErrorCode"/>.<see cref="ErrorCode.None"/> on success.
+ /// </returns>
+ public virtual ErrorCode Read(IntPtr buffer, int offset, int count, int timeout, out int transferLength) { return Transfer(buffer, offset, count, timeout, out transferLength); }
+
+ /// <summary>
+ /// Reads data from the current <see cref="UsbEndpointReader"/>.
+ /// </summary>
+ /// <param name="buffer">The buffer to store the recieved data in.</param>
+ /// <param name="offset">The position in buffer to start storing the data.</param>
+ /// <param name="count">The maximum number of bytes to receive.</param>
+ /// <param name="timeout">Maximum time to wait for the transfer to complete. If the transfer times out, the IO operation will be cancelled.</param>
+ /// <param name="transferLength">Number of bytes actually transferred.</param>
+ /// <returns>
+ /// <see cref="ErrorCode"/>.<see cref="ErrorCode.None"/> on success.
+ /// </returns>
+ public virtual ErrorCode Read(byte[] buffer, int offset, int count, int timeout, out int transferLength) { return Transfer(buffer, offset, count, timeout, out transferLength); }
+
+ /// <summary>
+ /// Reads data from the current <see cref="UsbEndpointReader"/>.
+ /// </summary>
+ /// <param name="buffer">The buffer to store the recieved data in.</param>
+ /// <param name="offset">The position in buffer to start storing the data.</param>
+ /// <param name="count">The maximum number of bytes to receive.</param>
+ /// <param name="timeout">Maximum time to wait for the transfer to complete. If the transfer times out, the IO operation will be cancelled.</param>
+ /// <param name="transferLength">Number of bytes actually transferred.</param>
+ /// <returns>
+ /// <see cref="ErrorCode"/>.<see cref="ErrorCode.None"/> on success.
+ /// </returns>
+ public virtual ErrorCode Read(object buffer, int offset, int count, int timeout, out int transferLength) { return Transfer(buffer, offset, count, timeout, out transferLength); }
+
+ /// <summary>
+ /// Reads data from the current <see cref="UsbEndpointReader"/>.
+ /// </summary>
+ /// <param name="buffer">The buffer to store the recieved data in.</param>
+ /// <param name="timeout">Maximum time to wait for the transfer to complete. If the transfer times out, the IO operation will be cancelled.</param>
+ /// <param name="transferLength">Number of bytes actually transferred.</param>
+ /// <returns>
+ /// <see cref="ErrorCode"/>.<see cref="ErrorCode.None"/> on success.
+ /// </returns>
+ public virtual ErrorCode Read(object buffer, int timeout, out int transferLength) { return Transfer(buffer, 0, Marshal.SizeOf(buffer), timeout, out transferLength); }
+
+ /// <summary>
+ /// Reads/discards data from the enpoint until no more data is available.
+ /// </summary>
+ /// <returns>Alwats returns <see cref="ErrorCode.None"/> </returns>
+ public virtual ErrorCode ReadFlush()
+ {
+ byte[] bufDummy = new byte[64];
+ int iTransferred;
+ int iBufCount = 0;
+ while (Read(bufDummy, 10, out iTransferred) == ErrorCode.None && iBufCount < 128)
+ {
+ iBufCount++;
+ }
+
+ return ErrorCode.None;
+ }
+
+
+ private static void ReadData(object context)
+ {
+ UsbTransfer overlappedTransferContext = (UsbTransfer) context;
+ UsbEndpointReader reader = (UsbEndpointReader) overlappedTransferContext.EndpointBase;
+ reader.mDataReceivedEnabled = true;
+ EventHandler<DataReceivedEnabledChangedEventArgs> dataReceivedEnabledChangedEvent;
+
+ dataReceivedEnabledChangedEvent = reader.DataReceivedEnabledChanged;
+ if (!ReferenceEquals(dataReceivedEnabledChangedEvent,null))
+ dataReceivedEnabledChangedEvent(reader, new DataReceivedEnabledChangedEventArgs(reader.mDataReceivedEnabled));
+
+ overlappedTransferContext.Reset();
+
+ byte[] buf = new byte[reader.mReadBufferSize];
+ try
+ {
+ while (!overlappedTransferContext.IsCancelled)
+ {
+ int iTransferLength;
+ ErrorCode eReturn = reader.Transfer(buf, 0, buf.Length, Timeout.Infinite, out iTransferLength);
+ if (eReturn == ErrorCode.None)
+ {
+ EventHandler<EndpointDataEventArgs> temp = reader.DataReceived;
+ if (!ReferenceEquals(temp, null) && !overlappedTransferContext.IsCancelled)
+ {
+ temp(reader, new EndpointDataEventArgs(buf, iTransferLength));
+ }
+ continue;
+ }
+ if (eReturn != ErrorCode.IoTimedOut) break;
+ }
+ }
+ catch (ThreadAbortException)
+ {
+ UsbError.Error(ErrorCode.ReceiveThreadTerminated,0, "ReadData:Read thread aborted.", reader);
+ }
+ finally
+ {
+ reader.Abort();
+ reader.mDataReceivedEnabled = false;
+
+ dataReceivedEnabledChangedEvent = reader.DataReceivedEnabledChanged;
+ if (!ReferenceEquals(dataReceivedEnabledChangedEvent, null))
+ dataReceivedEnabledChangedEvent(reader, new DataReceivedEnabledChangedEventArgs(reader.mDataReceivedEnabled));
+
+ }
+ }
+
+ private void StartReadThread()
+ {
+ mReadThread = new Thread(ReadData);
+ mReadThread.Priority = ReadThreadPriority;
+ mReadThread.Start(TransferContext);
+ Thread.Sleep(1);
+ Application.DoEvents();
+ }
+
+ private bool StopReadThread()
+ {
+ Abort();
+ Thread.Sleep(1);
+ Application.DoEvents();
+ DateTime dtStart = DateTime.Now;
+ while (mReadThread.IsAlive && ((DateTime.Now - dtStart).TotalSeconds < 5)) // 5 sec fail-safe
+ {
+ Thread.Sleep(100);
+ Application.DoEvents();
+ }
+ if (mReadThread.IsAlive)
+ {
+ UsbError.Error(ErrorCode.ReceiveThreadTerminated,0, "Failed stopping read thread.", this);
+ mReadThread.Abort();
+ return false;
+ }
+ return true;
+ }
+
+ private void StartStopReadThread()
+ {
+ if (IsDisposed) throw new ObjectDisposedException(GetType().FullName);
+
+ if (mDataReceivedEnabled)
+ {
+ StopReadThread();
+ }
+ else
+ {
+ StartReadThread();
+ }
+ }
+
+
+ /// <summary>
+ /// The DataReceived Event is fired when new data arrives for the current <see cref="UsbEndpointReader"/>.
+ /// </summary>
+ /// <remarks>To use the DataReceived event, <see cref="DataReceivedEnabled"/> must be set to truw.</remarks>
+ public virtual event EventHandler<EndpointDataEventArgs> DataReceived;
+
+ /// <summary>
+ /// The <see cref="DataReceivedEnabledChanged"/> Event is fired when the <see cref="DataReceived"/> event is started or stopped.
+ /// </summary>
+ public virtual event EventHandler<DataReceivedEnabledChangedEventArgs> DataReceivedEnabledChanged;
+
+ internal override UsbTransfer CreateTransferContext() { return new OverlappedTransferContext(this); }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/UsbEndpointWriter.cs b/LibWinUsb/UsbEndpointWriter.cs
new file mode 100644
index 00000000..05499f88
--- /dev/null
+++ b/LibWinUsb/UsbEndpointWriter.cs
@@ -0,0 +1,100 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Internal;
+using LibUsbDotNet.Main;
+
+namespace LibUsbDotNet
+{
+ /// <summary>Contains methods for writing data to a <see cref="EndpointType.Bulk"/> or <see cref="EndpointType.Interrupt"/> endpoint using the overloaded <see cref="Write(byte[],int,out int)"/> functions.
+ /// </summary>
+ public class UsbEndpointWriter : UsbEndpointBase
+ {
+ internal UsbEndpointWriter(UsbDevice usbDevice, WriteEndpointID writeEndpointID, EndpointType endpointType)
+ : base(usbDevice, (byte)writeEndpointID, endpointType) { }
+
+
+ /// <summary>
+ /// Writes data to the current <see cref="UsbEndpointWriter"/>.
+ /// </summary>
+ /// <param name="buffer">The buffer storing the data to write.</param>
+ /// <param name="timeout">Maximum time to wait for the transfer to complete. If the transfer times out, the IO operation will be cancelled.</param>
+ /// <param name="transferLength">Number of bytes actually transferred.</param>
+ /// <returns>
+ /// <see cref="ErrorCode"/>.<see cref="ErrorCode.None"/> on success.
+ /// </returns>
+ public virtual ErrorCode Write(byte[] buffer, int timeout, out int transferLength) { return Write(buffer, 0, buffer.Length, timeout, out transferLength); }
+
+ /// <summary>
+ /// Writes data to the current <see cref="UsbEndpointWriter"/>.
+ /// </summary>
+ /// <param name="pBuffer">The buffer storing the data to write.</param>
+ /// <param name="offset">The position in buffer to start writing the data from.</param>
+ /// <param name="count">The number of bytes to write.</param>
+ /// <param name="timeout">Maximum time to wait for the transfer to complete. If the transfer times out, the IO operation will be cancelled.</param>
+ /// <param name="transferLength">Number of bytes actually transferred.</param>
+ /// <returns>
+ /// <see cref="ErrorCode"/>.<see cref="ErrorCode.None"/> on success.
+ /// </returns>
+ public virtual ErrorCode Write(IntPtr pBuffer, int offset, int count, int timeout, out int transferLength) { return Transfer(pBuffer, offset, count, timeout, out transferLength); }
+
+ /// <summary>
+ /// Writes data to the current <see cref="UsbEndpointWriter"/>.
+ /// </summary>
+ /// <param name="buffer">The buffer storing the data to write.</param>
+ /// <param name="offset">The position in buffer to start writing the data from.</param>
+ /// <param name="count">The number of bytes to write.</param>
+ /// <param name="timeout">Maximum time to wait for the transfer to complete. If the transfer times out, the IO operation will be cancelled.</param>
+ /// <param name="transferLength">Number of bytes actually transferred.</param>
+ /// <returns>
+ /// <see cref="ErrorCode"/>.<see cref="ErrorCode.None"/> on success.
+ /// </returns>
+ public virtual ErrorCode Write(byte[] buffer, int offset, int count, int timeout, out int transferLength) { return Transfer(buffer, offset, count, timeout, out transferLength); }
+
+ /// <summary>
+ /// Writes data to the current <see cref="UsbEndpointWriter"/>.
+ /// </summary>
+ /// <param name="buffer">The buffer storing the data to write.</param>
+ /// <param name="offset">The position in buffer to start writing the data from.</param>
+ /// <param name="count">The number of bytes to write.</param>
+ /// <param name="timeout">Maximum time to wait for the transfer to complete. If the transfer times out, the IO operation will be cancelled.</param>
+ /// <param name="transferLength">Number of bytes actually transferred.</param>
+ /// <returns>
+ /// <see cref="ErrorCode"/>.<see cref="ErrorCode.None"/> on success.
+ /// </returns>
+ public virtual ErrorCode Write(object buffer, int offset, int count, int timeout, out int transferLength) { return Transfer(buffer, offset, count, timeout, out transferLength); }
+
+ /// <summary>
+ /// Writes data to the current <see cref="UsbEndpointWriter"/>.
+ /// </summary>
+ /// <param name="buffer">The buffer storing the data to write.</param>
+ /// <param name="timeout">Maximum time to wait for the transfer to complete. If the transfer times out, the IO operation will be cancelled.</param>
+ /// <param name="transferLength">Number of bytes actually transferred.</param>
+ /// <returns>
+ /// <see cref="ErrorCode"/>.<see cref="ErrorCode.None"/> on success.
+ /// </returns>
+ public virtual ErrorCode Write(object buffer, int timeout, out int transferLength) { return Write(buffer, 0, Marshal.SizeOf(buffer), timeout, out transferLength); }
+
+ internal override UsbTransfer CreateTransferContext() { return new OverlappedTransferContext(this); }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/UsbGlobals.cs b/LibWinUsb/UsbGlobals.cs
new file mode 100644
index 00000000..f1246df8
--- /dev/null
+++ b/LibWinUsb/UsbGlobals.cs
@@ -0,0 +1,34 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using LibUsbDotNet.LibUsb;
+using LibUsbDotNet.Main;
+
+namespace LibUsbDotNet
+{
+ /// <summary>
+ /// Static class for opening, enumerating and finding USB devices.
+ /// </summary>
+ public static class UsbGlobals
+ {
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/WinUsb/DeviceInformationTypes.cs b/LibWinUsb/WinUsb/DeviceInformationTypes.cs
new file mode 100644
index 00000000..c4c3dd6c
--- /dev/null
+++ b/LibWinUsb/WinUsb/DeviceInformationTypes.cs
@@ -0,0 +1,33 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.WinUsb
+{
+ /// <summary> Types of information that can be retrieved with the WinUsb QueryDevice function.
+ /// </summary>
+ public enum DeviceInformationTypes : byte
+ {
+ /// <summary>
+ /// The device speed.
+ /// </summary>
+ DeviceSpeed = 0x01
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/WinUsb/DeviceSpeedTypes.cs b/LibWinUsb/WinUsb/DeviceSpeedTypes.cs
new file mode 100644
index 00000000..91e85322
--- /dev/null
+++ b/LibWinUsb/WinUsb/DeviceSpeedTypes.cs
@@ -0,0 +1,45 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.WinUsb
+{
+ /// <summary> Device speed types
+ /// </summary>
+ public enum DeviceSpeedTypes : byte
+ {
+ /// <summary>
+ /// Unknown
+ /// </summary>
+ Undefined = 0x00,
+ /// <summary>
+ /// Low speed device.
+ /// </summary>
+ LowSpeed = 0x01,
+ /// <summary>
+ /// Full speed device.
+ /// </summary>
+ FullSpeed = 0x02,
+ /// <summary>
+ /// High speed device.
+ /// </summary>
+ HighSpeed = 0x03,
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/WinUsb/Internal/SafeWinUsbInterfaceHandle.cs b/LibWinUsb/WinUsb/Internal/SafeWinUsbInterfaceHandle.cs
new file mode 100644
index 00000000..c376cbc7
--- /dev/null
+++ b/LibWinUsb/WinUsb/Internal/SafeWinUsbInterfaceHandle.cs
@@ -0,0 +1,67 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.WinUsb.Internal;
+
+namespace LibUsbDotNet.Internal.WinUsb
+{
+ internal class SafeWinUsbInterfaceHandle : SafeHandle
+ {
+ public SafeWinUsbInterfaceHandle()
+ : base(IntPtr.Zero, true) { }
+
+ public SafeWinUsbInterfaceHandle(IntPtr handle)
+ : base(handle, true) { }
+
+ ///<summary>
+ ///Gets a value indicating whether the <see cref="SafeWinUsbInterfaceHandle"/> value is invalid.
+ ///</summary>
+ ///
+ ///<returns>
+ ///true if the <see cref="SafeWinUsbInterfaceHandle"/> is valid; otherwise, false.
+ ///</returns>
+ public override bool IsInvalid
+ {
+ get { return (handle == IntPtr.Zero || handle.ToInt64() == -1); }
+ }
+
+ ///<summary>
+ ///Executes the code required to free the <see cref="SafeWinUsbInterfaceHandle"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///true if the <see cref="SafeWinUsbInterfaceHandle"/> is released successfully; otherwise, in the event of a catastrophic failure, false. In this case, it generates a ReleaseHandleFailed Managed Debugging Assistant.
+ ///</returns>
+ ///
+ protected override bool ReleaseHandle()
+ {
+ bool bSuccess = true;
+ if (!IsInvalid)
+ {
+ bSuccess = WinUsbAPI.WinUsb_Free(handle);
+ handle = IntPtr.Zero;
+ }
+ return bSuccess;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/WinUsb/Internal/WinUsbAPI.cs b/LibWinUsb/WinUsb/Internal/WinUsbAPI.cs
new file mode 100644
index 00000000..cfb994a9
--- /dev/null
+++ b/LibWinUsb/WinUsb/Internal/WinUsbAPI.cs
@@ -0,0 +1,226 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using System.Security;
+using LibUsbDotNet.Descriptors;
+using LibUsbDotNet.Internal;
+using LibUsbDotNet.Internal.WinUsb;
+using LibUsbDotNet.Main;
+using Microsoft.Win32.SafeHandles;
+
+// ReSharper disable InconsistentNaming
+
+namespace LibUsbDotNet.WinUsb.Internal
+{
+ [SuppressUnmanagedCodeSecurity]
+ internal class WinUsbAPI : UsbApiBase
+ {
+ internal const string WIN_USB_DLL = "winusb.dll";
+
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_AbortPipe", SetLastError = true)]
+ private static extern bool WinUsb_AbortPipe([In] SafeHandle InterfaceHandle, byte PipeID);
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_ControlTransfer", SetLastError = true)]
+ private static extern bool WinUsb_ControlTransfer([In] SafeHandle InterfaceHandle,
+ [In] UsbSetupPacket SetupPacket,
+ IntPtr Buffer,
+ int BufferLength,
+ out int LengthTransferred,
+ IntPtr pOVERLAPPED);
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_FlushPipe", SetLastError = true)]
+ private static extern bool WinUsb_FlushPipe([In] SafeHandle InterfaceHandle, byte PipeID);
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_Free", SetLastError = true)]
+ internal static extern bool WinUsb_Free([In] IntPtr InterfaceHandle);
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_GetAssociatedInterface", SetLastError = true)]
+ internal static extern bool WinUsb_GetAssociatedInterface([In] SafeHandle InterfaceHandle,
+ byte AssociatedInterfaceIndex,
+ ref IntPtr AssociatedInterfaceHandle);
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_GetCurrentAlternateSetting", SetLastError = true)]
+ internal static extern bool WinUsb_GetCurrentAlternateSetting([In] SafeHandle InterfaceHandle, out byte SettingNumber);
+
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_GetDescriptor", SetLastError = true)]
+ private static extern bool WinUsb_GetDescriptor([In] SafeHandle InterfaceHandle,
+ byte DescriptorType,
+ byte Index,
+ ushort LanguageID,
+ IntPtr Buffer,
+ int BufferLength,
+ out int LengthTransferred);
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_GetOverlappedResult", SetLastError = true)]
+ private static extern bool WinUsb_GetOverlappedResult([In] SafeHandle InterfaceHandle,
+ IntPtr pOVERLAPPED,
+ out int lpNumberOfBytesTransferred,
+ bool Wait);
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_GetPipePolicy", SetLastError = true)]
+ internal static extern bool WinUsb_GetPipePolicy([In] SafeHandle InterfaceHandle,
+ byte PipeID,
+ PipePolicyType policyType,
+ ref int ValueLength,
+ IntPtr Value);
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_GetPowerPolicy", SetLastError = true)]
+ internal static extern bool WinUsb_GetPowerPolicy([In] SafeHandle InterfaceHandle,
+ PowerPolicyType policyType,
+ ref int ValueLength,
+ IntPtr Value);
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_Initialize", SetLastError = true)]
+ internal static extern bool WinUsb_Initialize([In] SafeHandle DeviceHandle, [Out, In] ref SafeWinUsbInterfaceHandle InterfaceHandle);
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_QueryDeviceInformation", SetLastError = true)]
+ internal static extern bool WinUsb_QueryDeviceInformation([In] SafeHandle InterfaceHandle,
+ DeviceInformationTypes InformationType,
+ ref int BufferLength,
+ [MarshalAs(UnmanagedType.AsAny), In, Out] object Buffer);
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_QueryInterfaceSettings", SetLastError = true)]
+ internal static extern bool WinUsb_QueryInterfaceSettings([In] SafeHandle InterfaceHandle,
+ byte AlternateInterfaceNumber,
+ [MarshalAs(UnmanagedType.LPStruct), In, Out] UsbInterfaceDescriptor
+ UsbAltInterfaceDescriptor);
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_QueryPipe", SetLastError = true)]
+ internal static extern bool WinUsb_QueryPipe([In] SafeHandle InterfaceHandle,
+ byte AlternateInterfaceNumber,
+ byte PipeIndex,
+ [MarshalAs(UnmanagedType.LPStruct), In, Out] PipeInformation PipeInformation);
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_ReadPipe", SetLastError = true)]
+ private static extern bool WinUsb_ReadPipe([In] SafeHandle InterfaceHandle,
+ byte PipeID,
+ Byte[] Buffer,
+ int BufferLength,
+ out int LengthTransferred,
+ IntPtr pOVERLAPPED);
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_ReadPipe", SetLastError = true)]
+ private static extern bool WinUsb_ReadPipe([In] SafeHandle InterfaceHandle,
+ byte PipeID,
+ IntPtr pBuffer,
+ int BufferLength,
+ out int LengthTransferred,
+ IntPtr pOVERLAPPED);
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_ResetPipe", SetLastError = true)]
+ private static extern bool WinUsb_ResetPipe([In] SafeHandle InterfaceHandle, byte PipeID);
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_SetPipePolicy", SetLastError = true)]
+ internal static extern bool WinUsb_SetPipePolicy([In] SafeHandle InterfaceHandle,
+ byte PipeID,
+ PipePolicyType policyType,
+ int ValueLength,
+ IntPtr Value);
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_SetPowerPolicy", SetLastError = true)]
+ internal static extern bool WinUsb_SetPowerPolicy([In] SafeHandle InterfaceHandle, PowerPolicyType policyType, int ValueLength, IntPtr Value);
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_WritePipe", SetLastError = true)]
+ private static extern bool WinUsb_WritePipe([In] SafeHandle InterfaceHandle,
+ byte PipeID,
+ Byte[] Buffer,
+ int BufferLength,
+ out int LengthTransferred,
+ IntPtr pOVERLAPPED);
+
+ [DllImport(WIN_USB_DLL, EntryPoint = "WinUsb_WritePipe", SetLastError = true)]
+ private static extern bool WinUsb_WritePipe([In] SafeHandle InterfaceHandle,
+ byte PipeID,
+ IntPtr pBuffer,
+ int BufferLength,
+ out int LengthTransferred,
+ IntPtr pOVERLAPPED);
+
+
+ public override bool AbortPipe(SafeHandle InterfaceHandle, byte PipeID) { return WinUsb_AbortPipe(InterfaceHandle, PipeID); }
+
+ public override bool ControlTransfer(SafeHandle InterfaceHandle,
+ UsbSetupPacket SetupPacket,
+ IntPtr Buffer,
+ int BufferLength,
+ out int LengthTransferred) { return WinUsb_ControlTransfer(InterfaceHandle, SetupPacket, Buffer, BufferLength, out LengthTransferred, IntPtr.Zero); }
+
+ public override bool FlushPipe(SafeHandle InterfaceHandle, byte PipeID) { return WinUsb_FlushPipe(InterfaceHandle, PipeID); }
+
+ public override bool GetDescriptor(SafeHandle InterfaceHandle,
+ byte DescriptorType,
+ byte Index,
+ ushort LanguageID,
+ IntPtr Buffer,
+ int BufferLength,
+ out int LengthTransferred) { return WinUsb_GetDescriptor(InterfaceHandle, DescriptorType, Index, LanguageID, Buffer, BufferLength, out LengthTransferred); }
+
+ public override bool GetOverlappedResult(SafeHandle InterfaceHandle, IntPtr pOVERLAPPED, out int numberOfBytesTransferred, bool Wait) { return WinUsb_GetOverlappedResult(InterfaceHandle, pOVERLAPPED, out numberOfBytesTransferred, Wait); }
+
+ //public override bool ReadPipe(UsbEndpointBase endPointBase,
+ // byte[] Buffer,
+ // int BufferLength,
+ // out int LengthTransferred,
+ // int isoPacketSize,
+ // IntPtr pOVERLAPPED) { return WinUsb_ReadPipe(endPointBase.Device.Handle, endPointBase.EpNum, Buffer, BufferLength, out LengthTransferred, pOVERLAPPED); }
+
+ public override bool ReadPipe(UsbEndpointBase endPointBase,
+ IntPtr pBuffer,
+ int BufferLength,
+ out int LengthTransferred,
+ int isoPacketSize,
+ IntPtr pOVERLAPPED) { return WinUsb_ReadPipe(endPointBase.Device.Handle, endPointBase.EpNum, pBuffer, BufferLength, out LengthTransferred, pOVERLAPPED); }
+
+ public override bool ResetPipe(SafeHandle InterfaceHandle, byte PipeID) { return WinUsb_ResetPipe(InterfaceHandle, PipeID); }
+
+ //public override bool WritePipe(UsbEndpointBase endPointBase,
+ // byte[] Buffer,
+ // int BufferLength,
+ // out int LengthTransferred,
+ // int isoPacketSize,
+ // IntPtr pOVERLAPPED) { return WinUsb_WritePipe(endPointBase.Device.Handle, endPointBase.EpNum, Buffer, BufferLength, out LengthTransferred, pOVERLAPPED); }
+
+ public override bool WritePipe(UsbEndpointBase endPointBase,
+ IntPtr pBuffer,
+ int BufferLength,
+ out int LengthTransferred,
+ int isoPacketSize,
+ IntPtr pOVERLAPPED) { return WinUsb_WritePipe(endPointBase.Device.Handle, endPointBase.EpNum, pBuffer, BufferLength, out LengthTransferred, pOVERLAPPED); }
+
+ internal static bool OpenDevice(out SafeFileHandle sfhDevice, string DevicePath)
+ {
+ sfhDevice =
+ Kernel32.CreateFile(DevicePath,
+ NativeFileAccess.FILE_GENERIC_WRITE | NativeFileAccess.FILE_GENERIC_READ,
+ NativeFileShare.FILE_SHARE_WRITE | NativeFileShare.FILE_SHARE_READ,
+ IntPtr.Zero,
+ NativeFileMode.OPEN_EXISTING,
+ NativeFileFlag.FILE_ATTRIBUTE_NORMAL | NativeFileFlag.FILE_FLAG_OVERLAPPED,
+ IntPtr.Zero);
+
+ return (!sfhDevice.IsInvalid && !sfhDevice.IsClosed);
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/WinUsb/PipeInformation.cs b/LibWinUsb/WinUsb/PipeInformation.cs
new file mode 100644
index 00000000..793c28c2
--- /dev/null
+++ b/LibWinUsb/WinUsb/PipeInformation.cs
@@ -0,0 +1,57 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Main;
+
+namespace LibUsbDotNet.WinUsb
+{
+ /// <summary> WinUsb Pipe information.
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public class PipeInformation
+ {
+ /// <summary>
+ /// Size of the structure in bytes.
+ /// </summary>
+ public static readonly int Size = Marshal.SizeOf(typeof (PipeInformation));
+
+ /// <summary>
+ /// Specifies the pipe type.
+ /// </summary>
+ public EndpointType PipeType;
+
+ /// <summary>
+ /// The pipe identifier (ID).
+ /// </summary>
+ public byte PipeId;
+
+ /// <summary>
+ /// The maximum size, in bytes, of the packets that are transmitted on the pipe.
+ /// </summary>
+ public short MaximumPacketSize;
+
+ /// <summary>
+ /// The pipe interval.
+ /// </summary>
+ public byte Interval;
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/WinUsb/PipePolicies.cs b/LibWinUsb/WinUsb/PipePolicies.cs
new file mode 100644
index 00000000..52bd2feb
--- /dev/null
+++ b/LibWinUsb/WinUsb/PipePolicies.cs
@@ -0,0 +1,288 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Main;
+using LibUsbDotNet.WinUsb.Internal;
+
+namespace LibUsbDotNet.WinUsb
+{
+ /// <summary> Endpoint specific policies. <see cref="WinUsbDevice.EndpointPolicies(ReadEndpointID)"/>.
+ /// </summary>
+ public class PipePolicies
+ {
+ private const int MAX_SIZE = 4;
+ private readonly byte mEpNum;
+ private readonly SafeHandle mUsbHandle;
+
+ private IntPtr mBufferPtr = IntPtr.Zero;
+
+ internal PipePolicies(SafeHandle usbHandle, byte epNum)
+ {
+ mBufferPtr = Marshal.AllocCoTaskMem(MAX_SIZE);
+ mEpNum = epNum;
+ mUsbHandle = usbHandle;
+ }
+
+ /// <summary>
+ /// If the allow partial reads policy parameter is FALSE (that is, zero), the read request fails whenever the device returns more data than the client requested.
+ /// If the allow partial reads policy parameter is TRUE, the WinUSB driver saves the extra data and sends the extra data to the client during the client's next read.
+ /// The default value of the allow partial reads policy parameter is TRUE.
+ /// </summary>
+ public bool AllowPartialReads
+ {
+ get
+ {
+ int iValueLength = 1;
+ Marshal.WriteByte(mBufferPtr, 0);
+ bool bSuccess = GetPipePolicy(PipePolicyType.AllowPartialReads, ref iValueLength, mBufferPtr);
+ if (bSuccess)
+ return Marshal.ReadByte(mBufferPtr) == 0 ? false : true;
+ return false;
+ }
+ set
+ {
+ int iValueLength = 1;
+ byte bPipePolicyValue = (value) ? (byte) 1 : (byte) 0;
+ Marshal.WriteByte(mBufferPtr, bPipePolicyValue);
+ SetPipePolicy(PipePolicyType.AllowPartialReads, iValueLength, mBufferPtr);
+ }
+ }
+
+ /// <summary>
+ /// If the short packet terminate policy parameter is TRUE (that is, nonzero), every write request that is a multiple of the maximum packet size for the endpoint is terminated with a zero-length packet.
+ /// The default value of the short packet terminate policy parameter is FALSE.
+ /// </summary>
+ public bool ShortPacketTerminate
+ {
+ get
+ {
+ int iValueLength = 1;
+ Marshal.WriteByte(mBufferPtr, 0);
+ bool bSuccess = GetPipePolicy(PipePolicyType.ShortPacketTerminate, ref iValueLength, mBufferPtr);
+ if (bSuccess)
+ return Marshal.ReadByte(mBufferPtr) == 0 ? false : true;
+ return false;
+ }
+ set
+ {
+ int iValueLength = 1;
+ byte bPipePolicyValue = (value) ? (byte) 1 : (byte) 0;
+ Marshal.WriteByte(mBufferPtr, bPipePolicyValue);
+ SetPipePolicy(PipePolicyType.ShortPacketTerminate, iValueLength, mBufferPtr);
+ }
+ }
+
+ /// <summary>
+ /// If the auto clear stall policy parameter is TRUE (that is, nonzero), the driver fails stalled data transfers, but the driver clears the stall condition automatically, and data continues to flow on the pipe. This policy parameter does not affect control pipes.
+ /// The default value for the auto clear stall policy parameter is FALSE.
+ /// </summary>
+ public bool AutoClearStall
+ {
+ get
+ {
+ int iValueLength = 1;
+ Marshal.WriteByte(mBufferPtr, 0);
+ bool bSuccess = GetPipePolicy(PipePolicyType.AutoClearStall, ref iValueLength, mBufferPtr);
+ if (bSuccess)
+ return Marshal.ReadByte(mBufferPtr) == 0 ? false : true;
+ return false;
+ }
+ set
+ {
+ int iValueLength = 1;
+ byte bPipePolicyValue = (value) ? (byte) 1 : (byte) 0;
+ Marshal.WriteByte(mBufferPtr, bPipePolicyValue);
+ SetPipePolicy(PipePolicyType.AutoClearStall, iValueLength, mBufferPtr);
+ }
+ }
+
+
+ ///<summary>
+ /// The auto flush policy parameter works with allow partial reads. If allow partial reads is FALSE, the WinUSB driver ignores the value of auto flush. If allow partial reads is TRUE, the value of auto flush determines what the WinUSB driver does when the device returns more data than the client requested.
+ /// If both allow partial reads and auto flush policy parameters are TRUE (that is, nonzero) and the device returns more data than the client requested, the remaining data is discarded. If allow partial reads is TRUE, but auto flush is FALSE, the WinUSB driver caches the extra data and sends it to the client in the next read operation.
+ /// The default value of the auto flush policy parameter is FALSE.
+ ///</summary>
+ public bool AutoFlush
+ {
+ get
+ {
+ int iValueLength = 1;
+ Marshal.WriteByte(mBufferPtr, 0);
+ bool bSuccess = GetPipePolicy(PipePolicyType.AutoFlush, ref iValueLength, mBufferPtr);
+ if (bSuccess)
+ return Marshal.ReadByte(mBufferPtr) == 0 ? false : true;
+ return false;
+ }
+ set
+ {
+ int iValueLength = 1;
+ byte bPipePolicyValue = (value) ? (byte) 1 : (byte) 0;
+ Marshal.WriteByte(mBufferPtr, bPipePolicyValue);
+ SetPipePolicy(PipePolicyType.AutoFlush, iValueLength, mBufferPtr);
+ }
+ }
+
+ /// <summary>
+ /// If the ignore short packets policy parameter is TRUE (that is, nonzero), the host does not complete a read operation after it receives a short packet. Instead, the the host completes the operation only after the host has read the specified number of bytes.
+ /// If the ignore short packets policy parameter is FALSE, the host completes a read operation when either the host has read the specified number of bytes or the host has received a short packet.
+ /// The default value of the ignore short packets policy parameter is FALSE.
+ /// </summary>
+ public bool IgnoreShortPackets
+ {
+ get
+ {
+ int iValueLength = 1;
+ Marshal.WriteByte(mBufferPtr, 0);
+ bool bSuccess = GetPipePolicy(PipePolicyType.IgnoreShortPackets, ref iValueLength, mBufferPtr);
+ if (bSuccess)
+ return Marshal.ReadByte(mBufferPtr) == 0 ? false : true;
+ return false;
+ }
+ set
+ {
+ int iValueLength = 1;
+ byte bPipePolicyValue = (value) ? (byte) 1 : (byte) 0;
+ Marshal.WriteByte(mBufferPtr, bPipePolicyValue);
+ SetPipePolicy(PipePolicyType.IgnoreShortPackets, iValueLength, mBufferPtr);
+ }
+ }
+
+ /// <summary>
+ /// If the raw i/o policy parameter is TRUE (that is, nonzero), calls to WinUsb_ReadPipe and WinUsb_WritePipe for the specified endpoint must satisfy the following conditions:
+ /// The buffer length must be a multiple of the maximum endpoint packet size.
+ /// The length must be less than what the host controller supports.
+ /// If the preceding conditions are met, WinUSB sends data directly to the USB driver stack, bypassing WinUSB's queuing and error handling.
+ /// If the raw i/o policy parameter is FALSE, no restrictions are imposed on the buffers that are passed to WinUsb_ReadPipe and WinUsb_WritePipe.
+ /// The default value of the raw i/o policy parameter is FALSE.
+ /// </summary>
+ public bool RawIo
+ {
+ get
+ {
+ int iValueLength = 1;
+ Marshal.WriteByte(mBufferPtr, 0);
+ bool bSuccess = GetPipePolicy(PipePolicyType.RawIo, ref iValueLength, mBufferPtr);
+ if (bSuccess)
+ return Marshal.ReadByte(mBufferPtr) == 0 ? false : true;
+ return false;
+ }
+ set
+ {
+ int iValueLength = 1;
+ byte bPipePolicyValue = (value) ? (byte) 1 : (byte) 0;
+ Marshal.WriteByte(mBufferPtr, bPipePolicyValue);
+ SetPipePolicy(PipePolicyType.RawIo, iValueLength, mBufferPtr);
+ }
+ }
+
+ /// <summary>
+ /// The pipe transfer timeout policy parameter specifies the time-out interval, in milliseconds. The host cancels transfers that do not complete within the time-out interval. A value of zero means that transfers do not time out.
+ /// By default, the time-out value is zero, and the host never cancels a transfer because of a time-out.
+ /// </summary>
+ public int PipeTransferTimeout
+ {
+ get
+ {
+ int iValueLength = 4;
+ Marshal.WriteInt32(mBufferPtr, 0);
+ bool bSuccess = GetPipePolicy(PipePolicyType.PipeTransferTimeout, ref iValueLength, mBufferPtr);
+ if (bSuccess)
+ return Marshal.ReadInt32(mBufferPtr);
+ return -1;
+ }
+ set
+ {
+ int iValueLength = 4;
+ Marshal.WriteInt32(mBufferPtr, value);
+ SetPipePolicy(PipePolicyType.PipeTransferTimeout, iValueLength, mBufferPtr);
+ }
+ }
+
+ /// <summary>
+ /// The maximum number of bytes that can be transferred at once.
+ /// </summary>
+ public int MaxTransferSize
+ {
+ get
+ {
+ int iValueLength = 4;
+ Marshal.WriteInt32(mBufferPtr, 0);
+ bool bSuccess = GetPipePolicy(PipePolicyType.MaximumTransferSize, ref iValueLength, mBufferPtr);
+ if (bSuccess)
+ return Marshal.ReadInt32(mBufferPtr);
+ return -1;
+ }
+ }
+
+
+ ///<summary>
+ ///Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
+ ///</summary>
+ ///
+ ///<returns>
+ ///A <see cref="System.String"/> that represents the current <see cref="T:System.Object"/>.
+ ///</returns>
+ public override string ToString()
+ {
+ object[] o = new object[]
+ {
+ AllowPartialReads, ShortPacketTerminate, AutoClearStall, AutoFlush, IgnoreShortPackets, RawIo, PipeTransferTimeout,
+ MaxTransferSize
+ };
+ return
+ string.Format(
+ "AllowPartialReads:{0}\r\nShortPacketTerminate:{1}\r\nAutoClearStall:{2}\r\nAutoFlush:{3}\r\nIgnoreShortPackets:{4}\r\nRawIO:{5}\r\nPipeTransferTimeout:{6}\r\nMaxTransferSize:{7}\r\n",
+ o);
+ }
+
+
+ internal bool GetPipePolicy(PipePolicyType policyType, ref int valueLength, IntPtr pBuffer)
+ {
+ bool bSuccess = WinUsbAPI.WinUsb_GetPipePolicy(mUsbHandle, mEpNum, policyType, ref valueLength, pBuffer);
+
+ if (!bSuccess) UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "GetPipePolicy", this);
+
+ return bSuccess;
+ }
+
+ internal bool SetPipePolicy(PipePolicyType policyType, int valueLength, IntPtr pBuffer)
+ {
+ bool bSuccess = WinUsbAPI.WinUsb_SetPipePolicy(mUsbHandle, mEpNum, policyType, valueLength, pBuffer);
+
+ if (!bSuccess) UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "SetPipePolicy", this);
+
+ return bSuccess;
+ }
+
+ /// <summary>
+ /// Frees instance resources.
+ /// </summary>
+ ~PipePolicies()
+ {
+ if (mBufferPtr != IntPtr.Zero)
+ Marshal.FreeCoTaskMem(mBufferPtr);
+
+ mBufferPtr = IntPtr.Zero;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/WinUsb/PipePolicyType.cs b/LibWinUsb/WinUsb/PipePolicyType.cs
new file mode 100644
index 00000000..eb74a8e1
--- /dev/null
+++ b/LibWinUsb/WinUsb/PipePolicyType.cs
@@ -0,0 +1,35 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.WinUsb
+{
+ internal enum PipePolicyType : byte
+ {
+ ShortPacketTerminate = 0x01,
+ AutoClearStall = 0x02,
+ PipeTransferTimeout = 0x03,
+ IgnoreShortPackets = 0x04,
+ AllowPartialReads = 0x05,
+ AutoFlush = 0x06,
+ RawIo = 0x07,
+ MaximumTransferSize = 0x08,
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/WinUsb/PowerPolicies.cs b/LibWinUsb/WinUsb/PowerPolicies.cs
new file mode 100644
index 00000000..2b59c5c8
--- /dev/null
+++ b/LibWinUsb/WinUsb/PowerPolicies.cs
@@ -0,0 +1,98 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Runtime.InteropServices;
+
+namespace LibUsbDotNet.WinUsb
+{
+ /// <summary>
+ /// power policy for a <see cref="WinUsbDevice"/>.
+ /// </summary>
+ public class PowerPolicies
+ {
+ private const int MAX_SIZE = 4;
+ private readonly WinUsbDevice mUsbDevice;
+ private IntPtr mBufferPtr = IntPtr.Zero;
+
+ internal PowerPolicies(WinUsbDevice usbDevice)
+ {
+ mBufferPtr = Marshal.AllocCoTaskMem(MAX_SIZE);
+ mUsbDevice = usbDevice;
+ }
+
+ /// <summary>
+ /// If the auto suspend policy parameter is TRUE (that is, nonzero), the USB stack suspends the device when no transfers are pending. The default value for the AutoSuspend policy parameter is TRUE.
+ /// </summary>
+ public bool AutoSuspend
+ {
+ get
+ {
+ int iValueLength = 1;
+ Marshal.WriteByte(mBufferPtr, 0);
+ bool bSuccess = mUsbDevice.GetPowerPolicy(PowerPolicyType.AutoSuspend, ref iValueLength, mBufferPtr);
+ if (bSuccess)
+ return Marshal.ReadByte(mBufferPtr) == 0 ? false : true;
+ return false;
+ }
+ set
+ {
+ int iValueLength = 1;
+ byte bPowerPolicyValue = (value) ? (byte) 1 : (byte) 0;
+ Marshal.WriteByte(mBufferPtr, bPowerPolicyValue);
+ mUsbDevice.SetPowerPolicy(PowerPolicyType.AutoSuspend, iValueLength, mBufferPtr);
+ }
+ }
+
+ /// <summary>
+ /// The suspend delay policy parameter specifies the minimum amount of time, in milliseconds, that the WinUSB driver must wait after any transfer before it can suspend the device.
+ /// </summary>
+ public int SuspendDelay
+ {
+ get
+ {
+ int iValueLength = Marshal.SizeOf(typeof (int));
+ Marshal.WriteInt32(mBufferPtr, 0);
+ bool bSuccess = mUsbDevice.GetPowerPolicy(PowerPolicyType.SuspendDelay, ref iValueLength, mBufferPtr);
+ if (bSuccess)
+ return Marshal.ReadInt32(mBufferPtr);
+ return -1;
+ }
+ set
+ {
+ int iValueLength = Marshal.SizeOf(typeof (int));
+ Marshal.WriteInt32(mBufferPtr, value);
+ mUsbDevice.SetPowerPolicy(PowerPolicyType.SuspendDelay, iValueLength, mBufferPtr);
+ }
+ }
+
+ /// <summary>
+ /// Frees instance resources.
+ /// </summary>
+ ~PowerPolicies()
+ {
+ if (mBufferPtr != IntPtr.Zero)
+ Marshal.FreeCoTaskMem(mBufferPtr);
+
+ mBufferPtr = IntPtr.Zero;
+ }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/WinUsb/PowerPolicyType.cs b/LibWinUsb/WinUsb/PowerPolicyType.cs
new file mode 100644
index 00000000..18dff208
--- /dev/null
+++ b/LibWinUsb/WinUsb/PowerPolicyType.cs
@@ -0,0 +1,30 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+namespace LibUsbDotNet.WinUsb
+{
+ internal enum PowerPolicyType : byte
+ {
+ AutoSuspend = 0x81,
+ EnableWake = 0x82,
+ SuspendDelay = 0x83,
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/WinUsb/WinUsbDevice.cs b/LibWinUsb/WinUsb/WinUsbDevice.cs
new file mode 100644
index 00000000..55ac2cd0
--- /dev/null
+++ b/LibWinUsb/WinUsb/WinUsbDevice.cs
@@ -0,0 +1,317 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using LibUsbDotNet.Descriptors;
+using LibUsbDotNet.Internal;
+using LibUsbDotNet.Internal.WinUsb;
+using LibUsbDotNet.Main;
+using LibUsbDotNet.WinUsb.Internal;
+using Microsoft.Win32.SafeHandles;
+
+namespace LibUsbDotNet.WinUsb
+{
+ /// <summary>
+ /// Contains members specific to Microsofts WinUSB driver.
+ /// </summary>
+ /// <remarks>
+ /// A <see cref="WinUsbDevice"/> should be thought of as a part of, or an interface of a USB device.
+ /// The <see cref="WinUsbDevice"/> class does not have members for selecting configurations and
+ /// intefaces. This is done at a lower level by the winusb driver depending on which interface the
+ /// <see cref="WinUsbDevice"/> belongs to.
+ /// </remarks>
+ public class WinUsbDevice : UsbDevice, IUsbInterface
+ {
+ private readonly string mDevicePath;
+ private PowerPolicies mPowerPolicies;
+ private SafeFileHandle mSafeDevHandle;
+
+ internal WinUsbDevice(UsbApiBase usbApi,
+ SafeFileHandle usbHandle,
+ SafeHandle handle,
+ string devicePath)
+ : base(usbApi, handle)
+ {
+ mDevicePath = devicePath;
+ mSafeDevHandle = usbHandle;
+ mPowerPolicies = new PowerPolicies(this);
+ }
+
+ /// <summary>
+ /// Gets the power policies for this <see cref="WinUsbDevice"/>.
+ /// </summary>
+ public PowerPolicies PowerPolicy
+ {
+ get { return mPowerPolicies; }
+ }
+
+ /// <summary>
+ /// Gets the device path used to open this <see cref="WinUsbDevice"/>.
+ /// </summary>
+ public string DevicePath
+ {
+ get { return mDevicePath; }
+ }
+
+ #region IUsbInterface Members
+
+ /// <summary>
+ /// Returns the DriverMode this USB device is using.
+ /// </summary>
+ public override DriverModeType DriverMode
+ {
+ get { return DriverModeType.WinUsb; }
+ }
+
+ /// <summary>
+ /// Closes the <see cref="UsbDevice"/> and disposes any <see cref="UsbDevice.ActiveEndpoints"/>.
+ /// </summary>
+ /// <returns>True on success.</returns>
+ public override bool Close()
+ {
+ if (IsOpen)
+ {
+ ActiveEndpoints.Clear();
+ mUsbHandle.Close();
+
+ if (mSafeDevHandle != null)
+ if (!mSafeDevHandle.IsClosed)
+ mSafeDevHandle.Close();
+ }
+ return true;
+ }
+
+ ///<summary>
+ /// Opens the USB device handle.
+ ///</summary>
+ ///<returns>
+ ///True if the device is already opened or was opened successfully.
+ ///False if the device does not exists or is no longer valid.
+ ///</returns>
+ public override bool Open()
+ {
+ if (IsOpen) return true;
+
+ SafeFileHandle sfhDev;
+
+ bool bSuccess = WinUsbAPI.OpenDevice(out sfhDev, mDevicePath);
+ if (bSuccess)
+ {
+ SafeWinUsbInterfaceHandle handle = new SafeWinUsbInterfaceHandle();
+ if ((bSuccess = WinUsbAPI.WinUsb_Initialize(sfhDev, ref handle)))
+ {
+ mSafeDevHandle = sfhDev;
+ mUsbHandle = handle;
+ mPowerPolicies = new PowerPolicies(this);
+ }
+ else
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "Open:Initialize", typeof (UsbDevice));
+ }
+ else
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "Open", typeof(UsbDevice));
+
+
+ return bSuccess;
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Opens a WinUsb directly from the user supplied device path.
+ /// </summary>
+ /// <param name="devicePath">Device path (symbolic link) of the WinUsb device to open.</param>
+ /// <param name="usbDevice">Returns an opened WinUsb device on success, null on failure.</param>
+ /// <returns>True on success.</returns>
+ public static bool Open(string devicePath, out WinUsbDevice usbDevice)
+ {
+ usbDevice = null;
+
+ SafeFileHandle sfhDev;
+
+ bool bSuccess = WinUsbAPI.OpenDevice(out sfhDev, devicePath);
+ if (bSuccess)
+ {
+ SafeWinUsbInterfaceHandle handle = new SafeWinUsbInterfaceHandle();
+ bSuccess = WinUsbAPI.WinUsb_Initialize(sfhDev, ref handle);
+ if (bSuccess)
+ {
+ usbDevice = new WinUsbDevice(WinUsbApi, sfhDev, handle, devicePath);
+ }
+ else
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "Open:Initialize", typeof(UsbDevice));
+ }
+ else
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "Open", typeof(UsbDevice));
+
+
+ return bSuccess;
+ }
+
+ /// <summary>
+ /// Gets endpoint policies for the specified endpoint id.
+ /// </summary>
+ /// <param name="epNum">The endpoint ID to retrieve <see cref="PipePolicies"/> for.</param>
+ /// <returns>A <see cref="PipePolicies"/> class.</returns>
+ public PipePolicies EndpointPolicies(ReadEndpointID epNum) { return new PipePolicies(mUsbHandle, (byte) epNum); }
+
+ /// <summary>
+ /// Gets endpoint policies for the specified endpoint id.
+ /// </summary>
+ /// <param name="epNum">The endpoint ID to retrieve <see cref="PipePolicies"/> for.</param>
+ /// <returns>A <see cref="PipePolicies"/> class.</returns>
+ public PipePolicies EndpointPolicies(WriteEndpointID epNum) { return new PipePolicies(mUsbHandle, (byte) epNum); }
+
+ /// <summary>
+ /// Gets an interface associated with this <see cref="WinUsbDevice"/>.
+ /// </summary>
+ /// <param name="associatedInterfaceIndex">The index to retrieve. (0 = next interface, 1= interface after next, etc.).</param>
+ /// <param name="usbDevice">A new <see cref="WinUsbDevice"/> class for the specified AssociatedInterfaceIndex.</param>
+ /// <returns>True on success.</returns>
+ public bool GetAssociatedInterface(byte associatedInterfaceIndex, out WinUsbDevice usbDevice)
+ {
+ usbDevice = null;
+ IntPtr pHandle = IntPtr.Zero;
+ bool bSuccess = WinUsbAPI.WinUsb_GetAssociatedInterface(mUsbHandle, associatedInterfaceIndex, ref pHandle);
+ if (bSuccess)
+ {
+ SafeWinUsbInterfaceHandle tempHandle = new SafeWinUsbInterfaceHandle(pHandle);
+
+ usbDevice = new WinUsbDevice(mUsbApi, null, tempHandle, mDevicePath);
+ }
+ if (!bSuccess)
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "GetAssociatedInterface", this);
+
+ return bSuccess;
+ }
+
+ /// <summary>
+ /// Gets the currently selected alternate settings number for the selected inteface.
+ /// </summary>
+ /// <param name="settingNumber">The selected AlternateSetting number.</param>
+ /// <returns>True on success.</returns>
+ public bool GetCurrentAlternateSetting(out byte settingNumber)
+ {
+ bool bSuccess;
+ //settingNumber = 0;
+ //if (LockDevice() != ErrorCode.None) return false;
+
+ //try
+ //{
+ bSuccess = WinUsbAPI.WinUsb_GetCurrentAlternateSetting(mUsbHandle, out settingNumber);
+
+ if (!bSuccess)
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "GetCurrentAlternateSetting", this);
+ //}
+ //finally
+ //{
+ // UnlockDevice();
+ //}
+
+
+ return bSuccess;
+ }
+
+ /// <summary>
+ /// Gets the device speed.
+ /// </summary>
+ /// <param name="deviceSpeed">The device speed.</param>
+ /// <returns>True on success.</returns>
+ public bool QueryDeviceSpeed(out DeviceSpeedTypes deviceSpeed)
+ {
+ deviceSpeed = DeviceSpeedTypes.Undefined;
+ byte[] buf = new byte[1];
+ int uTransferLength = 1;
+ bool bSuccess = WinUsbAPI.WinUsb_QueryDeviceInformation(mUsbHandle, DeviceInformationTypes.DeviceSpeed, ref uTransferLength, buf);
+
+ if (bSuccess)
+ {
+ deviceSpeed = (DeviceSpeedTypes) buf[0];
+ }
+ else
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "QueryDeviceInformation:QueryDeviceSpeed", this);
+
+ return bSuccess;
+ }
+
+ /// <summary>
+ /// Gets a <see cref="UsbInterfaceDescriptor"/> for the specified AlternateInterfaceNumber,
+ /// </summary>
+ /// <param name="alternateInterfaceNumber">The alternate interface index for the <see cref="UsbInterfaceDescriptor"/> to retrieve. </param>
+ /// <param name="usbAltInterfaceDescriptor">The <see cref="UsbInterfaceDescriptor"/> for the specified AlternateInterfaceNumber.</param>
+ /// <returns>True on success.</returns>
+ public bool QueryInterfaceSettings(byte alternateInterfaceNumber, ref UsbInterfaceDescriptor usbAltInterfaceDescriptor)
+ {
+ bool bSuccess;
+ //if (mSemDeviceLock != null)
+ //{
+ // if (LockDevice() != ErrorCode.None) return false;
+ //}
+
+ //try
+ //{
+ bSuccess = WinUsbAPI.WinUsb_QueryInterfaceSettings(Handle, alternateInterfaceNumber, usbAltInterfaceDescriptor);
+ if (!bSuccess)
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "QueryInterfaceSettings", this);
+ //}
+ //finally
+ //{
+ // if (mSemDeviceLock != null) UnlockDevice();
+ //}
+
+ return bSuccess;
+ }
+
+ internal bool GetPowerPolicy(PowerPolicyType policyType, ref int valueLength, IntPtr pBuffer)
+ {
+ bool bSuccess = WinUsbAPI.WinUsb_GetPowerPolicy(mUsbHandle, policyType, ref valueLength, pBuffer);
+
+ if (!bSuccess)
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "GetPowerPolicy", this);
+
+ return bSuccess;
+ }
+
+ /// <summary>
+ /// Gets a list a valid, connected WinUSB device inteface paths for the a given WinUSB device interface guid.
+ /// </summary>
+ /// <param name="interfaceGuid">A WinUSB DeviceInterfaceGUID. This is set in the usb devices inf file when the drivers for it are installed.</param>
+ /// <param name="devicePathList">A list of connected WinUSB device inteface paths.</param>
+ /// <returns>True if one or more device paths were found. False if no devices are found or an error occured. <see cref="UsbDevice.UsbErrorEvent"/> </returns>
+ public static bool GetDevicePathList(Guid interfaceGuid, out List<String> devicePathList) { return WinUsbRegistry.GetDevicePathList(interfaceGuid, out devicePathList); }
+
+ internal bool SetPowerPolicy(PowerPolicyType policyType, int valueLength, IntPtr pBuffer)
+ {
+ bool bSuccess = WinUsbAPI.WinUsb_SetPowerPolicy(mUsbHandle, policyType, valueLength, pBuffer);
+
+ if (!bSuccess)
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "SetPowerPolicy", this);
+
+ return bSuccess;
+ }
+
+ /// <summary>
+ /// Closes the device. <see cref="WinUsbDevice.Close"/>.
+ /// </summary>
+ ~WinUsbDevice() { Close(); }
+ }
+} \ No newline at end of file
diff --git a/LibWinUsb/WinUsb/WinUsbRegistry.cs b/LibWinUsb/WinUsb/WinUsbRegistry.cs
new file mode 100644
index 00000000..d7ef5616
--- /dev/null
+++ b/LibWinUsb/WinUsb/WinUsbRegistry.cs
@@ -0,0 +1,518 @@
+// Copyright © 2006-2010 Travis Robinson. All rights reserved.
+//
+// website: http://sourceforge.net/projects/libusbdotnet
+// e-mail: libusbdotnet@gmail.com
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or
+// visit www.gnu.org.
+//
+//
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Text.RegularExpressions;
+using LibUsbDotNet.Internal;
+using LibUsbDotNet.Internal.UsbRegex;
+using LibUsbDotNet.Main;
+using Microsoft.Win32;
+
+namespace LibUsbDotNet.WinUsb
+{
+ /// <summary> WinUsb specific members for device registry settings.
+ /// </summary>
+ public class WinUsbRegistry : UsbRegistry
+ {
+ private bool mIsDeviceIDParsed;
+
+ private string mDeviceID;
+
+ // Parsed out of the device ID
+ private byte mInterfaceID;
+ private ushort mVid;
+ private ushort mPid;
+
+ /// <summary>
+ /// Gets a list of WinUSB device paths for the specified interface guid.
+ /// </summary>
+ /// <param name="deviceInterfaceGuid">The DeviceInterfaceGUID to search for.</param>
+ /// <param name="devicePathList">A list of device paths associated with the <paramref name="deviceInterfaceGuid"/>.</param>
+ /// <returns>True of one or more device paths was found.</returns>
+ /// <remarks>
+ /// Each device path string in the <paramref name="devicePathList"/> represents a seperate WinUSB device (interface).
+ /// </remarks>
+ /// <seealso cref="GetWinUsbRegistryList"/>
+ public static bool GetDevicePathList(Guid deviceInterfaceGuid, out List<String> devicePathList)
+ {
+ devicePathList = new List<string>();
+ int devicePathIndex = 0;
+ SetupApi.SP_DEVICE_INTERFACE_DATA interfaceData = SetupApi.SP_DEVICE_INTERFACE_DATA.Empty;
+ SetupApi.DeviceInterfaceDetailHelper detailHelper;
+
+ IntPtr deviceInfo = SetupApi.SetupDiGetClassDevs(ref deviceInterfaceGuid, null, IntPtr.Zero, SetupApi.DICFG.PRESENT | SetupApi.DICFG.DEVICEINTERFACE);
+ if (deviceInfo != IntPtr.Zero)
+ {
+ while ((SetupApi.SetupDiEnumDeviceInterfaces(deviceInfo, null, ref deviceInterfaceGuid, devicePathIndex, ref interfaceData)))
+ {
+ int length = 1024;
+ detailHelper = new SetupApi.DeviceInterfaceDetailHelper(length);
+ bool bResult = SetupApi.SetupDiGetDeviceInterfaceDetail(deviceInfo, ref interfaceData, detailHelper.Handle, length, out length, null);
+ if (bResult) devicePathList.Add(detailHelper.DevicePath);
+
+ devicePathIndex++;
+ }
+ }
+ if (devicePathIndex == 0)
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "GetDevicePathList", typeof(SetupApi));
+
+ if (deviceInfo != IntPtr.Zero)
+ SetupApi.SetupDiDestroyDeviceInfoList(deviceInfo);
+
+ return (devicePathIndex > 0);
+ }
+
+ /// <summary>
+ /// Gets a list of <see cref="WinUsbRegistry"/> classes for the specified interface guid.
+ /// </summary>
+ /// <param name="deviceInterfaceGuid">The DeviceInterfaceGUID to search for.</param>
+ /// <param name="deviceRegistryList">A list of device paths associated with the <paramref name="deviceInterfaceGuid"/>.</param>
+ /// <returns>True of one or more device paths was found.</returns>
+ /// <remarks>
+ /// Each <see cref="WinUsbRegistry"/> in the <paramref name="deviceRegistryList"/> represents a seperate WinUSB device (interface).
+ /// </remarks>
+ public static bool GetWinUsbRegistryList(Guid deviceInterfaceGuid, out List<WinUsbRegistry> deviceRegistryList)
+ {
+ deviceRegistryList = new List<WinUsbRegistry>();
+
+ int devicePathIndex = 0;
+ SetupApi.SP_DEVICE_INTERFACE_DATA interfaceData = SetupApi.SP_DEVICE_INTERFACE_DATA.Empty;
+ SetupApi.DeviceInterfaceDetailHelper detailHelper;
+
+ SetupApi.SP_DEVINFO_DATA devInfoData = SetupApi.SP_DEVINFO_DATA.Empty;
+
+ // [1]
+ IntPtr deviceInfo = SetupApi.SetupDiGetClassDevs(ref deviceInterfaceGuid, null, IntPtr.Zero, SetupApi.DICFG.PRESENT | SetupApi.DICFG.DEVICEINTERFACE);
+ if (deviceInfo != IntPtr.Zero)
+ {
+ while ((SetupApi.SetupDiEnumDeviceInterfaces(deviceInfo, null, ref deviceInterfaceGuid, devicePathIndex, ref interfaceData)))
+ {
+ int length = 1024;
+ detailHelper = new SetupApi.DeviceInterfaceDetailHelper(length);
+ bool bResult = SetupApi.SetupDiGetDeviceInterfaceDetail(deviceInfo, ref interfaceData, detailHelper.Handle, length, out length, ref devInfoData);
+ if (bResult)
+ {
+ WinUsbRegistry regInfo = new WinUsbRegistry();
+
+ SetupApi.getSPDRPProperties(deviceInfo, ref devInfoData, regInfo.mDeviceProperties);
+
+ // Use the actual winusb device path for SYMBOLIC_NAME_KEY. This will be used to open the device.
+ regInfo.mDeviceProperties.Add(SYMBOLIC_NAME_KEY, detailHelper.DevicePath);
+
+ //Debug.WriteLine(detailHelper.DevicePath);
+
+ regInfo.mDeviceInterfaceGuids = new Guid[] { deviceInterfaceGuid };
+
+ StringBuilder sbDeviceID=new StringBuilder(1024);
+ if (SetupApi.CM_Get_Device_ID(devInfoData.DevInst,sbDeviceID,sbDeviceID.Capacity,0)==SetupApi.CR.SUCCESS)
+ {
+ regInfo.mDeviceProperties[DEVICE_ID_KEY] = sbDeviceID.ToString();
+ }
+ deviceRegistryList.Add(regInfo);
+ }
+
+ devicePathIndex++;
+ }
+ }
+ if (devicePathIndex == 0)
+ UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "GetDevicePathList", typeof(SetupApi));
+
+ if (deviceInfo != IntPtr.Zero)
+ SetupApi.SetupDiDestroyDeviceInfoList(deviceInfo);
+
+ return (devicePathIndex > 0);
+ }
+
+ internal WinUsbRegistry() { }
+
+ /// <summary>
+ /// Gets a list of available LibUsb devices.
+ /// </summary>
+ public static List<WinUsbRegistry> DeviceList
+ {
+ get
+ {
+ List<WinUsbRegistry> deviceList = new List<WinUsbRegistry>();
+ SetupApi.EnumClassDevs(null, SetupApi.DICFG.ALLCLASSES | SetupApi.DICFG.PRESENT, WinUsbRegistryCallBack, deviceList);
+ return deviceList;
+ }
+ }
+
+ /// <summary>
+ /// Gets a collection of DeviceInterfaceGuids that are associated with this WinUSB device.
+ /// </summary>
+ public override Guid[] DeviceInterfaceGuids
+ {
+ get
+ {
+ return mDeviceInterfaceGuids;
+ }
+ }
+
+ /// <summary>
+ /// Check this value to determine if the usb device is still connected to the bus and ready to open.
+ /// </summary>
+ /// <remarks>
+ /// Uses the symbolic name as a unique id to determine if this device instance is still attached.
+ /// </remarks>
+ /// <exception cref="UsbException">An exception is thrown if the <see cref="UsbRegistry.SymbolicName"/> property is null or empty.</exception>
+ public override bool IsAlive
+ {
+ get
+ {
+ if (String.IsNullOrEmpty(SymbolicName)) throw new UsbException(this, "A symbolic name is required for this property.");
+
+ List<WinUsbRegistry> deviceList = DeviceList;
+ foreach (WinUsbRegistry registry in deviceList)
+ {
+ if (String.IsNullOrEmpty(registry.SymbolicName)) continue;
+
+ if (registry.SymbolicName == SymbolicName)
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Opens the USB device for communucation.
+ /// </summary>
+ /// <returns>Return a new instance of the <see cref="UsbDevice"/> class.
+ /// If the device fails to open a null refrence is return. For extended error
+ /// information use the <see cref="UsbDevice.UsbErrorEvent"/>.
+ /// </returns>
+ public override UsbDevice Device
+ {
+ get
+ {
+ WinUsbDevice winUsbDevice;
+ Open(out winUsbDevice);
+ return winUsbDevice;
+ }
+ }
+
+
+ private void parseDeviceID()
+ {
+ if (mIsDeviceIDParsed) return;
+
+ mIsDeviceIDParsed = true;
+
+ byte bTemp;
+ ushort uTemp;
+
+ MatchCollection matches = RegHardwareID.GlobalInstance.Matches(DeviceID);
+ foreach (Match match in matches)
+ {
+ foreach (NamedGroup namedGroup in RegHardwareID.NAMED_GROUPS)
+ {
+ Group g = match.Groups[namedGroup.GroupNumber];
+ if (g.Success)
+ {
+ switch ((RegHardwareID.ENamedGroups)namedGroup.GroupNumber)
+ {
+ case RegHardwareID.ENamedGroups.Vid:
+ if (ushort.TryParse(g.Value, NumberStyles.HexNumber, null, out uTemp))
+ {
+ mVid = uTemp;
+ break;
+ }
+ break;
+ case RegHardwareID.ENamedGroups.Pid:
+ if (ushort.TryParse(g.Value, NumberStyles.HexNumber, null, out uTemp))
+ {
+ mPid = uTemp;
+ break;
+ }
+ break;
+ case RegHardwareID.ENamedGroups.Rev:
+ break;
+ case RegHardwareID.ENamedGroups.MI:
+ if (Byte.TryParse(g.Value, NumberStyles.HexNumber, null, out bTemp))
+ {
+ mInterfaceID = bTemp;
+ break;
+ }
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ }
+
+ }
+ }
+
+ /// <summary>
+ /// Gets the device instance id.
+ /// </summary>
+ /// <remarks>
+ /// For more information on device instance ids, see the <a href="http://msdn.microsoft.com/en-us/library/ff538405%28v=VS.85%29.aspx">CM_Get_Device_ID Function</a> at MSDN.
+ /// </remarks>
+ public string DeviceID
+ {
+ get
+ {
+ if (ReferenceEquals(mDeviceID,null))
+ {
+ object oDeviceID;
+ if (mDeviceProperties.TryGetValue(DEVICE_ID_KEY, out oDeviceID))
+ {
+ mDeviceID = oDeviceID.ToString();
+ }
+ else
+ {
+ mDeviceID = string.Empty;
+ }
+ }
+ return mDeviceID;
+ }
+ }
+
+ /// <summary>
+ /// VendorID
+ /// </summary>
+ /// <remarks>This value is parsed out of the <see cref="DeviceID"/> field.</remarks>
+ public override int Vid
+ {
+ get
+ {
+ parseDeviceID();
+ return mVid;
+ }
+ }
+
+ /// <summary>
+ /// ProductID
+ /// </summary>
+ /// <remarks>This value is parsed out of the <see cref="DeviceID"/> field.</remarks>
+ public override int Pid
+ {
+ get
+ {
+ parseDeviceID();
+ return mPid;
+ }
+ }
+
+
+ ///<summary>
+ /// Gets the interface ID this WinUSB device (interface) is associated with.
+ ///</summary>
+ /// <remarks>This value is parsed out of the <see cref="DeviceID"/> field.</remarks>
+ public byte InterfaceID
+ {
+ get
+ {
+ parseDeviceID();
+ return (byte) mInterfaceID;
+ }
+ }
+
+ /// <summary>
+ /// Opens the USB device for communucation.
+ /// </summary>
+ /// <param name="usbDevice">The newly created UsbDevice.</param>
+ /// <returns>True on success.</returns>
+ public override bool Open(out UsbDevice usbDevice)
+ {
+ usbDevice = null;
+ WinUsbDevice winUsbDevice;
+ bool bSuccess = Open(out winUsbDevice);
+ if (bSuccess)
+ usbDevice = winUsbDevice;
+ return bSuccess;
+ }
+
+ /// <summary>
+ /// Opens the USB device for communucation.
+ /// </summary>
+ /// <param name="usbDevice">Returns an opened WinUsb device on success, null on failure.</param>
+ /// <returns>True on success.</returns>
+ public bool Open(out WinUsbDevice usbDevice)
+ {
+ usbDevice = null;
+
+ if (String.IsNullOrEmpty(SymbolicName)) return false;
+ if (WinUsbDevice.Open(SymbolicName, out usbDevice))
+ {
+ usbDevice.mUsbRegistry = this;
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ private static bool WinUsbRegistryCallBack(IntPtr deviceInfoSet,
+ int deviceIndex,
+ ref SetupApi.SP_DEVINFO_DATA deviceInfoData,
+ object classEnumeratorCallbackParam1)
+ {
+
+ List<WinUsbRegistry> deviceList = (List<WinUsbRegistry>) classEnumeratorCallbackParam1;
+
+ RegistryValueKind propertyType;
+ byte[] propBuffer = new byte[256];
+ int requiredSize;
+ bool isNew = true;
+ bool bSuccess;
+
+ bSuccess = SetupApi.SetupDiGetCustomDeviceProperty(deviceInfoSet,
+ ref deviceInfoData,
+ DEVICE_INTERFACE_GUIDS,
+ SetupApi.DICUSTOMDEVPROP.NONE,
+ out propertyType,
+ propBuffer,
+ propBuffer.Length,
+ out requiredSize);
+ if (bSuccess)
+ {
+ string[] devInterfaceGuids = GetAsStringArray(propBuffer, requiredSize);
+
+ foreach (String devInterfaceGuid in devInterfaceGuids)
+ {
+ Guid g = new Guid(devInterfaceGuid);
+ List<string> devicePaths;
+ if (SetupApi.GetDevicePathList(g, out devicePaths))
+ {
+ foreach (string devicePath in devicePaths)
+ {
+ WinUsbRegistry regInfo = new WinUsbRegistry();
+
+ SetupApi.getSPDRPProperties(deviceInfoSet, ref deviceInfoData, regInfo.mDeviceProperties);
+
+ // Use the actual winusb device path for SYMBOLIC_NAME_KEY. This will be used to open the device.
+ regInfo.mDeviceProperties.Add(SYMBOLIC_NAME_KEY, devicePath);
+
+ regInfo.mDeviceInterfaceGuids = new Guid[] { g };
+
+ // Don't add duplicate devices (with the same device path)
+ WinUsbRegistry foundRegistry=null;
+ foreach (WinUsbRegistry usbRegistry in deviceList)
+ {
+ if (usbRegistry.SymbolicName == regInfo.SymbolicName)
+ {
+ foundRegistry = usbRegistry;
+ break;
+ }
+ }
+ if (foundRegistry == null)
+ deviceList.Add(regInfo);
+ else
+ {
+ if (isNew)
+ {
+ deviceList.Remove(foundRegistry);
+ deviceList.Add(regInfo);
+ }
+ else
+ {
+
+ // If the device path already exists, add this compatible guid
+ // to the foundRegstry guid list.
+ List<Guid> newGuidList = new List<Guid>(foundRegistry.mDeviceInterfaceGuids);
+ if (!newGuidList.Contains(g))
+ {
+ newGuidList.Add(g);
+ foundRegistry.mDeviceInterfaceGuids = newGuidList.ToArray();
+ }
+ }
+ }
+ isNew = false;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+ */
+ private static bool WinUsbRegistryCallBack(IntPtr deviceInfoSet,
+ int deviceIndex,
+ ref SetupApi.SP_DEVINFO_DATA deviceInfoData,
+ object classEnumeratorCallbackParam1)
+ {
+
+ List<WinUsbRegistry> deviceList = (List<WinUsbRegistry>)classEnumeratorCallbackParam1;
+
+ RegistryValueKind propertyType;
+ byte[] propBuffer = new byte[256];
+ int requiredSize;
+ bool bSuccess;
+
+ bSuccess = SetupApi.SetupDiGetCustomDeviceProperty(deviceInfoSet,
+ ref deviceInfoData,
+ DEVICE_INTERFACE_GUIDS,
+ SetupApi.DICUSTOMDEVPROP.NONE,
+ out propertyType,
+ propBuffer,
+ propBuffer.Length,
+ out requiredSize);
+ if (bSuccess)
+ {
+ string[] devInterfaceGuids = GetAsStringArray(propBuffer, requiredSize);
+
+ foreach (String devInterfaceGuid in devInterfaceGuids)
+ {
+ Guid g = new Guid(devInterfaceGuid);
+ List<WinUsbRegistry> tempList;
+ if (GetWinUsbRegistryList(g, out tempList))
+ {
+ foreach (WinUsbRegistry regInfo in tempList)
+ {
+ // Don't add duplicate devices (with the same device path)
+ WinUsbRegistry foundRegistry = null;
+ foreach (WinUsbRegistry usbRegistry in deviceList)
+ {
+ if (usbRegistry.SymbolicName == regInfo.SymbolicName)
+ {
+ foundRegistry = usbRegistry;
+ break;
+ }
+ }
+ if (foundRegistry == null)
+ deviceList.Add(regInfo);
+ else
+ {
+ // If the device path already exists, add this compatible guid
+ // to the foundRegstry guid list.
+ List<Guid> newGuidList = new List<Guid>(foundRegistry.mDeviceInterfaceGuids);
+ if (!newGuidList.Contains(g))
+ {
+ newGuidList.Add(g);
+ foundRegistry.mDeviceInterfaceGuids = newGuidList.ToArray();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ }
+} \ No newline at end of file