C# Windows API USB IO(winusb.dll)

C# Windows API USB IO(winusb.dll),c#,winapi,usb,hid,winusb,C#,Winapi,Usb,Hid,Winusb,编辑:这个问题随着时间的推移而演变。基本问题是如何连接到Windows中的USB设备,以及如何在Windows中读取/写入USB设备。最后,我在@benvoigt的帮助下回答了这个问题。 我已经编写了一个Hid库,它向Hid USB设备写入和读取数据。它工作得很好。但是,我连接的设备已从Hid访问切换到香草USB。当连接到不同类型的设备时,Hid代码不起作用。我现在的目标是连接到USB接口(与Hid接口相反)并对其进行读/写操作 在所有访问USB的平台上,我们必须查询USB设备存在的接口,然后“

编辑:这个问题随着时间的推移而演变。基本问题是如何连接到Windows中的USB设备,以及如何在Windows中读取/写入USB设备。最后,我在@benvoigt的帮助下回答了这个问题。

我已经编写了一个Hid库,它向Hid USB设备写入和读取数据。它工作得很好。但是,我连接的设备已从Hid访问切换到香草USB。当连接到不同类型的设备时,Hid代码不起作用。我现在的目标是连接到USB接口(与Hid接口相反)并对其进行读/写操作

在所有访问USB的平台上,我们必须查询USB设备存在的接口,然后“声明”用于读写的接口。下面是来自LibUsbDotNet示例的一些代码(LibUsb是一个工作的C-USB库,LibUsbDotNet对其进行了包装)

我有一种感觉,LibUsb正在实现C中接口/端点的开放,就像这样()。这就是它调用Initialize的地方:这就是我的代码失败的地方

有一点信息是,这绝对是一个WinUSB设备。我可以在这里看到:

根据其他人的评论和示例代码,我可以看出我需要使用winusb.dll。我可以调用CreateFile从设备获取句柄。根据我看到的其他示例代码,下一步是调用WinUsb\u Initialize。然而,当我调用它时,我得到一个错误代码8(错误\u内存不足)。这里有一些信息。但是,我不太明白它要我做什么。这是我目前的代码:

    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 > 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();
    }
您可以在此处克隆此回购的分支:。只需运行Usb.Net.WindowsSample项目

我也试过了,得到了完全相同的结果:

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 > 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);
我坚信该设备的WinUSB实现本身有问题。它可以与LibUsb、UWP和Android等其他库一起使用,但WinUsb似乎不喜欢它。我尝试了这个库:它在同一次调用中也失败了,错误代码相同。它发生故障并获得错误代码8的行如下所示:

我的代码有什么问题?我需要为WinUsb\u初始化调用分配内存吗?

我应该如何使用winusb.dll Windows API?我需要进行哪些API调用来声明和接口或端点以进行读写?

如果有人能给我指出一个简单的C或C样本,它可以读取和写入USB设备,并实际工作,那将对我有很大帮助

WinDBG输出:

*************路径验证摘要*************响应时间(毫秒)位置延迟
srv*符号搜索路径为:srv*可执行搜索路径为:ModLoad: 00000236
157c0000 00000236
157c8000 Usb.Net.WindowsSample.exe ModLoad:00007ffb
62880000 00007ffb
62a61000 ntdll.dll ModLoad: 00007ffb
60F400000007FFB
610d0000 C:\WINDOWS\System32\user32.dll ModLoad:00007ffb
5ed00000 00007ffb
5ed20000
C:\WINDOWS\System32\win32u.dll ModLoad:00007ffb
4e1b0000
00007ffb
4e214000 C:\WINDOWS\SYSTEM32\MSCOREE.DLL ModLoad: 00007ffb
612a0000 00007ffb
612c8000 C:\WINDOWS\System32\GDI32.dll onecore\windows\core\console\open\src\renderer\gdi\invalidate.cpp(121)\conhost.exe!00007FF7169FE2AF: (呼叫者:00007FF7169FF414)返回HR(1)tid(4230)80070578无效 窗户把手。ModLoad:00007ffb
60990000 00007ffb
60a42000
C:\WINDOWS\System32\KERNEL32.dll ModLoad:00007ffb
5f000000
00007ffb
5f192000 C:\WINDOWS\System32\gdi32full.dll ModLoad: 00007ffb
60d90000 00007ffb
60f03000 C:\WINDOWS\System32\MSCTF.dll ModLoad:00007ffb
5ed80000 00007ffb
5eff3000
C:\WINDOWS\System32\KERNELBASE.dll ModLoad:00007ffb
60610000
00007ffb
606d2000 C:\WINDOWS\System32\OLEAUT32.dll ModLoad: 00007ffb
60f10000 00007ffb
60f3d000C:\WINDOWS\System32\IMM32.DLL

*************路径验证摘要*************响应时间(毫秒)位置延迟
srv*符号搜索路径为:srv*可执行搜索路径为:ModLoad: 00007ff7
169f0000 00007ff7
16a8f000 conhost.exe ModLoad: 00007ffb
613400000 00007ffb
62780000 C:\WINDOWS\System32\shell32.dll ModLoad:00007ffb
5cd80000 00007ffb
5cda9000
C:\WINDOWS\system32\dwmapi.dll ModLoad:00007ffb
62880000
00007ffb
62a61000 ntdll.dll ModLoad:00007ffb
5fcc0000
00007ffb
5fd09000 C:\WINDOWS\System32\cfgmgr32.dll ModLoad: 00007ffb
5F53000007FFB
5fc3d000
C:\WINDOWS\System32\WINDOWS.storage.dll onecore\windows\core\console\open\src\renderer\gdi\invalidate.cpp(121)\conhost.exe!00007FF7169FE2AF: (呼叫者:00007FF7169FF414)返回HR(2)tid(4230)80070578无效 窗户把手。ModLoad:00007ffb
6114000007FFB
61191000
C:\WINDOWS\System32\shlwapi.dll ModLoad:00007ffb
60990000
00007ffb
60a42000 C:\WINDOWS\System32\KERNEL32.DLL ModLoad: 00007ffb
5ec30000 00007ffb
5ec41000
C:\WINDOWS\System32\kernel.appcore.dll ModLoad:00007ffb
5ed80000
00007ffb
5eff3000 C:\WINDOWS\System32\KERNELBASE.dll ModLoad: 00007ffb
5ec10000 00007ffb
5ec2f000 C:\WINDOWS\System32\profapi.dll ModLoad:00007ffb
5ebc0000 00007ffb
5ec0c000
C:\WINDOWS\System32\powrpof.dll ModLoad:00007ffb
5ebb0000
00007ffb
5ebba000 C:\WINDOWS\System32\FLTLIB.DLL ModLoad: 00007ffb
5F49000 00007ffb
5f52f000
C:\WINDOWS\System32\msvcp_win.dll ModLoad:00007ffb
5f1a0000
00007ffb
5f29a000 C:\WINDOWS\System32\ucrtbase.dll ModLoad: 00007ffb
606e0000 00007ffb
60789000 C:\WINDOWS\System32\shcore.dll ModLoad:00007ffb
4e290000 00007ffb
4e4f9000
C:\WINDOWS\WinSxS\
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 > 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);
public static class Kernel32APICalls
{
    //Abridged

    #region Kernel32
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
    #endregion    
}

public static partial class WinUsbApiCalls
{
    public const uint DEVICE_SPEED = 1;
    public const byte USB_ENDPOINT_DIRECTION_MASK = 0X80;
    public const int WritePipeId = 0x80;

    /// <summary>
    /// Not sure where this constant is defined...
    /// </summary>
    public const int DEFAULT_DESCRIPTOR_TYPE = 0x01;

    [DllImport("winusb.dll", SetLastError = true)]
    public static extern bool WinUsb_ControlTransfer(IntPtr InterfaceHandle, WINUSB_SETUP_PACKET SetupPacket, byte[] Buffer, uint BufferLength, ref uint LengthTransferred, IntPtr Overlapped);

    [DllImport("winusb.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern bool WinUsb_GetAssociatedInterface(SafeFileHandle InterfaceHandle, byte AssociatedInterfaceIndex, out SafeFileHandle AssociatedInterfaceHandle);

    [DllImport("winusb.dll", SetLastError = true)]
    public static extern bool WinUsb_GetDescriptor(SafeFileHandle InterfaceHandle, byte DescriptorType, byte Index, ushort LanguageID, out USB_DEVICE_DESCRIPTOR deviceDesc, uint BufferLength, out uint LengthTransfered);

    [DllImport("winusb.dll", SetLastError = true)]
    public static extern bool WinUsb_Free(SafeFileHandle InterfaceHandle);

    [DllImport("winusb.dll", SetLastError = true)]
    public static extern bool WinUsb_Initialize(SafeFileHandle DeviceHandle, out SafeFileHandle InterfaceHandle);

    [DllImport("winusb.dll", SetLastError = true)]
    public static extern bool WinUsb_QueryDeviceInformation(IntPtr InterfaceHandle, uint InformationType, ref uint BufferLength, ref byte Buffer);

    [DllImport("winusb.dll", SetLastError = true)]
    public static extern bool WinUsb_QueryInterfaceSettings(SafeFileHandle InterfaceHandle, byte AlternateInterfaceNumber, out USB_INTERFACE_DESCRIPTOR UsbAltInterfaceDescriptor);

    [DllImport("winusb.dll", SetLastError = true)]
    public static extern bool WinUsb_QueryPipe(SafeFileHandle InterfaceHandle, byte AlternateInterfaceNumber, byte PipeIndex, out WINUSB_PIPE_INFORMATION PipeInformation);

    [DllImport("winusb.dll", SetLastError = true)]
    public static extern bool WinUsb_ReadPipe(SafeFileHandle InterfaceHandle, byte PipeID, byte[] Buffer, uint BufferLength, out uint LengthTransferred, IntPtr Overlapped);

    [DllImport("winusb.dll", SetLastError = true)]
    public static extern bool WinUsb_SetPipePolicy(IntPtr InterfaceHandle, byte PipeID, uint PolicyType, uint ValueLength, ref uint Value);

    [DllImport("winusb.dll", SetLastError = true)]
    public static extern bool WinUsb_WritePipe(SafeFileHandle InterfaceHandle, byte PipeID, byte[] Buffer, uint BufferLength, out uint LengthTransferred, IntPtr Overlapped);
}