Редактировать: Этот вопрос развивался с течением времени.Основной вопрос был о том, как подключиться к устройству USB и читать / записывать на него / с него в Windows.В конце концов я ответил на вопрос с помощью @ benvoigt.
Я написал библиотеку Hid, которая записывает и читает с / на USB-устройства Hid.Это работает хорошо.Однако устройство, к которому я подключаюсь, переключилось с Hid на USB-порт.Код Hid не работает при подключении к другому типу устройства.Теперь моя цель - подключиться к интерфейсу USB (в отличие от интерфейса Hid) и выполнять чтение / запись на него / с него.
На всех платформах, имеющих доступ к USB, мы должны запросить интерфейсы, которые существуют дляUSB-устройство, а затем «претендовать» на интерфейс для чтения и записи.Вот некоторый код из образца LibUsbDotNet (LibUsb - это работающая библиотека C USB, и LibUsbDotNet оборачивает ее) https://github.com/LibUsbDotNet/LibUsbDotNet/blob/master/src/Examples/Read.Write/ReadWrite.cs.
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 => d.ProductId == ProductId && 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);
}
}
У меня такое ощущение, что LibUsb достигает открытия интерфейсов / конечных точек в C, какthis (https://github.com/libusb/libusb/blob/c6f3866414e8deeee19e8a9f10f20bde9cb408d3/libusb/os/windows_winusb.c#L2199). Здесь он вызывает Initialize: https://github.com/libusb/libusb/blob/c6f3866414e8deeee19e8a9f10f20bde9cb408d3/libusb/os/windows_winusb.c#L2225, где мой код не работает.
Небольшой фрагмент информации о том, что это определенно устройство WinUSB.Я вижу это здесь:
На основании комментариев других людей и примера кода, я вижу, что мне нужно использовать winusb.dll.в состоянии вызвать CreateFile, чтобы получить дескриптор от устройства. В соответствии с другим примером кода, который я видел, следующим шагом является вызов WinUsb_Initialize. Однако, когда я вызываю это, я получаю код ошибки 8 (ERROR_NOT_ENOUGH_MEMORY). Есть некоторыеинформация здесь https://docs.microsoft.com/en-us/windows/desktop/api/winusb/nf-winusb-winusb_initialize. Но я не совсем понимаю, что он просит меня сделать. Это мой код:
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();
}
Вы можете клонировать ветку этого репо здесь: https://github.com/MelbourneDeveloper/Device.Net/tree/WindowsUsbDevice.Просто запустите проект 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, похоже, не нравится.Я попробовал эту библиотеку: https://github.com/madwizard-thomas/winusbnet, и она также не работает на тот же вызов с тем же кодом ошибки.Строка, в которой происходит сбой и появляется код ошибки 8, находится здесь: https://github.com/madwizard-thomas/winusbnet/blob/8f62d751a99be1e31d34b91115715d60aeff2dfc/WinUSBNet/API/WinUSBDevice.cs#L225
Что не так с моим кодом здесь?Что мне нужно сделать, чтобы выделить память для вызова WinUsb_Initialize?
Как использовать 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 60f40000 00007ffb
610d0000 C: \ WINDOWS \ System32 \ user32.dll ModLoad: 00007ffb 5ed00000 00007ffb
5ed20000
C: \ WINDOWS \ System32 \ win32u.dll Загрузка модуля: 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) ReturnHr (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\ MSCTF.dll ModLoad: 00007ffb 5ed80000 00007ffb
5eff3000
C: \ WINDOWS \ System32 \ KERNELBASE.dll ModLoad: 00007ffb 60610000
00007ffb
606d2000 C: \ WINDOWS \ System32 \ OLEAUT32.dll, загрузка модуля: 00007ffb 60f10000 00007ffb
60f: 60f * 60f * 60ff\ WINDOWS \ System32 \ IMM32.DLL
************* Сводка проверки пути ************** Время отклика (мс) Местоположение отложено
srv * Путь поиска символа:srv * Путь поиска исполняемого файла: ModLoad: 00007ff7 169f0000 00007ff7
16a8f000 conhost.exe ModLoad: 00007ffb 61340000 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 5f530000 00007ffb
5fc3d000
C: \ WINDOWS \ Systemstorage.dll onecore \ windows \ core \ console \ open \ src \ renderer \ gdi \ invalidate.cpp (121) \ conhost.exe! 00007FF7169FE2AF: (абонент: 00007FF7169FF414) ReturnHr (2) tid (4230) 80070578 Недопустимый дескриптор окна.ModLoad: 00007ffb 61140000 00007ffb
61191000
C: \ WINDOWS \ System32 \ shlwapi.dll ModLoad: 00007ffb 60990000
00007ffb
60a42000 C: \ WINDOWS \ System32 \ KERNEL32.DLL Загрузка модуля: 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 Модулевая загрузка: 00007ffb 5ebc0000 00007ffb
1090 *
C: \ WINDOWS \ System32 \ powrprof.dll ModLoad: 00007ffb 5ebb0000
00007ffb
5ebba000 C: \ WINDOWS \ System32 \ FLTLIB.DLL ModLoad: 00007ffb 5f490000 00007ffb
5f52f000
C: \ WINDOWS \ System32 \ msvcp_win.dllModLoad: 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: WINSS\ amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.17134.472_none_fb3f9af53068156d \ comctl32.DLL ModLoad: 00007ffb 5ca60000 00007ffb
5caf8000
C: \ WINDOWS \ system32 \ u64OW * system32: каталог-системная папка * * *msvcrt.dll ModLoad: 00007ffb 601e0000 00007ffb
60304000 C: \ WINDOWS \ System32 \ RPCRT4.dll ModLoad: 00007ffb 60a60000 00007ffb
60d82000
C: \ WINDOWS \ System32 \ combase.dll ModLoad: 00007ffb 5fc40000
00007ffb
5fcba000 C: \ WINDOWS \ System32 \ bcryptPrimitives.dll Мод загрузки:00007ffb 627a0000 00007ffb
62841000 C: \ WINDOWS \ System32 \ advapi32.dll ModLoad: 00007ffb 610d0000 00007ffb
6112b000
C: \ WINDOWS \ System32 \ sechost.dll ModLoad: 00007ffb 57b30000
00007ffb
57bc6000 C: \ WINDOWS \ System32 \ TextInput.dll (3d80.256c): исключение инструкции разрыва - код 80000003 (первый шанс) ntdll! LdrpDoDebuggerBreak + 0x30: 00007ffb`6294c93c cc
int 3