changeset 67:2d16447eff12

Simplified USB communication code, added functions to abort pipe transfers
author Ivo Smits <Ivo@UCIS.nl>
date Wed, 16 Oct 2013 01:11:49 +0200
parents b7bc27c6734e
children e811297f5aa4
files USBLib/Communication/IUsbDevice.cs USBLib/Communication/LibUsb0/LibUsbDevice.cs USBLib/Communication/LibUsb1/LibUsb1Device.cs USBLib/Communication/LibUsbDotNet.cs USBLib/Communication/USBIO/USBIODevice.cs USBLib/Communication/UsbInterface.cs USBLib/Communication/UsbPipeStream.cs USBLib/Communication/VBoxUSB.cs USBLib/Communication/WinUsb/WinUsbDevice.cs USBLib/Windows/USB/UsbDevice.cs
diffstat 10 files changed, 103 insertions(+), 224 deletions(-) [+]
line wrap: on
line diff
--- a/USBLib/Communication/IUsbDevice.cs	Tue Oct 15 16:22:54 2013 +0200
+++ b/USBLib/Communication/IUsbDevice.cs	Wed Oct 16 01:11:49 2013 +0200
@@ -13,19 +13,13 @@
 		Byte Configuration { get; }
 		void Close();
 
-		//int ControlTransfer(byte requestType, byte request, short value, short index, Byte[] buffer, int offset, int length);
 		int GetDescriptor(byte descriptorType, byte index, short langId, Byte[] buffer, int offset, int length);
 
-		int BulkWrite(Byte endpoint, Byte[] buffer, int offset, int length);
-		int BulkRead(Byte endpoint, Byte[] buffer, int offset, int length);
-		void BulkReset(Byte endpoint);
-		int InterruptWrite(Byte endpoint, Byte[] buffer, int offset, int length);
-		int InterruptRead(Byte endpoint, Byte[] buffer, int offset, int length);
-		void InterruptReset(Byte endpoint);
-		int ControlWrite(UsbControlRequestType requestType, byte request, short value, short index, Byte[] buffer, int offset, int length);
-		int ControlRead(UsbControlRequestType requestType, byte request, short value, short index, Byte[] buffer, int offset, int length);
+		int PipeTransfer(Byte endpoint, Byte[] buffer, int offset, int length);
+		void PipeReset(Byte endpoint);
+		void PipeAbort(Byte endpoint);
+		int ControlTransfer(UsbControlRequestType requestType, byte request, short value, short index, Byte[] buffer, int offset, int length);
 
-		UsbPipeStream GetBulkStream(Byte endpoint);
-		UsbPipeStream GetInterruptStream(Byte endpoint);
+		UsbPipeStream GetPipeStream(Byte endpoint);
 	}
 }
--- a/USBLib/Communication/LibUsb0/LibUsbDevice.cs	Tue Oct 15 16:22:54 2013 +0200
+++ b/USBLib/Communication/LibUsb0/LibUsbDevice.cs	Wed Oct 16 01:11:49 2013 +0200
@@ -7,7 +7,6 @@
 
 namespace UCIS.USBLib.Communication.LibUsb {
 	public class LibUsb0Device : UsbInterface, IUsbDevice {
-		//private readonly List<int> mClaimedInterfaces = new List<int>();
 		public string DeviceFilename { get; private set; }
 		public IUsbDeviceRegistry Registry { get; private set; }
 		private SafeFileHandle DeviceHandle;
@@ -81,25 +80,13 @@
 			}
 			return ret;
 		}
-		public override int BulkRead(byte endpoint, byte[] buffer, int offset, int length) {
-			return PipeTransfer(endpoint, false, false, buffer, offset, length, 0);
-		}
-		public override int BulkWrite(byte endpoint, byte[] buffer, int offset, int length) {
-			return PipeTransfer(endpoint, true, false, buffer, offset, length, 0);
-		}
-		public override void BulkReset(byte endpoint) {
-			PipeReset(endpoint);
+		public override int ControlTransfer(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
+			if ((requestType & UsbControlRequestType.EndpointMask) == UsbControlRequestType.EndpointIn)
+				return ControlRead(requestType, request, value, index, buffer, offset, length);
+			else
+				return ControlWrite(requestType, request, value, index, buffer, offset, length);
 		}
-		public override int InterruptRead(byte endpoint, byte[] buffer, int offset, int length) {
-			return PipeTransfer(endpoint, false, false, buffer, offset, length, 0);
-		}
-		public override int InterruptWrite(byte endpoint, byte[] buffer, int offset, int length) {
-			return PipeTransfer(endpoint, true, false, buffer, offset, length, 0);
-		}
-		public override void InterruptReset(byte endpoint) {
-			PipeReset(endpoint);
-		}
-		public unsafe override int ControlRead(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
+		public unsafe int ControlRead(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
 			if (buffer == null) buffer = new Byte[0];
 			if (offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer length");
 			int code;
@@ -111,7 +98,7 @@
 			}
 			return ret;
 		}
-		public unsafe override int ControlWrite(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
+		public unsafe int ControlWrite(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
 			Byte[] inbuffer = new Byte[length + LibUsbRequest.Size];
 			if (length > 0) Buffer.BlockCopy(buffer, offset, inbuffer, LibUsbRequest.Size, length);
 			int code;
@@ -201,6 +188,10 @@
 			}
 		}
 
+		public override int PipeTransfer(Byte epnum, Byte[] buffer, int offset, int length) {
+			return PipeTransfer(epnum, (epnum & (Byte)UsbControlRequestType.EndpointMask) == (Byte)UsbControlRequestType.EndpointOut, false, buffer, offset, length, 0);
+		}
+
 		unsafe int PipeTransfer(Byte epnum, Boolean write, Boolean isochronous, Byte[] buffer, int offset, int length, int packetsize) {
 			if (offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer length");
 			LibUsbRequest req = new LibUsbRequest();
@@ -228,13 +219,20 @@
 				}
 			}
 		}
-		public void PipeReset(byte pipeID) {
+		public override void PipeReset(byte pipeID) {
 			LibUsbRequest req = new LibUsbRequest();
 			req.Endpoint.ID = pipeID;
 			req.Timeout = UsbConstants.DEFAULT_TIMEOUT;
 			int ret;
 			DeviceIoControl(DeviceHandle, LibUsbIoCtl.RESET_ENDPOINT, ref req, LibUsbRequest.Size, null, 0, out ret);
 		}
+		public override void PipeAbort(byte pipeID) {
+			LibUsbRequest req = new LibUsbRequest();
+			req.Endpoint.ID = pipeID;
+			req.Timeout = UsbConstants.DEFAULT_TIMEOUT;
+			int ret;
+			DeviceIoControl(DeviceHandle, LibUsbIoCtl.ABORT_ENDPOINT, ref req, LibUsbRequest.Size, null, 0, out ret);
+		}
 
 		private unsafe void DeviceIoControl(SafeHandle hDevice, int IoControlCode, [In] ref LibUsbRequest InBuffer, int nInBufferSize, Byte[] OutBuffer, int nOutBufferSize, out int pBytesReturned) {
 			fixed (LibUsbRequest* InBufferPtr = &InBuffer) {
--- a/USBLib/Communication/LibUsb1/LibUsb1Device.cs	Tue Oct 15 16:22:54 2013 +0200
+++ b/USBLib/Communication/LibUsb1/LibUsb1Device.cs	Wed Oct 16 01:11:49 2013 +0200
@@ -17,52 +17,22 @@
 			if (Handle != null) Handle.Close();
 		}
 
-		public override int BulkWrite(byte endpoint, byte[] buffer, int offset, int length) {
-			return BulkTransfer(endpoint, buffer, offset, length);
-		}
-		public override int BulkRead(byte endpoint, byte[] buffer, int offset, int length) {
-			return BulkTransfer(endpoint, buffer, offset, length);
-		}
-		public override void BulkReset(byte endpoint) {
+		public override void PipeReset(byte endpoint) {
 			int ret = libusb1.libusb_clear_halt(Handle, endpoint);
 			if (ret < 0) throw new Exception("libusb_clear_halt returned " + ret.ToString());
 		}
-		private int BulkTransfer(byte endpoint, byte[] buffer, int offset, int length) {
+		public override int PipeTransfer(byte endpoint, byte[] buffer, int offset, int length) {
 			if (offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer length");
 			if (length == 0) return 0;
 			fixed (Byte* b = buffer) {
 				int ret = libusb1.libusb_bulk_transfer(Handle, endpoint, b + offset, length, out length, 0);
+				//libusb1.libusb_interrupt_transfer(Handle, endpoint, b + offset, length, out length, 0);
 				if (ret < 0) throw new Exception("libusb_bulk_transfer returned " + ret.ToString());
 			}
 			return length;
 		}
 
-		public override int InterruptWrite(byte endpoint, byte[] buffer, int offset, int length) {
-			return InterruptTransfer(endpoint, buffer, offset, length);
-		}
-		public override int InterruptRead(byte endpoint, byte[] buffer, int offset, int length) {
-			return InterruptTransfer(endpoint, buffer, offset, length);
-		}
-		public override void InterruptReset(byte endpoint) {
-			BulkReset(endpoint);
-		}
-		private int InterruptTransfer(byte endpoint, byte[] buffer, int offset, int length) {
-			if (offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer length");
-			if (length == 0) return 0;
-			fixed (Byte* b = buffer) {
-				int ret = libusb1.libusb_interrupt_transfer(Handle, endpoint, b + offset, length, out length, 0);
-				if (ret < 0) throw new Exception("libusb_interrupt_transfer returned " + ret.ToString());
-			}
-			return length;
-		}
-
-		public override int ControlWrite(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
-			return ControlTransfer(requestType, request, value, index, buffer, offset, length);
-		}
-		public override int ControlRead(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
-			return ControlTransfer(requestType, request, value, index, buffer, offset, length);
-		}
-		private int ControlTransfer(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
+		public override int ControlTransfer(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
 			if (buffer == null) buffer = new Byte[0];
 			if (offset < 0 || length < 0 || length > ushort.MaxValue || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length");
 			fixed (Byte* b = buffer) {
--- a/USBLib/Communication/LibUsbDotNet.cs	Tue Oct 15 16:22:54 2013 +0200
+++ b/USBLib/Communication/LibUsbDotNet.cs	Wed Oct 16 01:11:49 2013 +0200
@@ -34,11 +34,7 @@
 			}
 		}
 		public bool ControlTransfer(ref UsbSetupPacket setupPacket, Byte[] buffer, int bufferLength, out int lengthTransferred) {
-			if ((setupPacket.RequestType & 128) != 0) {
-				lengthTransferred = Device.ControlRead((UsbControlRequestType)setupPacket.RequestType, setupPacket.Request, setupPacket.Value, setupPacket.Index, buffer, 0, bufferLength);
-			} else {
-				lengthTransferred = Device.ControlWrite((UsbControlRequestType)setupPacket.RequestType, setupPacket.Request, setupPacket.Value, setupPacket.Index, buffer, 0, bufferLength);
-			}
+			lengthTransferred = Device.ControlTransfer((UsbControlRequestType)setupPacket.RequestType, setupPacket.Request, setupPacket.Value, setupPacket.Index, buffer, 0, bufferLength);
 			return true;
 		}
 		public UsbEndpointReader OpenEndpointReader(ReadEndpointID readEndpointID, int buffersize, EndpointType endpointType) {
@@ -139,11 +135,7 @@
 			ReadBufferSize = 4096;
 		}
 		public ErrorCode Read(byte[] buffer, int offset, int count, int timeout, out int transferLength) {
-			switch (EndpointType) {
-				case EndpointType.Bulk: transferLength = Device.BulkRead(EndpointID, buffer, offset, count); break;
-				case EndpointType.Interrupt: transferLength = Device.InterruptRead(EndpointID, buffer, offset, count); break;
-				default: transferLength = 0; return ErrorCode.Error;
-			}
+			transferLength = Device.PipeTransfer(EndpointID, buffer, offset, count);
 			return ErrorCode.Ok;
 		}
 		public void Dispose() { DataReceivedEnabled = false; }
--- a/USBLib/Communication/USBIO/USBIODevice.cs	Tue Oct 15 16:22:54 2013 +0200
+++ b/USBLib/Communication/USBIO/USBIODevice.cs	Wed Oct 16 01:11:49 2013 +0200
@@ -28,6 +28,7 @@
 		static readonly int IOCTL_USBIO_RESET_DEVICE = _USBIO_IOCTL_CODE(21, METHOD_BUFFERED);
 		static readonly int IOCTL_USBIO_BIND_PIPE = _USBIO_IOCTL_CODE(30, METHOD_BUFFERED);
 		static readonly int IOCTL_USBIO_RESET_PIPE = _USBIO_IOCTL_CODE(32, METHOD_BUFFERED);
+		static readonly int IOCTL_USBIO_ABORT_PIPE = _USBIO_IOCTL_CODE(33, METHOD_BUFFERED);
 
 		[DllImport("kernel32.dll", SetLastError = true)]
 		static unsafe extern bool ReadFile(SafeFileHandle hFile, byte* lpBuffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);
@@ -150,31 +151,7 @@
 				return DeviceIoControl(DeviceHandle, IOCTL_USBIO_GET_DESCRIPTOR, (IntPtr)(&req), sizeof(USBIO_DESCRIPTOR_REQUEST), (IntPtr)(b + offset), length);
 			}
 		}
-		public override int BulkRead(byte endpoint, byte[] buffer, int offset, int length) {
-			return PipeRead(endpoint, buffer, offset, length);
-		}
-		public override int BulkWrite(byte endpoint, byte[] buffer, int offset, int length) {
-			return PipeWrite(endpoint, buffer, offset, length);
-		}
-		public override void BulkReset(byte endpoint) {
-			PipeReset(endpoint);
-		}
-		public override int InterruptRead(byte endpoint, byte[] buffer, int offset, int length) {
-			return PipeRead(endpoint, buffer, offset, length);
-		}
-		public override int InterruptWrite(byte endpoint, byte[] buffer, int offset, int length) {
-			return PipeWrite(endpoint, buffer, offset, length);
-		}
-		public override void InterruptReset(byte endpoint) {
-			PipeReset(endpoint);
-		}
-		public unsafe override int ControlRead(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
-			return ControlTransfer(requestType, request, value, index, buffer, offset, length);
-		}
-		public override int ControlWrite(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
-			return ControlTransfer(requestType, request, value, index, buffer, offset, length);
-		}
-		private unsafe int ControlTransfer(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
+		public override unsafe int ControlTransfer(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
 			if (buffer == null) {
 				if (offset != 0 || length != 0) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer length");
 			} else {
@@ -245,28 +222,28 @@
 				return handle;
 			}
 		}
-		unsafe int PipeRead(Byte epnum, Byte[] buffer, int offset, int length) {
+		public unsafe override int PipeTransfer(Byte epnum, Byte[] buffer, int offset, int length) {
 			if (offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer length");
 			SafeFileHandle handle = GetHandleForPipe(epnum);
 			uint ret;
 			fixed (Byte* b = buffer) {
-				if (!ReadFile(handle, b + offset, (uint)length, out ret, IntPtr.Zero)) throw new Win32Exception(Marshal.GetLastWin32Error());
+				Boolean success;
+				if ((epnum & (Byte)UsbControlRequestType.EndpointMask) == (Byte)UsbControlRequestType.EndpointIn)
+					success = ReadFile(handle, b + offset, (uint)length, out ret, IntPtr.Zero);
+				else
+					success = WriteFile(handle, b + offset, (uint)length, out ret, IntPtr.Zero);
+				if (!success) throw new Win32Exception(Marshal.GetLastWin32Error());
 			}
 			return (int)ret;
 		}
-		unsafe int PipeWrite(Byte epnum, Byte[] buffer, int offset, int length) {
-			if (offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer length");
-			SafeFileHandle handle = GetHandleForPipe(epnum);
-			uint ret;
-			fixed (Byte* b = buffer) {
-				if (!WriteFile(handle, b + offset, (uint)length, out ret, IntPtr.Zero)) throw new Win32Exception(Marshal.GetLastWin32Error());
-			}
-			return (int)ret;
-		}
-		public void PipeReset(byte pipeID) {
+		public override void PipeReset(byte pipeID) {
 			SafeFileHandle handle = GetHandleForPipe(pipeID);
 			DeviceIoControl(handle, IOCTL_USBIO_RESET_PIPE, IntPtr.Zero, 0, IntPtr.Zero, 0);
 		}
+		public override void PipeAbort(byte pipeID) {
+			SafeFileHandle handle = GetHandleForPipe(pipeID);
+			DeviceIoControl(handle, IOCTL_USBIO_ABORT_PIPE, IntPtr.Zero, 0, IntPtr.Zero, 0);
+		}
 
 		private unsafe int DeviceIoControl(SafeHandle hDevice, int IoControlCode, IntPtr InBuffer, int nInBufferSize, IntPtr OutBuffer, int nOutBufferSize) {
 			int pBytesReturned;
@@ -275,16 +252,13 @@
 			throw new Win32Exception(Marshal.GetLastWin32Error());
 		}
 
-		public override UsbPipeStream GetBulkStream(byte endpoint) {
-			return new PipeStream(this, endpoint, false, GetHandleForPipe(endpoint));
-		}
-		public override UsbPipeStream GetInterruptStream(byte endpoint) {
-			return new PipeStream(this, endpoint, true, GetHandleForPipe(endpoint));
+		public override UsbPipeStream GetPipeStream(byte endpoint) {
+			return new PipeStream(this, endpoint, GetHandleForPipe(endpoint));
 		}
 
 		class PipeStream : UsbPipeStream {
 			private SafeFileHandle Handle;
-			public PipeStream(IUsbInterface device, Byte endpoint, Boolean interrupt, SafeFileHandle handle) : base(device, endpoint, interrupt) {
+			public PipeStream(IUsbInterface device, Byte endpoint, SafeFileHandle handle) : base(device, endpoint) {
 				this.Handle = handle;
 			}
 
--- a/USBLib/Communication/UsbInterface.cs	Tue Oct 15 16:22:54 2013 +0200
+++ b/USBLib/Communication/UsbInterface.cs	Wed Oct 16 01:11:49 2013 +0200
@@ -7,7 +7,7 @@
 		public virtual byte Configuration {
 			get {
 				byte[] buf = new byte[1];
-				int tl = ControlRead(
+				int tl = ControlTransfer(
 					UsbControlRequestType.EndpointIn | UsbControlRequestType.TypeStandard | UsbControlRequestType.RecipDevice,
 					(byte)UsbStandardRequest.GetConfiguration, 0, 0,
 					buf, 0, buf.Length);
@@ -19,31 +19,24 @@
 			}
 		}
 		public virtual int GetDescriptor(byte descriptorType, byte index, short langId, byte[] buffer, int offset, int length) {
-			return ControlRead(
+			return ControlTransfer(
 				UsbControlRequestType.EndpointIn | UsbControlRequestType.RecipDevice | UsbControlRequestType.TypeStandard,
 				(Byte)UsbStandardRequest.GetDescriptor,
 				(short)((descriptorType << 8) | index), langId, buffer, offset, length);
 		}
-		public virtual int ControlWrite(UsbControlRequestType requestType, byte request, short value, short index) {
-			return ControlWrite(requestType, request, value, index, null, 0, 0);
+		public virtual int ControlTransfer(UsbControlRequestType requestType, byte request, short value, short index) {
+			return ControlTransfer(requestType, request, value, index, null, 0, 0);
 		}
 
 		public abstract void Close();
 
-		public abstract int BulkWrite(Byte endpoint, Byte[] buffer, int offset, int length);
-		public abstract int BulkRead(Byte endpoint, Byte[] buffer, int offset, int length);
-		public virtual void BulkReset(Byte endpoint) { throw new NotImplementedException(); }
-		public abstract int InterruptWrite(Byte endpoint, Byte[] buffer, int offset, int length);
-		public abstract int InterruptRead(Byte endpoint, Byte[] buffer, int offset, int length);
-		public virtual void InterruptReset(Byte endpoint) { throw new NotImplementedException(); }
-		public abstract int ControlWrite(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length);
-		public abstract int ControlRead(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length);
+		public abstract int PipeTransfer(Byte endpoint, Byte[] buffer, int offset, int length);
+		public virtual void PipeReset(Byte endpoint) { throw new NotImplementedException(); }
+		public virtual void PipeAbort(Byte endpoint) { throw new NotImplementedException(); }
+		public abstract int ControlTransfer(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length);
 
-		public virtual UsbPipeStream GetBulkStream(Byte endpoint) {
-			return new UsbPipeStream(this, endpoint, false);
-		}
-		public virtual UsbPipeStream GetInterruptStream(Byte endpoint) {
-			return new UsbPipeStream(this, endpoint, true);
+		public virtual UsbPipeStream GetPipeStream(Byte endpoint) {
+			return new UsbPipeStream(this, endpoint);
 		}
 
 		public void Dispose() {
--- a/USBLib/Communication/UsbPipeStream.cs	Tue Oct 15 16:22:54 2013 +0200
+++ b/USBLib/Communication/UsbPipeStream.cs	Wed Oct 16 01:11:49 2013 +0200
@@ -5,12 +5,10 @@
 	public class UsbPipeStream : Stream {
 		public IUsbInterface Device { get; private set; }
 		public Byte Endpoint { get; private set; }
-		public Boolean InterruptEndpoint { get; private set; }
 
-		public UsbPipeStream(IUsbInterface device, Byte endpoint, Boolean interrupt) {
+		public UsbPipeStream(IUsbInterface device, Byte endpoint) {
 			this.Device = device;
 			this.Endpoint = endpoint;
-			this.InterruptEndpoint = interrupt;
 		}
 
 		public override bool CanRead {
@@ -35,12 +33,17 @@
 			set { throw new NotImplementedException(); }
 		}
 
+		public void Abort() {
+			Device.PipeAbort(Endpoint);
+		}
+
+		public void ClearHalt() {
+			Device.PipeReset(Endpoint);
+		}
+
 		public override int Read(byte[] buffer, int offset, int count) {
-			if (InterruptEndpoint) {
-				return Device.InterruptRead(Endpoint, buffer, offset, count);
-			} else {
-				return Device.BulkRead(Endpoint, buffer, offset, count);
-			}
+			if (!CanRead) throw new InvalidOperationException("Can not read from an output endpoint");
+			return Device.PipeTransfer(Endpoint, buffer, offset, count);
 		}
 
 		public override long Seek(long offset, SeekOrigin origin) {
@@ -52,13 +55,14 @@
 		}
 
 		public override void Write(byte[] buffer, int offset, int count) {
-			int written;
-			if (InterruptEndpoint) {
-				written = Device.InterruptWrite(Endpoint, buffer, offset, count);
-			} else {
-				written = Device.BulkWrite(Endpoint, buffer, offset, count);
-			}
+			if (!CanWrite) throw new InvalidOperationException("Can not write to an input endpoint");
+			int written = Device.PipeTransfer(Endpoint, buffer, offset, count);
 			if (written != count) throw new EndOfStreamException("Could not write all data");
 		}
+
+		protected override void Dispose(bool disposing) {
+			if (disposing) try { Abort(); } catch { }
+			base.Dispose(disposing);
+		}
 	}
 }
--- a/USBLib/Communication/VBoxUSB.cs	Tue Oct 15 16:22:54 2013 +0200
+++ b/USBLib/Communication/VBoxUSB.cs	Wed Oct 16 01:11:49 2013 +0200
@@ -308,6 +308,7 @@
 		static readonly int SUPUSB_IOCTL_USB_SET_CONFIG = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x60A, METHOD_BUFFERED, FILE_WRITE_ACCESS);
 		static readonly int SUPUSB_IOCTL_USB_SELECT_INTERFACE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x609, METHOD_BUFFERED, FILE_WRITE_ACCESS);
 		static readonly int SUPUSB_IOCTL_SEND_URB = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x607, METHOD_BUFFERED, FILE_WRITE_ACCESS);
+		static readonly int SUPUSB_IOCTL_USB_ABORT_ENDPOINT = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x610, METHOD_BUFFERED, FILE_WRITE_ACCESS);
 
 		const UInt32 USBDRV_MAJOR_VERSION = 4;
 		const UInt32 USBDRV_MINOR_VERSION = 0;
@@ -426,12 +427,13 @@
 			hDev.Close();
 		}
 
-		public unsafe override void BulkReset(byte endpoint) {
+		public unsafe override void PipeReset(byte endpoint) {
 			USBSUP_CLEAR_ENDPOINT inp = new USBSUP_CLEAR_ENDPOINT() { bEndpoint = endpoint };
 			SyncIoControl(hDev, SUPUSB_IOCTL_USB_CLEAR_ENDPOINT, &inp, sizeof(USBSUP_CLEAR_ENDPOINT), null, 0);
 		}
-		public override void InterruptReset(byte endpoint) {
-			BulkReset(endpoint);
+		public unsafe override void PipeAbort(byte endpoint) {
+			USBSUP_CLEAR_ENDPOINT inp = new USBSUP_CLEAR_ENDPOINT() { bEndpoint = endpoint };
+			SyncIoControl(hDev, SUPUSB_IOCTL_USB_ABORT_ENDPOINT, &inp, sizeof(USBSUP_CLEAR_ENDPOINT), null, 0);
 		}
 
 		public unsafe void ResetDevice() {
@@ -476,19 +478,11 @@
 			}
 		}
 
-		public override int BulkWrite(byte endpoint, byte[] buffer, int offset, int length) {
-			return BlockTransfer(USBSUP_TRANSFER_TYPE.USBSUP_TRANSFER_TYPE_BULK, USBSUP_DIRECTION.USBSUP_DIRECTION_OUT, USBSUP_XFER_FLAG.USBSUP_FLAG_NONE, endpoint, buffer, offset, length);
-		}
-		public override int BulkRead(byte endpoint, byte[] buffer, int offset, int length) {
-			return BlockTransfer(USBSUP_TRANSFER_TYPE.USBSUP_TRANSFER_TYPE_BULK, USBSUP_DIRECTION.USBSUP_DIRECTION_IN, USBSUP_XFER_FLAG.USBSUP_FLAG_NONE, endpoint, buffer, offset, length);
+		public override int PipeTransfer(byte endpoint, byte[] buffer, int offset, int length) {
+			return BlockTransfer(USBSUP_TRANSFER_TYPE.USBSUP_TRANSFER_TYPE_BULK, (endpoint & 0x80) == 0 ? USBSUP_DIRECTION.USBSUP_DIRECTION_OUT : USBSUP_DIRECTION.USBSUP_DIRECTION_IN, USBSUP_XFER_FLAG.USBSUP_FLAG_NONE, endpoint, buffer, offset, length);
+			//return BlockTransfer(USBSUP_TRANSFER_TYPE.USBSUP_TRANSFER_TYPE_INTR, USBSUP_DIRECTION.USBSUP_DIRECTION_OUT, USBSUP_XFER_FLAG.USBSUP_FLAG_NONE, endpoint, buffer, offset, length);
 		}
-		public override int InterruptWrite(byte endpoint, byte[] buffer, int offset, int length) {
-			return BlockTransfer(USBSUP_TRANSFER_TYPE.USBSUP_TRANSFER_TYPE_INTR, USBSUP_DIRECTION.USBSUP_DIRECTION_OUT, USBSUP_XFER_FLAG.USBSUP_FLAG_NONE, endpoint, buffer, offset, length);
-		}
-		public override int InterruptRead(byte endpoint, byte[] buffer, int offset, int length) {
-			return BlockTransfer(USBSUP_TRANSFER_TYPE.USBSUP_TRANSFER_TYPE_INTR, USBSUP_DIRECTION.USBSUP_DIRECTION_IN, USBSUP_XFER_FLAG.USBSUP_FLAG_NONE, endpoint, buffer, offset, length);
-		}
-		private unsafe int ControlTransfer(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
+		public override unsafe int ControlTransfer(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
 			Byte[] bigbuffer = new Byte[sizeof(UsbSetupPacket) + length];
 			Boolean isout = (requestType & UsbControlRequestType.EndpointMask) == UsbControlRequestType.EndpointOut;
 			if (isout && length > 0) Buffer.BlockCopy(buffer, offset, bigbuffer, sizeof(UsbSetupPacket), length);
@@ -500,12 +494,6 @@
 			if (!isout) Buffer.BlockCopy(bigbuffer, sizeof(UsbSetupPacket), buffer, offset, dlen);
 			return dlen;
 		}
-		public override int ControlWrite(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
-			return ControlTransfer(requestType, request, value, index, buffer, offset, length);
-		}
-		public override int ControlRead(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
-			return ControlTransfer(requestType, request, value, index, buffer, offset, length);
-		}
 
 		public void ClaimInterface(int interfaceID) {
 			bInterfaceNumber = (Byte)interfaceID;
--- a/USBLib/Communication/WinUsb/WinUsbDevice.cs	Tue Oct 15 16:22:54 2013 +0200
+++ b/USBLib/Communication/WinUsb/WinUsbDevice.cs	Wed Oct 16 01:11:49 2013 +0200
@@ -145,7 +145,7 @@
 			}
 		}
 
-		public unsafe int ControlTransfer(byte requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
+		public override unsafe int ControlTransfer(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
 			if (buffer == null) buffer = new Byte[0];
 			if (offset < 0 || length < 0 || length > short.MaxValue || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length");
 			SafeWinUsbInterfaceHandle ih = InterfaceHandles[0];
@@ -156,21 +156,13 @@
 			}
 			fixed (Byte* b = buffer) {
 				if (!WinUsb_ControlTransfer(ih,
-					new UsbSetupPacket(requestType, request, value, index, (short)length),
+					new UsbSetupPacket((byte)requestType, request, value, index, (short)length),
 					(IntPtr)(b + offset), length, out length, IntPtr.Zero))
 					throw new Win32Exception(Marshal.GetLastWin32Error(), "Control transfer failed");
 				return length;
 			}
 		}
 
-		public override int ControlWrite(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
-			return ControlTransfer((byte)(requestType | UsbControlRequestType.EndpointOut), request, value, index, buffer, offset, length);
-		}
-
-		public override int ControlRead(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) {
-			return ControlTransfer((byte)(requestType | UsbControlRequestType.EndpointIn), request, value, index, buffer, offset, length);
-		}
-
 		public unsafe override int GetDescriptor(byte descriptorType, byte index, short langId, byte[] buffer, int offset, int length) {
 			if (length > short.MaxValue || offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length");
 			fixed (Byte* b = buffer) {
@@ -180,48 +172,27 @@
 			return length;
 		}
 
-		public unsafe int PipeWrite(byte endpoint, byte[] buffer, int offset, int length) {
+		public override unsafe int PipeTransfer(byte endpoint, byte[] buffer, int offset, int length) {
 			if (offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer length");
 			SafeWinUsbInterfaceHandle ih = GetInterfaceHandleForEndpoint(endpoint);
 			fixed (Byte* b = buffer) {
-				if (!WinUsb_WritePipe(ih, endpoint, (IntPtr)(b + offset), length, out length, IntPtr.Zero))
-						throw new Win32Exception(Marshal.GetLastWin32Error());
-			}
-			return length;
-		}
-
-		public unsafe int PipeRead(byte endpoint, byte[] buffer, int offset, int length) {
-			if (offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer length");
-			SafeWinUsbInterfaceHandle ih = GetInterfaceHandleForEndpoint(endpoint);
-			fixed (Byte* b = buffer) {
-				if (!WinUsb_ReadPipe(ih, endpoint, (IntPtr)(b + offset), length, out length, IntPtr.Zero))
-					throw new Win32Exception(Marshal.GetLastWin32Error());
+				Boolean success;
+				if ((endpoint & (Byte)UsbControlRequestType.EndpointMask) == (Byte)UsbControlRequestType.EndpointOut)
+					success = WinUsb_WritePipe(ih, endpoint, (IntPtr)(b + offset), length, out length, IntPtr.Zero);
+				else
+					success = WinUsb_ReadPipe(ih, endpoint, (IntPtr)(b + offset), length, out length, IntPtr.Zero);
+				if (!success) throw new Win32Exception(Marshal.GetLastWin32Error());
 			}
 			return length;
 		}
 
-		public void PipeReset(byte endpoint) {
+		public override void PipeReset(byte endpoint) {
 			SafeWinUsbInterfaceHandle ih = GetInterfaceHandleForEndpoint(endpoint);
 			WinUsb_ResetPipe(ih, endpoint);
 		}
-
-		public override int BulkWrite(Byte endpoint, Byte[] buffer, int offset, int length) {
-			return PipeWrite(endpoint, buffer, offset, length);
-		}
-		public override int BulkRead(Byte endpoint, Byte[] buffer, int offset, int length) {
-			return PipeRead(endpoint, buffer, offset, length);
-		}
-		public override void BulkReset(Byte endpoint) {
-			PipeReset(endpoint);
-		}
-		public override int InterruptWrite(Byte endpoint, Byte[] buffer, int offset, int length) {
-			return PipeWrite(endpoint, buffer, offset, length);
-		}
-		public override int InterruptRead(Byte endpoint, Byte[] buffer, int offset, int length) {
-			return PipeRead(endpoint, buffer, offset, length);
-		}
-		public override void InterruptReset(Byte endpoint) {
-			PipeReset(endpoint);
+		public override void PipeAbort(byte endpoint) {
+			SafeWinUsbInterfaceHandle ih = GetInterfaceHandleForEndpoint(endpoint);
+			WinUsb_AbortPipe(ih, endpoint);
 		}
 	}
 }
\ No newline at end of file
--- a/USBLib/Windows/USB/UsbDevice.cs	Tue Oct 15 16:22:54 2013 +0200
+++ b/USBLib/Windows/USB/UsbDevice.cs	Wed Oct 16 01:11:49 2013 +0200
@@ -157,19 +157,14 @@
 		void IUsbDevice.ResetDevice() { throw new NotImplementedException(); }
 		IUsbDeviceRegistry IUsbDevice.Registry { get { throw new NotImplementedException(); } }
 		void IUsbInterface.Close() { }
-		int IUsbInterface.BulkWrite(byte endpoint, byte[] buffer, int offset, int length) { throw new NotSupportedException(); }
-		int IUsbInterface.BulkRead(byte endpoint, byte[] buffer, int offset, int length) { throw new NotSupportedException(); }
-		void IUsbInterface.BulkReset(byte endpoint) { throw new NotImplementedException(); }
-		int IUsbInterface.InterruptWrite(byte endpoint, byte[] buffer, int offset, int length) { throw new NotSupportedException(); }
-		int IUsbInterface.InterruptRead(byte endpoint, byte[] buffer, int offset, int length) { throw new NotSupportedException(); }
-		void IUsbInterface.InterruptReset(byte endpoint) { throw new NotSupportedException(); }
-		int IUsbInterface.ControlWrite(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) { throw new NotSupportedException(); }
-		int IUsbInterface.ControlRead(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) { throw new NotSupportedException(); }
-		UsbPipeStream IUsbInterface.GetBulkStream(byte endpoint) { throw new NotSupportedException(); }
-		UsbPipeStream IUsbInterface.GetInterruptStream(byte endpoint) { throw new NotSupportedException(); }
+		int IUsbInterface.PipeTransfer(byte endpoint, byte[] buffer, int offset, int length) { throw new NotSupportedException(); }
+		void IUsbInterface.PipeReset(byte endpoint) { throw new NotImplementedException(); }
+		void IUsbInterface.PipeAbort(byte endpoint) { throw new NotImplementedException(); }
+		int IUsbInterface.ControlTransfer(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) { throw new NotSupportedException(); }
+		UsbPipeStream IUsbInterface.GetPipeStream(byte endpoint) { throw new NotSupportedException(); }
 		void IDisposable.Dispose() { }
 		void IUsbDevice.ClaimInterface(int interfaceID) { }
-		void IUsbDevice.ReleaseInterface(int interfaceID) {	}
+		void IUsbDevice.ReleaseInterface(int interfaceID) { }
 		#endregion
 	}
 }