C# Windows API USB IO(winusb.dll)
编辑:这个问题随着时间的推移而演变。基本问题是如何连接到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内存不足)。这里有一些信息。但是,我不太明白它要我做什么。这是我目前的代码: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设备存在的接口,然后“
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:00007ffb62880000 00007ffb
62a61000 ntdll.dll ModLoad:
00007ffb60F400000007FFB
610d0000 C:\WINDOWS\System32\user32.dll
ModLoad:00007ffb5ed00000 00007ffb
5ed20000C:\WINDOWS\System32\win32u.dll ModLoad:00007ffb
4e1b0000
00007ffb
4e214000 C:\WINDOWS\SYSTEM32\MSCOREE.DLL ModLoad:
00007ffb612a0000 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:00007ffb60990000 00007ffb
60a42000C:\WINDOWS\System32\KERNEL32.dll ModLoad:00007ffb
5f000000
00007ffb
5f192000 C:\WINDOWS\System32\gdi32full.dll ModLoad:
00007ffb60d90000 00007ffb
60f03000 C:\WINDOWS\System32\MSCTF.dll
ModLoad:00007ffb5ed80000 00007ffb
5eff3000C:\WINDOWS\System32\KERNELBASE.dll ModLoad:00007ffb
60610000
00007ffb
606d2000 C:\WINDOWS\System32\OLEAUT32.dll ModLoad:
00007ffb60f10000 00007ffb
60f3d000C:\WINDOWS\System32\IMM32.DLL
*************路径验证摘要*************响应时间(毫秒)位置延迟srv*符号搜索路径为:srv*可执行搜索路径为:ModLoad: 00007ff7
169f0000 00007ff7
16a8f000 conhost.exe ModLoad:
00007ffb613400000 00007ffb
62780000 C:\WINDOWS\System32\shell32.dll
ModLoad:00007ffb5cd80000 00007ffb
5cda9000C:\WINDOWS\system32\dwmapi.dll ModLoad:00007ffb
62880000
00007ffb
62a61000 ntdll.dll ModLoad:00007ffb5fcc0000
00007ffb
5fd09000 C:\WINDOWS\System32\cfgmgr32.dll ModLoad:
00007ffb5F53000007FFB
5fc3d000C:\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
61191000C:\WINDOWS\System32\shlwapi.dll ModLoad:00007ffb
60990000
00007ffb
60a42000 C:\WINDOWS\System32\KERNEL32.DLL ModLoad:
00007ffb5ec30000 00007ffb
5ec41000C:\WINDOWS\System32\kernel.appcore.dll ModLoad:00007ffb
5ed80000
00007ffb
5eff3000 C:\WINDOWS\System32\KERNELBASE.dll ModLoad:
00007ffb5ec10000 00007ffb
5ec2f000 C:\WINDOWS\System32\profapi.dll
ModLoad:00007ffb5ebc0000 00007ffb
5ec0c000C:\WINDOWS\System32\powrpof.dll ModLoad:00007ffb
5ebb0000
00007ffb
5ebba000 C:\WINDOWS\System32\FLTLIB.DLL ModLoad:
00007ffb5F49000 00007ffb
5f52f000C:\WINDOWS\System32\msvcp_win.dll ModLoad:00007ffb
5f1a0000
00007ffb
5f29a000 C:\WINDOWS\System32\ucrtbase.dll ModLoad:
00007ffb606e0000 00007ffb
60789000 C:\WINDOWS\System32\shcore.dll
ModLoad:00007ffb4e290000 00007ffb
4e4f9000C:\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);
}