comparison USBLib/Communication/VBoxUSB.cs @ 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 b1efeada517e
children 99ed461509fe
comparison
equal deleted inserted replaced
59:4e1a5dec786a 60:3424fa5a12c9
236 public UIntPtr len; 236 public UIntPtr len;
237 public void* buf; 237 public void* buf;
238 public UInt32 numIsoPkts; 238 public UInt32 numIsoPkts;
239 public fixed byte aIsoPkts[8 * 8]; 239 public fixed byte aIsoPkts[8 * 8];
240 } 240 }
241 class USBRegistry : WindowsUsbDeviceRegistry, IUsbDeviceRegistry { 241 class USBRegistry : IUsbDeviceRegistry {
242 public DeviceNode DeviceNode { get; private set; }
243 public String DevicePath { get; private set; }
244 public String DeviceID { get; private set; }
245 public String SymbolicName { get { return DevicePath; } }
246 private UCIS.HWLib.Windows.USB.UsbDevice usbdev = null;
247 private Boolean hasDeviceDescriptor = false;
248 private UCIS.USBLib.Descriptor.UsbDeviceDescriptor deviceDescriptor;
249 private IDictionary<string, object> mDeviceProperties;
250 public UCIS.HWLib.Windows.USB.UsbDevice USBDevice {
251 get {
252 if (usbdev == null) usbdev = UCIS.HWLib.Windows.USB.UsbDevice.GetUsbDevice(DeviceNode);
253 return usbdev;
254 }
255 }
256 public UCIS.USBLib.Descriptor.UsbDeviceDescriptor DeviceDescriptor {
257 get {
258 if (!hasDeviceDescriptor) deviceDescriptor = UCIS.USBLib.Descriptor.UsbDeviceDescriptor.FromDevice(USBDevice);
259 return deviceDescriptor;
260 }
261 }
262 public IDictionary<string, object> DeviceProperties {
263 get {
264 if (mDeviceProperties == null) mDeviceProperties = SetupApi.GetSPDRPProperties(DeviceNode);
265 return mDeviceProperties;
266 }
267 }
268
269 internal USBRegistry(DeviceNode device, String interfacepath) {
270 DeviceNode = device;
271 DeviceID = device.DeviceID;
272 DevicePath = interfacepath;
273 }
274
275 public int Vid { get { return DeviceDescriptor.VendorID; } }
276 public int Pid { get { return DeviceDescriptor.ProductID; } }
277 public byte InterfaceID { get { return 0; } }
278
279 public string Name { get { return DeviceNode.GetPropertyString(CMRDP.DEVICEDESC); } }
280 public string Manufacturer { get { return DeviceNode.GetPropertyString(CMRDP.MFG); } }
281 public string FullName {
282 get {
283 String desc = Name;
284 String mfg = Manufacturer;
285 if (mfg == null) return desc;
286 if (desc == null) return mfg;
287 return mfg + " - " + desc;
288 }
289 }
290
242 public IUsbDevice Open() { return new VBoxUSB(this); } 291 public IUsbDevice Open() { return new VBoxUSB(this); }
243 public USBRegistry(DeviceNode devnode, String intf) : base(devnode, intf) { }
244 } 292 }
245 293
246 public class VBoxUSB : UsbInterface, IUsbDevice { 294 public class VBoxUSB : UsbInterface, IUsbDevice {
247 const int FILE_DEVICE_UNKNOWN = 0x00000022; 295 const int FILE_DEVICE_UNKNOWN = 0x00000022;
248 const int METHOD_BUFFERED = 0; 296 const int METHOD_BUFFERED = 0;
267 const UInt32 USBMON_MINOR_VERSION = 0; 315 const UInt32 USBMON_MINOR_VERSION = 0;
268 316
269 static SafeFileHandle hMonitor = null; 317 static SafeFileHandle hMonitor = null;
270 const String USBMON_DEVICE_NAME = "\\\\.\\VBoxUSBMon"; 318 const String USBMON_DEVICE_NAME = "\\\\.\\VBoxUSBMon";
271 319
320 static unsafe int SyncIoControl(SafeHandle hDevice, int IoControlCode, void* InBuffer, int nInBufferSize, void* OutBuffer, int nOutBufferSize, Boolean throwError) {
321 Int32 pBytesReturned = 0;
322 if (Kernel32.DeviceIoControl(hDevice, IoControlCode, InBuffer, nInBufferSize, OutBuffer, nOutBufferSize, out pBytesReturned, null)) return 0;
323 int ret = Marshal.GetLastWin32Error();
324 if (throwError) throw new Win32Exception(ret);
325 return ret;
326 }
272 static unsafe void SyncIoControl(SafeHandle hDevice, int IoControlCode, void* InBuffer, int nInBufferSize, void* OutBuffer, int nOutBufferSize) { 327 static unsafe void SyncIoControl(SafeHandle hDevice, int IoControlCode, void* InBuffer, int nInBufferSize, void* OutBuffer, int nOutBufferSize) {
273 Int32 pBytesReturned = 0; 328 SyncIoControl(hDevice, IoControlCode, InBuffer, nInBufferSize, OutBuffer, nOutBufferSize, true);
274 if (!Kernel32.DeviceIoControl(hDevice, IoControlCode, InBuffer, nInBufferSize, OutBuffer, nOutBufferSize, out pBytesReturned, null))
275 throw new Win32Exception(Marshal.GetLastWin32Error());
276 } 329 }
277 330
278 unsafe static void InitMonitor() { 331 unsafe static void InitMonitor() {
279 if (hMonitor != null && !hMonitor.IsClosed && !hMonitor.IsInvalid) return; 332 if (hMonitor != null && !hMonitor.IsClosed && !hMonitor.IsInvalid) return;
280 hMonitor = Kernel32.CreateFile(USBMON_DEVICE_NAME, Kernel32.GENERIC_READ | Kernel32.GENERIC_WRITE, Kernel32.FILE_SHARE_READ | Kernel32.FILE_SHARE_WRITE, IntPtr.Zero, Kernel32.OPEN_EXISTING, Kernel32.FILE_ATTRIBUTE_SYSTEM, IntPtr.Zero); 333 hMonitor = Kernel32.CreateFile(USBMON_DEVICE_NAME, Kernel32.GENERIC_READ | Kernel32.GENERIC_WRITE, Kernel32.FILE_SHARE_READ | Kernel32.FILE_SHARE_WRITE, IntPtr.Zero, Kernel32.OPEN_EXISTING, Kernel32.FILE_ATTRIBUTE_SYSTEM, IntPtr.Zero);
324 InitMonitor(); 377 InitMonitor();
325 USBFILTER Filter = new USBFILTER(USBFILTERTYPE.USBFILTERTYPE_ONESHOT_CAPTURE); 378 USBFILTER Filter = new USBFILTER(USBFILTERTYPE.USBFILTERTYPE_ONESHOT_CAPTURE);
326 initFilterFromDevice(ref Filter, aDevice); 379 initFilterFromDevice(ref Filter, aDevice);
327 IntPtr pvId = USBLibAddFilter(ref Filter); 380 IntPtr pvId = USBLibAddFilter(ref Filter);
328 if (pvId == IntPtr.Zero) throw new Exception("Add one-shot Filter failed"); 381 if (pvId == IntPtr.Zero) throw new Exception("Add one-shot Filter failed");
329 //USBLibRunFilters(); 382 USBLibRunFilters();
330 aDevice.Reenumerate(0); 383 //aDevice.Reenumerate(0);
331 } 384 }
332 public unsafe static void Release(DeviceNode aDevice) { 385 public unsafe static void Release(DeviceNode aDevice) {
333 InitMonitor(); 386 InitMonitor();
334 USBFILTER Filter = new USBFILTER(USBFILTERTYPE.USBFILTERTYPE_ONESHOT_IGNORE); 387 USBFILTER Filter = new USBFILTER(USBFILTERTYPE.USBFILTERTYPE_ONESHOT_IGNORE);
335 initFilterFromDevice(ref Filter, aDevice); 388 initFilterFromDevice(ref Filter, aDevice);
336 IntPtr pvId = USBLibAddFilter(ref Filter); 389 IntPtr pvId = USBLibAddFilter(ref Filter);
337 if (pvId == IntPtr.Zero) throw new Exception("Add one-shot Filter failed"); 390 if (pvId == IntPtr.Zero) throw new Exception("Add one-shot Filter failed");
338 //USBLibRunFilters(); 391 USBLibRunFilters();
339 aDevice.Reenumerate(0); 392 //aDevice.Reenumerate(0);
340 } 393 }
341 public static IUsbDeviceRegistry GetDeviceForDeviceNode(DeviceNode device) { 394 public static IUsbDeviceRegistry GetDeviceForDeviceNode(DeviceNode device) {
342 String[] intfpath = device.GetInterfaces(new Guid(0x873fdf, 0xCAFE, 0x80EE, 0xaa, 0x5e, 0x0, 0xc0, 0x4f, 0xb1, 0x72, 0xb)); 395 String[] intfpath = device.GetInterfaces(new Guid(0x873fdf, 0xCAFE, 0x80EE, 0xaa, 0x5e, 0x0, 0xc0, 0x4f, 0xb1, 0x72, 0xb));
343 if (intfpath == null || intfpath.Length == 0) return null; 396 if (intfpath == null || intfpath.Length == 0) return null;
344 return new USBRegistry(device, intfpath[0]); 397 return new USBRegistry(device, intfpath[0]);
366 } 419 }
367 } 420 }
368 public unsafe override void Close() { 421 public unsafe override void Close() {
369 if (!hDev.IsInvalid && !hDev.IsClosed) { 422 if (!hDev.IsInvalid && !hDev.IsClosed) {
370 USBSUP_CLAIMDEV release = new USBSUP_CLAIMDEV() { bInterfaceNumber = bInterfaceNumber }; 423 USBSUP_CLAIMDEV release = new USBSUP_CLAIMDEV() { bInterfaceNumber = bInterfaceNumber };
371 SyncIoControl(hDev, SUPUSB_IOCTL_USB_RELEASE_DEVICE, &release, sizeof(USBSUP_CLAIMDEV), null, 0); 424 SyncIoControl(hDev, SUPUSB_IOCTL_USB_RELEASE_DEVICE, &release, sizeof(USBSUP_CLAIMDEV), null, 0, false);
372 } 425 }
373 hDev.Close(); 426 hDev.Close();
374 } 427 }
375 428
376 public unsafe override void BulkReset(byte endpoint) { 429 public unsafe override void BulkReset(byte endpoint) {
407 throw new Win32Exception(Marshal.GetLastWin32Error()); 460 throw new Win32Exception(Marshal.GetLastWin32Error());
408 } 461 }
409 } 462 }
410 463
411 private unsafe int BlockTransfer(USBSUP_TRANSFER_TYPE type, USBSUP_DIRECTION dir, USBSUP_XFER_FLAG flags, UInt32 ep, Byte[] buffer, int offset, int length) { 464 private unsafe int BlockTransfer(USBSUP_TRANSFER_TYPE type, USBSUP_DIRECTION dir, USBSUP_XFER_FLAG flags, UInt32 ep, Byte[] buffer, int offset, int length) {
465 if (offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer length");
412 fixed (Byte* ptr = buffer) { 466 fixed (Byte* ptr = buffer) {
413 USBSUP_URB urb = new USBSUP_URB(); 467 USBSUP_URB urb = new USBSUP_URB();
414 urb.type = type; 468 urb.type = type;
415 urb.dir = dir; 469 urb.dir = dir;
416 urb.flags = flags; 470 urb.flags = flags;
417 urb.ep = ep; 471 urb.ep = ep;
418 urb.len = (UIntPtr)length; 472 urb.len = (UIntPtr)length;
419 urb.buf = ptr; 473 urb.buf = ptr + offset;
420 HandleURB(&urb); 474 HandleURB(&urb);
421 return (int)urb.len; 475 return (int)urb.len;
422 } 476 }
423 } 477 }
424 478