title: Windows API USB IO (winusb.dll)
body: <p><strong>Edit: This question evolved over time. The basic question was about how to connect to a and read/write to/from a USB device in Windows. Eventually I answered the question with the help of @benvoigt.</strong> </p>
  
  <p>I have written a Hid library which writes and reads to/from Hid USB devices. It works well. However, the device I am connecting to has switched from Hid access to vanilla USB. The Hid code does not work when connecting to the different type of device. My aim now is to connect to the USB interface (as opposed to the Hid interface) and read/write to/from it.</p>
  
  <p>On all platforms that access USB, we have to query the interfaces that exist for the USB device, and then "claim" an interface for reading and writing. Here is some code from a LibUsbDotNet sample (LibUsb is a working C USB library and LibUsbDotNet wraps it) <a href="https://github.com/LibUsbDotNet/LibUsbDotNet/blob/master/src/Examples/Read.Write/ReadWrite.cs" rel="nofollow noreferrer">https://github.com/LibUsbDotNet/LibUsbDotNet/blob/master/src/Examples/Read.Write/ReadWrite.cs</a>.</p>
  
  <pre><code>            using (var context = new UsbContext())
              {
                  context.SetDebugLevel(LogLevel.Info);
  
                  //Get a list of all connected devices
                  var usbDeviceCollection = context.List();
  
                  //Narrow down the device by vendor and pid
                  var selectedDevice = usbDeviceCollection.FirstOrDefault(d =&gt; d.ProductId == ProductId &amp;&amp; d.VendorId == VendorId);
  
                  //Open the device
                  selectedDevice.Open();
  
                  //Get the first config number of the interface
                  selectedDevice.ClaimInterface(selectedDevice.Configs[0].Interfaces[0].Number);
  
                  //Open up the endpoints
                  var writeEndpoint = selectedDevice.OpenEndpointWriter(WriteEndpointID.Ep01);
                  var readEnpoint = selectedDevice.OpenEndpointReader(ReadEndpointID.Ep01);
  
                  //Create a buffer with some data in it
                  var buffer = new byte[64];
                  buffer[0] = 0x3f;
                  buffer[1] = 0x23;
                  buffer[2] = 0x23;
  
                  //Write three bytes
                  writeEndpoint.Write(buffer, 3000, out var bytesWritten);
  
                  var readBuffer = new byte[64];
  
                  //Read some data
                  readEnpoint.Read(readBuffer, 3000, out var readBytes);
              }
  }
  </code></pre>
  
  <p>I have a feeling that LibUsb is achieving the opening of interfaces/endpoints in C like this (<a href="https://github.com/libusb/libusb/blob/c6f3866414e8deeee19e8a9f10f20bde9cb408d3/libusb/os/windows_winusb.c#L2199" rel="nofollow noreferrer">https://github.com/libusb/libusb/blob/c6f3866414e8deeee19e8a9f10f20bde9cb408d3/libusb/os/windows_winusb.c#L2199</a>) . This is where it calls Initialize: <a href="https://github.com/libusb/libusb/blob/c6f3866414e8deeee19e8a9f10f20bde9cb408d3/libusb/os/windows_winusb.c#L2225" rel="nofollow noreferrer">https://github.com/libusb/libusb/blob/c6f3866414e8deeee19e8a9f10f20bde9cb408d3/libusb/os/windows_winusb.c#L2225</a> which is where my code is failing.</p>
  
  <p>A little snippet of information is that this is definitely a WinUSB device. I can see that here:</p>
  
  <p><a href="https://i.stack.imgur.com/me0Zu.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/me0Zu.png" alt="enter image description here"></a></p>
  
  <p>Based on other people's comments and sample code, I can see that I need to use winusb.dll. I am able to call CreateFile to get a handle from the device. According to other sample code I have seen, the next step is to call WinUsb_Initialize. However, when I call this, I get an error code of 8 (ERROR_NOT_ENOUGH_MEMORY). There is some information here <a href="https://docs.microsoft.com/en-us/windows/desktop/api/winusb/nf-winusb-winusb_initialize" rel="nofollow noreferrer">https://docs.microsoft.com/en-us/windows/desktop/api/winusb/nf-winusb-winusb_initialize</a> . But, I don't quite understand what it is asking me to do. This is my code so far:</p>
  
  <pre><code>    public override async Task InitializeAsync()
      {
          Dispose();
  
          if (string.IsNullOrEmpty(DeviceId))
          {
              throw new WindowsException($"{nameof(DeviceDefinition)} must be specified before {nameof(InitializeAsync)} can be called.");
          }
  
          _DeviceHandle = APICalls.CreateFile(DeviceId, (APICalls.GenericWrite | APICalls.GenericRead), APICalls.FileShareRead | APICalls.FileShareWrite, IntPtr.Zero, APICalls.OpenExisting, APICalls.FileAttributeNormal | APICalls.FileFlagOverlapped, IntPtr.Zero);
  
          var errorCode = Marshal.GetLastWin32Error();
  
          if (errorCode &gt; 0) throw new Exception($"Write handle no good. Error code: {errorCode}");
  
          if (_DeviceHandle.IsInvalid) throw new Exception("Device handle no good");
  
          var isSuccess = WinUsbApiCalls.WinUsb_Initialize(_DeviceHandle, out var interfaceHandle);
  
          errorCode = Marshal.GetLastWin32Error();
  
          if (!isSuccess) throw new Exception($"Initialization failed. Error code: {errorCode}");
  
          IsInitialized = true;
  
          RaiseConnected();
      }
  </code></pre>
  
  <p>You can clone the branch of this repo here: <a href="https://github.com/MelbourneDeveloper/Device.Net/tree/WindowsUsbDevice" rel="nofollow noreferrer">https://github.com/MelbourneDeveloper/Device.Net/tree/WindowsUsbDevice</a>. Just run the Usb.Net.WindowsSample project.</p>
  
  <p>I also tried this and got exactly the same result:</p>
  
  <pre><code>public override async Task InitializeAsync()
  {
      Dispose();
  
      if (string.IsNullOrEmpty(DeviceId))
      {
          throw new WindowsException($"{nameof(DeviceDefinition)} must be specified before {nameof(InitializeAsync)} can be called.");
      }
  
      _DeviceHandle = APICalls.CreateFile(DeviceId, (APICalls.GenericWrite | APICalls.GenericRead), APICalls.FileShareRead | APICalls.FileShareWrite, IntPtr.Zero, APICalls.OpenExisting, APICalls.FileAttributeNormal | APICalls.FileFlagOverlapped, IntPtr.Zero);
  
      var errorCode = Marshal.GetLastWin32Error();
  
      if (errorCode &gt; 0) throw new Exception($"Write handle no good. Error code: {errorCode}");
  
      var interfaceHandle = new IntPtr();
  
      var pDll = NativeMethods.LoadLibrary(@"C:\GitRepos\Device.Net\src\Usb.Net.WindowsSample\bin\Debug\net452\winusb.dll");
  
      var pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "WinUsb_Initialize");
  
      var initialize = (WinUsb_Initialize)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall, typeof(WinUsb_Initialize));
  
      var isSuccess = initialize(_DeviceHandle, ref interfaceHandle);
  
      errorCode = Marshal.GetLastWin32Error();
  
      if (!isSuccess) throw new Exception($"Initialization failed. Error code: {errorCode}");
  
      IsInitialized = true;
  
      RaiseConnected();
  }
  
  [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  private delegate bool WinUsb_Initialize(SafeFileHandle DeviceHandle, ref IntPtr InterfaceHandle);
  </code></pre>
  
  <p>I strongly believe that there is something wrong with the device's WinUSB implementation itself. It works with other libraries like LibUsb, UWP, and Android, but WinUsb doesn't seem to like it. I tried this library: <a href="https://github.com/madwizard-thomas/winusbnet" rel="nofollow noreferrer">https://github.com/madwizard-thomas/winusbnet</a> and it also fails on the same call with the same error code. The line it fails on and gets error code 8 is here: <a href="https://github.com/madwizard-thomas/winusbnet/blob/8f62d751a99be1e31d34b91115715d60aeff2dfc/WinUSBNet/API/WinUSBDevice.cs#L225" rel="nofollow noreferrer">https://github.com/madwizard-thomas/winusbnet/blob/8f62d751a99be1e31d34b91115715d60aeff2dfc/WinUSBNet/API/WinUSBDevice.cs#L225</a></p>
  
  <p><strong>What is wrong with my code here? Is there something I need to do to allocate memory for the WinUsb_Initialize call?</strong></p>
  
  <p><strong>How should I use the winusb.dll Windows API? What API calls do I need to make to claim and interface or endpoint for reading and writing?</strong></p>
  
  <p><strong>It would really help me if someone could point me to a simple C or C# sample that reads and writes to a USB device and actually works</strong>.</p>
  
  <p>WinDBG output:</p>
  
  <blockquote>
    <p>************* Path validation summary ************** Response                         Time (ms)     Location Deferred<br>
    srv* Symbol search path is: srv* Executable search path is:  ModLoad:
    00000236<code>157c0000 00000236</code>157c8000   Usb.Net.WindowsSample.exe
    ModLoad: 00007ffb<code>62880000 00007ffb</code>62a61000   ntdll.dll ModLoad:
    00007ffb<code>60f40000 00007ffb</code>610d0000   C:\WINDOWS\System32\user32.dll
    ModLoad: 00007ffb<code>5ed00000 00007ffb</code>5ed20000<br>
    C:\WINDOWS\System32\win32u.dll ModLoad: 00007ffb<code>4e1b0000
    00007ffb</code>4e214000   C:\WINDOWS\SYSTEM32\MSCOREE.DLL ModLoad:
    00007ffb<code>612a0000 00007ffb</code>612c8000   C:\WINDOWS\System32\GDI32.dll
    onecore\windows\core\console\open\src\renderer\gdi\invalidate.cpp(121)\conhost.exe!00007FF7169FE2AF:
    (caller: 00007FF7169FF414) ReturnHr(1) tid(4230) 80070578 Invalid
    window handle. ModLoad: 00007ffb<code>60990000 00007ffb</code>60a42000<br>
    C:\WINDOWS\System32\KERNEL32.dll ModLoad: 00007ffb<code>5f000000
    00007ffb</code>5f192000   C:\WINDOWS\System32\gdi32full.dll ModLoad:
    00007ffb<code>60d90000 00007ffb</code>60f03000   C:\WINDOWS\System32\MSCTF.dll
    ModLoad: 00007ffb<code>5ed80000 00007ffb</code>5eff3000<br>
    C:\WINDOWS\System32\KERNELBASE.dll ModLoad: 00007ffb<code>60610000
    00007ffb</code>606d2000   C:\WINDOWS\System32\OLEAUT32.dll ModLoad:
    00007ffb<code>60f10000 00007ffb</code>60f3d000   C:\WINDOWS\System32\IMM32.DLL</p>
    
    <p>************* Path validation summary ************** Response                         Time (ms)     Location Deferred<br>
    srv* Symbol search path is: srv* Executable search path is:  ModLoad:
    00007ff7<code>169f0000 00007ff7</code>16a8f000   conhost.exe ModLoad:
    00007ffb<code>61340000 00007ffb</code>62780000   C:\WINDOWS\System32\shell32.dll
    ModLoad: 00007ffb<code>5cd80000 00007ffb</code>5cda9000<br>
    C:\WINDOWS\system32\dwmapi.dll ModLoad: 00007ffb<code>62880000
    00007ffb</code>62a61000   ntdll.dll ModLoad: 00007ffb<code>5fcc0000
    00007ffb</code>5fd09000   C:\WINDOWS\System32\cfgmgr32.dll ModLoad:
    00007ffb<code>5f530000 00007ffb</code>5fc3d000<br>
    C:\WINDOWS\System32\windows.storage.dll
    onecore\windows\core\console\open\src\renderer\gdi\invalidate.cpp(121)\conhost.exe!00007FF7169FE2AF:
    (caller: 00007FF7169FF414) ReturnHr(2) tid(4230) 80070578 Invalid
    window handle. ModLoad: 00007ffb<code>61140000 00007ffb</code>61191000<br>
    C:\WINDOWS\System32\shlwapi.dll ModLoad: 00007ffb<code>60990000
    00007ffb</code>60a42000   C:\WINDOWS\System32\KERNEL32.DLL ModLoad:
    00007ffb<code>5ec30000 00007ffb</code>5ec41000<br>
    C:\WINDOWS\System32\kernel.appcore.dll ModLoad: 00007ffb<code>5ed80000
    00007ffb</code>5eff3000   C:\WINDOWS\System32\KERNELBASE.dll ModLoad:
    00007ffb<code>5ec10000 00007ffb</code>5ec2f000   C:\WINDOWS\System32\profapi.dll
    ModLoad: 00007ffb<code>5ebc0000 00007ffb</code>5ec0c000<br>
    C:\WINDOWS\System32\powrprof.dll ModLoad: 00007ffb<code>5ebb0000
    00007ffb</code>5ebba000   C:\WINDOWS\System32\FLTLIB.DLL ModLoad:
    00007ffb<code>5f490000 00007ffb</code>5f52f000<br>
    C:\WINDOWS\System32\msvcp_win.dll ModLoad: 00007ffb<code>5f1a0000
    00007ffb</code>5f29a000   C:\WINDOWS\System32\ucrtbase.dll ModLoad:
    00007ffb<code>606e0000 00007ffb</code>60789000   C:\WINDOWS\System32\shcore.dll
    ModLoad: 00007ffb<code>4e290000 00007ffb</code>4e4f9000<br>
    C:\WINDOWS\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.17134.472_none_fb3f9af53068156d\comctl32.DLL
    ModLoad: 00007ffb<code>5ca60000 00007ffb</code>5caf8000<br>
    C:\WINDOWS\system32\uxtheme.dll ModLoad: 00007ffb<code>608f0000
    00007ffb</code>6098e000   C:\WINDOWS\System32\msvcrt.dll ModLoad:
    00007ffb<code>601e0000 00007ffb</code>60304000   C:\WINDOWS\System32\RPCRT4.dll
    ModLoad: 00007ffb<code>60a60000 00007ffb</code>60d82000<br>
    C:\WINDOWS\System32\combase.dll ModLoad: 00007ffb<code>5fc40000
    00007ffb</code>5fcba000   C:\WINDOWS\System32\bcryptPrimitives.dll ModLoad:
    00007ffb<code>627a0000 00007ffb</code>62841000   C:\WINDOWS\System32\advapi32.dll
    ModLoad: 00007ffb<code>610d0000 00007ffb</code>6112b000<br>
    C:\WINDOWS\System32\sechost.dll ModLoad: 00007ffb<code>57b30000
    00007ffb</code>57bc6000   C:\WINDOWS\System32\TextInputFramework.dll
    (3d80.256c): Break instruction exception - code 80000003 (first
    chance) ntdll!LdrpDoDebuggerBreak+0x30: 00007ffb`6294c93c cc<br>
    int     3</p>
  </blockquote>