changeset 60:3424fa5a12c9

Updated Windows USB enumeration classes and VBoxUSB backend
author Ivo Smits <Ivo@UCIS.nl>
date Sat, 12 Oct 2013 16:35:24 +0200
parents 4e1a5dec786a
children 2b24666cd759
files UCIS.Core.csproj USBLib/Communication/LibUsbDotNet.cs USBLib/Communication/VBoxUSB.cs USBLib/Windows/USB/UsbBus.cs USBLib/Windows/USB/UsbController.cs USBLib/Windows/USB/UsbDevice.cs USBLib/Windows/USB/UsbHub.cs
diffstat 7 files changed, 115 insertions(+), 87 deletions(-) [+]
line wrap: on
line diff
--- a/UCIS.Core.csproj	Wed Oct 09 20:56:28 2013 +0200
+++ b/UCIS.Core.csproj	Sat Oct 12 16:35:24 2013 +0200
@@ -161,7 +161,6 @@
     <Compile Include="USBLib\Internal\Windows\UsbApi.cs" />
     <Compile Include="USBLib\Internal\Windows\Win32Kernel.cs" />
     <Compile Include="USBLib\Windows\Devices\DeviceNode.cs" />
-    <Compile Include="USBLib\Windows\USB\UsbBus.cs" />
     <Compile Include="USBLib\Windows\USB\UsbController.cs" />
     <Compile Include="USBLib\Windows\USB\UsbDevice.cs" />
     <Compile Include="USBLib\Windows\USB\UsbHub.cs" />
--- a/USBLib/Communication/LibUsbDotNet.cs	Wed Oct 09 20:56:28 2013 +0200
+++ b/USBLib/Communication/LibUsbDotNet.cs	Sat Oct 12 16:35:24 2013 +0200
@@ -20,6 +20,7 @@
 	public class UsbDevice : IUsbDevice {
 		public nIUsbInterface Device { get; private set; }
 		public UsbDevice(nIUsbInterface dev) {
+			if (dev == null) throw new ArgumentNullException("dev");
 			Device = dev;
 		}
 		public bool GetDescriptor(byte descriptorType, byte index, short langId, Byte[] buffer, int bufferLength, out int transferLength) {
@@ -87,6 +88,7 @@
 			nIUsbDevice dev = Device as nIUsbDevice;
 			if (dev == null) return false;
 			try {
+				if (dev.Configuration == 0) dev.Configuration = 1;
 				dev.ClaimInterface(interfaceID);
 				return true;
 			} catch {
--- a/USBLib/Communication/VBoxUSB.cs	Wed Oct 09 20:56:28 2013 +0200
+++ b/USBLib/Communication/VBoxUSB.cs	Sat Oct 12 16:35:24 2013 +0200
@@ -238,9 +238,57 @@
 		public UInt32 numIsoPkts;
 		public fixed byte aIsoPkts[8 * 8];
 	}
-	class USBRegistry : WindowsUsbDeviceRegistry, IUsbDeviceRegistry {
+	class USBRegistry : IUsbDeviceRegistry {
+		public DeviceNode DeviceNode { get; private set; }
+		public String DevicePath { get; private set; }
+		public String DeviceID { get; private set; }
+		public String SymbolicName { get { return DevicePath; } }
+		private UCIS.HWLib.Windows.USB.UsbDevice usbdev = null;
+		private Boolean hasDeviceDescriptor = false;
+		private UCIS.USBLib.Descriptor.UsbDeviceDescriptor deviceDescriptor;
+		private IDictionary<string, object> mDeviceProperties;
+		public UCIS.HWLib.Windows.USB.UsbDevice USBDevice {
+			get {
+				if (usbdev == null) usbdev = UCIS.HWLib.Windows.USB.UsbDevice.GetUsbDevice(DeviceNode);
+				return usbdev;
+			}
+		}
+		public UCIS.USBLib.Descriptor.UsbDeviceDescriptor DeviceDescriptor {
+			get {
+				if (!hasDeviceDescriptor) deviceDescriptor = UCIS.USBLib.Descriptor.UsbDeviceDescriptor.FromDevice(USBDevice);
+				return deviceDescriptor;
+			}
+		}
+		public IDictionary<string, object> DeviceProperties {
+			get {
+				if (mDeviceProperties == null) mDeviceProperties = SetupApi.GetSPDRPProperties(DeviceNode);
+				return mDeviceProperties;
+			}
+		}
+
+		internal USBRegistry(DeviceNode device, String interfacepath) {
+			DeviceNode = device;
+			DeviceID = device.DeviceID;
+			DevicePath = interfacepath;
+		}
+
+		public int Vid { get { return DeviceDescriptor.VendorID; } }
+		public int Pid { get { return DeviceDescriptor.ProductID; } }
+		public byte InterfaceID { get { return 0; } }
+
+		public string Name { get { return DeviceNode.GetPropertyString(CMRDP.DEVICEDESC); } }
+		public string Manufacturer { get { return DeviceNode.GetPropertyString(CMRDP.MFG); } }
+		public string FullName {
+			get {
+				String desc = Name;
+				String mfg = Manufacturer;
+				if (mfg == null) return desc;
+				if (desc == null) return mfg;
+				return mfg + " - " + desc;
+			}
+		}
+
 		public IUsbDevice Open() { return new VBoxUSB(this); }
-		public USBRegistry(DeviceNode devnode, String intf) : base(devnode, intf) { }
 	}
 
 	public class VBoxUSB : UsbInterface, IUsbDevice {
@@ -269,10 +317,15 @@
 		static SafeFileHandle hMonitor = null;
 		const String USBMON_DEVICE_NAME = "\\\\.\\VBoxUSBMon";
 
-		static unsafe void SyncIoControl(SafeHandle hDevice, int IoControlCode, void* InBuffer, int nInBufferSize, void* OutBuffer, int nOutBufferSize) {
+		static unsafe int SyncIoControl(SafeHandle hDevice, int IoControlCode, void* InBuffer, int nInBufferSize, void* OutBuffer, int nOutBufferSize, Boolean throwError) {
 			Int32 pBytesReturned = 0;
-			if (!Kernel32.DeviceIoControl(hDevice, IoControlCode, InBuffer, nInBufferSize, OutBuffer, nOutBufferSize, out pBytesReturned, null))
-				throw new Win32Exception(Marshal.GetLastWin32Error());
+			if (Kernel32.DeviceIoControl(hDevice, IoControlCode, InBuffer, nInBufferSize, OutBuffer, nOutBufferSize, out pBytesReturned, null)) return 0;
+			int ret = Marshal.GetLastWin32Error();
+			if (throwError) throw new Win32Exception(ret);
+			return ret;
+		}
+		static unsafe void SyncIoControl(SafeHandle hDevice, int IoControlCode, void* InBuffer, int nInBufferSize, void* OutBuffer, int nOutBufferSize) {
+			SyncIoControl(hDevice, IoControlCode, InBuffer, nInBufferSize, OutBuffer, nOutBufferSize, true);
 		}
 		
 		unsafe static void InitMonitor() {
@@ -326,8 +379,8 @@
 			initFilterFromDevice(ref Filter, aDevice);
 			IntPtr pvId = USBLibAddFilter(ref Filter);
 			if (pvId == IntPtr.Zero) throw new Exception("Add one-shot Filter failed");
-			//USBLibRunFilters();
-			aDevice.Reenumerate(0);
+			USBLibRunFilters();
+			//aDevice.Reenumerate(0);
 		}
 		public unsafe static void Release(DeviceNode aDevice) {
 			InitMonitor();
@@ -335,8 +388,8 @@
 			initFilterFromDevice(ref Filter, aDevice);
 			IntPtr pvId = USBLibAddFilter(ref Filter);
 			if (pvId == IntPtr.Zero) throw new Exception("Add one-shot Filter failed");
-			//USBLibRunFilters();
-			aDevice.Reenumerate(0);
+			USBLibRunFilters();
+			//aDevice.Reenumerate(0);
 		}
 		public static IUsbDeviceRegistry GetDeviceForDeviceNode(DeviceNode device) {
 			String[] intfpath = device.GetInterfaces(new Guid(0x873fdf, 0xCAFE, 0x80EE, 0xaa, 0x5e, 0x0, 0xc0, 0x4f, 0xb1, 0x72, 0xb));
@@ -368,7 +421,7 @@
 		public unsafe override void Close() {
 			if (!hDev.IsInvalid && !hDev.IsClosed) {
 				USBSUP_CLAIMDEV release = new USBSUP_CLAIMDEV() { bInterfaceNumber = bInterfaceNumber };
-				SyncIoControl(hDev, SUPUSB_IOCTL_USB_RELEASE_DEVICE, &release, sizeof(USBSUP_CLAIMDEV), null, 0);
+				SyncIoControl(hDev, SUPUSB_IOCTL_USB_RELEASE_DEVICE, &release, sizeof(USBSUP_CLAIMDEV), null, 0, false);
 			}
 			hDev.Close();
 		}
@@ -409,6 +462,7 @@
 		}
 
 		private unsafe int BlockTransfer(USBSUP_TRANSFER_TYPE type, USBSUP_DIRECTION dir, USBSUP_XFER_FLAG flags, UInt32 ep, 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");
 			fixed (Byte* ptr = buffer) {
 				USBSUP_URB urb = new USBSUP_URB();
 				urb.type = type;
@@ -416,7 +470,7 @@
 				urb.flags = flags;
 				urb.ep = ep;
 				urb.len = (UIntPtr)length;
-				urb.buf = ptr;
+				urb.buf = ptr + offset;
 				HandleURB(&urb);
 				return (int)urb.len;
 			}
--- a/USBLib/Windows/USB/UsbBus.cs	Wed Oct 09 20:56:28 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-using System;
-using System.Collections.Generic;
-using UCIS.HWLib.Windows.Devices;
-using UCIS.USBLib.Internal.Windows;
-
-namespace UCIS.HWLib.Windows.USB {
-	public class UsbBus {
-		private List<UsbController> devices = null;
-		public IList<UsbController> Controllers {
-			get {
-				if (devices == null) Refresh();
-				return devices.AsReadOnly();
-			}
-		}
-		public void Refresh() {
-			devices = new List<UsbController>();
-			Guid m_Guid = new Guid(UsbApi.GUID_DEVINTERFACE_HUBCONTROLLER);
-			foreach (DeviceNode dev in DeviceNode.GetDevices(m_Guid)) {
-				String[] interfaces = dev.GetInterfaces(m_Guid);
-				if (interfaces == null || interfaces.Length == 0) continue;
-				devices.Add(new UsbController(this, dev, interfaces[0]));
-			}
-		}
-	}
-}
\ No newline at end of file
--- a/USBLib/Windows/USB/UsbController.cs	Wed Oct 09 20:56:28 2013 +0200
+++ b/USBLib/Windows/USB/UsbController.cs	Sat Oct 12 16:35:24 2013 +0200
@@ -1,19 +1,16 @@
 using System;
-using System.Runtime.InteropServices;
+using System.Collections.Generic;
 using Microsoft.Win32.SafeHandles;
 using UCIS.HWLib.Windows.Devices;
 using UCIS.USBLib.Internal.Windows;
 
 namespace UCIS.HWLib.Windows.USB {
 	public class UsbController {
+		static readonly Guid IID_DEVINTERFACE_USB_CONTROLLER = new Guid(UsbApi.GUID_DEVINTERFACE_HUBCONTROLLER);
 		public String DevicePath { get; private set; }
 		public DeviceNode DeviceNode { get; private set; }
-		public String DeviceDescription {
-			get { return DeviceNode.GetPropertyString(SPDRP.DeviceDesc); }
-		}
-		public String DriverKey {
-			get { return DeviceNode.GetPropertyString(SPDRP.Driver); }
-		}
+		public String DeviceDescription { get { return DeviceNode.DeviceDescription; } }
+		public String DriverKey { get { return DeviceNode.DriverKey; } }
 		public UsbHub RootHub {
 			get {
 				String rootHubName;
@@ -21,9 +18,24 @@
 				return new UsbHub(null, new USB_NODE_CONNECTION_INFORMATION_EX(), @"\\?\" + rootHubName, 0, true);
 			}
 		}
-		internal UsbController(UsbBus parent, DeviceNode di, String devicePath) {
+		private UsbController(DeviceNode di, String devicePath) {
 			this.DeviceNode = di;
 			this.DevicePath = devicePath;
 		}
+
+		public static UsbController GetControllerForDeviceNode(DeviceNode node) {
+			String[] interfaces = node.GetInterfaces(IID_DEVINTERFACE_USB_CONTROLLER);
+			if (interfaces == null || interfaces.Length == 0) return null;
+			return new UsbController(node, interfaces[0]);
+		}
+
+		public static IList<UsbController> GetControllers() {
+			IList<UsbController>  devices = new List<UsbController>();
+			foreach (DeviceNode dev in DeviceNode.GetDevices(IID_DEVINTERFACE_USB_CONTROLLER)) {
+				UsbController controller = GetControllerForDeviceNode(dev);
+				if (controller != null) devices.Add(controller);
+			}
+			return devices;
+		}
 	}
 }
--- a/USBLib/Windows/USB/UsbDevice.cs	Wed Oct 09 20:56:28 2013 +0200
+++ b/USBLib/Windows/USB/UsbDevice.cs	Sat Oct 12 16:35:24 2013 +0200
@@ -1,8 +1,6 @@
 using System;
-using System.Collections.Generic;
 using System.ComponentModel;
 using System.Runtime.InteropServices;
-using System.Text;
 using Microsoft.Win32.SafeHandles;
 using UCIS.HWLib.Windows.Devices;
 using UCIS.USBLib.Communication;
@@ -10,8 +8,8 @@
 using UCIS.USBLib.Internal.Windows;
 
 namespace UCIS.HWLib.Windows.USB {
-	public class UsbDevice : IUsbInterface {
-		internal static SafeFileHandle OpenHandle(String path) {
+	public class UsbDevice : IUsbDevice, IUsbInterface {
+		protected internal static SafeFileHandle OpenHandle(String path) {
 			SafeFileHandle handle = Kernel32.CreateFile(path, Kernel32.GENERIC_WRITE, Kernel32.FILE_SHARE_WRITE, IntPtr.Zero, Kernel32.OPEN_EXISTING, 0, IntPtr.Zero);
 			if (handle.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error());
 			return handle;
@@ -29,7 +27,7 @@
 				throw new Win32Exception(Marshal.GetLastWin32Error());
 			return true;
 		}
-		internal static String GetNodeConnectionName(SafeFileHandle handle, UInt32 port) {
+		protected static String GetNodeConnectionName(SafeFileHandle handle, UInt32 port) {
 			int nBytes = Marshal.SizeOf(typeof(USB_NODE_CONNECTION_NAME));
 			USB_NODE_CONNECTION_NAME nameConnection = new USB_NODE_CONNECTION_NAME();
 			nameConnection.ConnectionIndex = port;
@@ -37,7 +35,7 @@
 				throw new Win32Exception(Marshal.GetLastWin32Error());
 			return nameConnection.NodeName;
 		}
-		internal unsafe static int GetDescriptor(SafeFileHandle handle, UInt32 port, byte descriptorType, byte index, short langId, byte[] buffer, int offset, int length) {
+		protected unsafe static int GetDescriptor(SafeFileHandle handle, UInt32 port, byte descriptorType, byte index, short langId, byte[] buffer, int offset, int length) {
 			int szRequest = Marshal.SizeOf(typeof(USB_DESCRIPTOR_REQUEST));
 			USB_DESCRIPTOR_REQUEST request = new USB_DESCRIPTOR_REQUEST();
 			request.ConnectionIndex = port;
@@ -57,7 +55,7 @@
 			if (nBytes > 0) Buffer.BlockCopy(bigbuffer, szRequest, buffer, offset, nBytes);
 			return nBytes;
 		}
-		internal unsafe static String GetRootHubName(SafeFileHandle handle) {
+		protected internal unsafe static String GetRootHubName(SafeFileHandle handle) {
 			USB_ROOT_HUB_NAME rootHubName = new USB_ROOT_HUB_NAME();
 			int nBytesReturned;
 			if (!Kernel32.DeviceIoControl(handle, UsbApi.IOCTL_USB_GET_ROOT_HUB_NAME, IntPtr.Zero, 0, out rootHubName, Marshal.SizeOf(rootHubName), out nBytesReturned, IntPtr.Zero))
@@ -65,7 +63,7 @@
 			if (rootHubName.ActualLength <= 0) return null;
 			return rootHubName.RootHubName;
 		}
-		internal unsafe static String GetNodeConnectionDriverKey(SafeFileHandle handle, UInt32 port) {
+		protected unsafe static String GetNodeConnectionDriverKey(SafeFileHandle handle, UInt32 port) {
 			USB_NODE_CONNECTION_DRIVERKEY_NAME DriverKeyStruct = new USB_NODE_CONNECTION_DRIVERKEY_NAME();
 			int nBytes = Marshal.SizeOf(DriverKeyStruct);
 			DriverKeyStruct.ConnectionIndex = port;
@@ -75,10 +73,10 @@
 		}
 
 		public UsbDevice Parent { get; protected set; }
-		public string DevicePath { get; private set; }
-		public uint AdapterNumber { get; private set; }
+		public String DevicePath { get; private set; }
+		public UInt32 AdapterNumber { get; private set; }
 		internal USB_NODE_CONNECTION_INFORMATION_EX NodeConnectionInfo { get; set; }
-		internal USB_DEVICE_DESCRIPTOR DeviceDescriptor { get { return NodeConnectionInfo.DeviceDescriptor; } }
+		private USB_DEVICE_DESCRIPTOR DeviceDescriptor { get { return NodeConnectionInfo.DeviceDescriptor; } }
 
 		public bool IsHub { get { return NodeConnectionInfo.DeviceIsHub != 0; } }
 		public bool IsConnected { get { return NodeConnectionInfo.ConnectionStatus == USB_CONNECTION_STATUS.DeviceConnected; } }
@@ -105,7 +103,7 @@
 		public string SerialNumber { get { return DeviceDescriptor == null ? null : GetStringSafe(DeviceDescriptor.iSerialNumber); } }
 		public virtual string DriverKey { get { using (SafeFileHandle handle = OpenHandle(DevicePath)) return UsbHub.GetNodeConnectionDriverKey(handle, AdapterNumber); } }
 
-		public virtual string DeviceDescription { get { return DeviceNode == null ? null : DeviceNode.GetPropertyString(CMRDP.DEVICEDESC); } }
+		public virtual string DeviceDescription { get { return DeviceNode == null ? null : DeviceNode.DeviceDescription; } }
 		public string DeviceID { get { return DeviceNode == null ? null : DeviceNode.DeviceID; } }
 
 		private DeviceNode mDeviceNode;
@@ -137,10 +135,10 @@
 		}
 
 		static UsbDevice GetUsbDevice(DeviceNode node, out Boolean isHostController) {
-			String[] hciinterface = node.GetInterfaces(UsbApi.GUID_DEVINTERFACE_USB_HOST_CONTROLLER);
-			if (hciinterface != null && hciinterface.Length > 0) {
+			UsbController controller = UsbController.GetControllerForDeviceNode(node);
+			if (controller != null) {
 				isHostController = true;
-				return (new UsbController(null, node, hciinterface[0])).RootHub;
+				return controller.RootHub;
 			}
 			isHostController = false;
 			DeviceNode parent = node.GetParent();
@@ -148,8 +146,12 @@
 			UsbDevice usbdev = GetUsbDevice(parent, out isHostControllerA);
 			if (isHostControllerA) return usbdev;
 			UsbHub usbhub = usbdev as UsbHub;
-			if (usbhub == null) return null;
+			if (usbhub == null) {
+				if (parent.Service == "usbccgp") return usbdev;
+				return null;
+			}
 			String driverkey = node.DriverKey;
+			if (driverkey == null) return null;
 			foreach (UsbDevice child in usbhub.Devices) {
 				if (driverkey.Equals(child.DriverKey, StringComparison.InvariantCultureIgnoreCase)) return child;
 			}
@@ -158,27 +160,6 @@
 		public static UsbDevice GetUsbDevice(DeviceNode node) {
 			Boolean isHostController;
 			return GetUsbDevice(node, out isHostController);
-			/*
-
-			String[] hubinterface = node.GetInterfaces(UsbApi.GUID_DEVINTERFACE_USB_HUB);
-			if (hubinterface != null && hubinterface.Length > 0) {
-				USB_NODE_CONNECTION_INFORMATION_EX nodeConnection;
-				using (SafeFileHandle handle = OpenHandle(hubinterface[0])) {
-					if (!GetNodeConnectionInformation(handle, 0, out nodeConnection)) return null;
-				}
-				return new UsbHub(null, nodeConnection, hubinterface[0], false);
-			}
-			String[] devinterface = node.GetInterfaces(UsbApi.GUID_DEVINTERFACE_USB_DEVICE);
-			if (devinterface == null || devinterface.Length == 0) return null;
-			DeviceNode parent = node.GetParent();
-			if (parent == null) return null;
-			UsbHub usbhub = GetUsbDevice(parent) as UsbHub;
-			if (usbhub == null) return null;
-			String driverkey = node.DriverKey;
-			foreach (UsbDevice usbdev in usbhub.Devices) {
-				if (driverkey.Equals(usbdev.DriverKey, StringComparison.InvariantCultureIgnoreCase)) return usbdev;
-			}
-			return null;*/
 		}
 
 		#region IUsbInterface Members
@@ -202,6 +183,12 @@
 		UsbPipeStream IUsbInterface.GetInterruptStream(byte endpoint) { throw new NotImplementedException(); }
 		void IDisposable.Dispose() { }
 		#endregion
+		#region IUsbDevice Members
+		byte IUsbDevice.Configuration { get { throw new NotSupportedException(); } set { throw new NotSupportedException(); } }
+		void IUsbDevice.ClaimInterface(int interfaceID) { }
+		void IUsbDevice.ReleaseInterface(int interfaceID) {	}
+		void IUsbDevice.ResetDevice() { throw new NotSupportedException(); }
+		IUsbDeviceRegistry IUsbDevice.Registry { get { throw new NotImplementedException(); } }
+		#endregion
 	}
-	
 }
--- a/USBLib/Windows/USB/UsbHub.cs	Wed Oct 09 20:56:28 2013 +0200
+++ b/USBLib/Windows/USB/UsbHub.cs	Sat Oct 12 16:35:24 2013 +0200
@@ -1,10 +1,9 @@
 using System;
 using System.Collections.Generic;
+using System.ComponentModel;
 using System.Runtime.InteropServices;
 using Microsoft.Win32.SafeHandles;
 using UCIS.USBLib.Internal.Windows;
-using System.ComponentModel;
-using UCIS.USBLib.Communication;
 
 namespace UCIS.HWLib.Windows.USB {
 	public class UsbHub : UsbDevice {
@@ -18,7 +17,7 @@
 		public override string DriverKey {
 			get {
 				if (Parent == null) return null;
-				using (SafeFileHandle handle = OpenHandle(Parent.DevicePath)) return UsbHub.GetNodeConnectionDriverKey(handle, AdapterNumber);
+				using (SafeFileHandle handle = OpenHandle(Parent.DevicePath)) return GetNodeConnectionDriverKey(handle, AdapterNumber);
 			}
 		}
 		
@@ -34,7 +33,7 @@
 
 		public override int GetDescriptor(byte descriptorType, byte index, short langId, byte[] buffer, int offset, int length) {
 			if (Parent == null) return 0;
-			using (SafeFileHandle handle = UsbHub.OpenHandle(Parent.DevicePath)) return UsbHub.GetDescriptor(handle, AdapterNumber, descriptorType, index, langId, buffer, offset, length);
+			using (SafeFileHandle handle = UsbHub.OpenHandle(Parent.DevicePath)) return GetDescriptor(handle, AdapterNumber, descriptorType, index, langId, buffer, offset, length);
 		}