LibUSBDotNet: Странные ошибки после некоторой работы с USB-устройством
Я использую библиотеку LibUSBDotNet в приложении WPF, которое взаимодействует с простым USB-устройством. Я отправляю на устройство только 3 байта в качестве команды, ответа от него не ожидается, и мой код работает как чудо:
MyUsbFinder = new UsbDeviceFinder(vid, pid);
MyUsbDevice = UsbDevice.OpenUsbDevice(MyUsbFinder);
wholeUsbDevice = MyUsbDevice as IUsbDevice;
if (!ReferenceEquals(wholeUsbDevice, null))
{
wholeUsbDevice.SetConfiguration(1);
wholeUsbDevice.ClaimInterface(0);
}
writer = MyUsbDevice.OpenEndpointWriter(WriteEndpointID.Ep01);
А затем процесс записи на устройство:
byte[] update = { 0x21, some_code_generated_byte, some_code_generated_byte };
int bytesWritten;
if (MyUsbDevice != null)
{
ec = writer.Write(update, 2000, out bytesWritten);
}
Я относительно новичок в работе с USB, но я дошел до этого, и все это работает. Однако через некоторое время, время от времени, при попытке перезаписи на устройство я получаю одну из следующих двух ошибок:
Win32Error:GetOverlappedResult Ep 0x01
31:The parameter is incorrect.
Win32Error:PipeTransferSubmit Ep 0x01
87:The parameter is incorrect.
Часто мне нужно несколько раз перезапускать устройство / приложение, прежде чем оно снова начинает работать, а затем еще несколько часов работает как чудо, прежде чем это произойдет снова... Я до сих пор не смог воспроизвести сбой в тестовой среде,
Я провел много исследований, пытаясь найти проблему / решение, подобное моему, но безуспешно. Единственное предложение, которое я оставил, заключается в том, что в какой-то момент устройству не хватает энергии, и оно переходит в этот режим ошибки, но даже это кажется маловероятным, поскольку у него есть отдельный источник питания 12 В и все, что он делает, - это включает и выключает несколько реле...
Я также пытался заполнить устройство множеством последовательных команд, в том числе мусорных, но оно все еще работает и работает правильно только после сбоя.
Открыты для любых предложений или идей, спасибо!
РЕДАКТИРОВАТЬ: После многих попыток я все еще не могу определить основную причину проблемы, но мне удалось добраться до точки, где мой код работает и может восстановиться после ошибки OverlappedResult, используя функции переподключения, которые пытаются перезагрузить устройство как только он начинает терпеть неудачу. Ниже выложен код, и, надеюсь, кто-то сможет сузить проблему и определить причину ошибки.
Некоторый код во время инициализации:
UsbDeviceFinder MyUsbFinder;
UsbDevice MyUsbDevice;
IUsbDevice wholeUsbDevice;
MyUsbFinder = new UsbDeviceFinder(vid, pid);
MyUsbDevice = UsbDevice.OpenUsbDevice(MyUsbFinder);
wholeUsbDevice = MyUsbDevice as IUsbDevice;
if (!ReferenceEquals(wholeUsbDevice, null))
{
// This is a "whole" USB device. Before it can be used,
// the desired configuration and interface must be selected.
// I think those do make some difference...
// Select config #1
wholeUsbDevice.SetConfiguration(1);
// Claim interface #0.
wholeUsbDevice.ClaimInterface(0);
}
writer = MyUsbDevice.OpenEndpointWriter(WriteEndpointID.Ep01);
Далее я пытаюсь отправить некоторую информацию на устройство. Это где ошибка в конечном итоге всплывает, и я ловлю ее как исключение в простом блоке try / catch:
ErrorCode ec = ErrorCode.None;
if (MyUsbDevice != null)
{
ec = writer.Write(update, 2000, out bytesWritten);
if (ec != ErrorCode.None)
{
//now try to reconnect to the device, dispose writer first
writer.Dispose(); // I think this also helps to reestablish the connection and get rid of the error
if (this.reconnect())
{
//reconnected, try to write to the device again
ec = writer.Write(update, 2000, out bytesWritten);
if (ec != ErrorCode.None)
{
//log the error
}
}
}
}
else //there's no connection to the device, try to reconnect and update again
{
//now try to reconnect to the device, dispose writer first
//writer.Dispose();
if (this.reconnect())
updateRelayController();
}
Там "update" - это байтовый массив, который я отправляю на свое устройство с соответствующими командами, а updateRelayController - это функция, которая имеет фрагмент кода выше, записывающий команды на USB-устройство. И наконец, вот моя функция reconnect(), которая позволяет восстановить соединение с устройством в 99% случаев без необходимости перезапуска устройства вручную, подключения / отключения USB-кабелей и т. Д.
public bool reconnect()
{
//clear the info so far
if (MyUsbDevice != null)
{
writer.Dispose();
wholeUsbDevice.ReleaseInterface(0);
wholeUsbDevice.Close();
MyUsbDevice.Close();
UsbDevice.Exit();
}
//now start over
MyUsbFinder = new UsbDeviceFinder(vid, pid);
MyUsbDevice = UsbDevice.OpenUsbDevice(MyUsbFinder);
// If the device is open and ready
if (MyUsbDevice == null)
{
//log the error
return false;
}
else
{
wholeUsbDevice = MyUsbDevice as IUsbDevice;
if (!ReferenceEquals(wholeUsbDevice, null))
{
// Select config #1
wholeUsbDevice.SetConfiguration(1);
// Claim interface #0.
wholeUsbDevice.ClaimInterface(0);
}
writer = MyUsbDevice.OpenEndpointWriter(WriteEndpointID.Ep01);
return true;
}
}
Это в значительной степени так далеко. Комбинация SetConfiguration/ClaimInterface/Dispose уменьшает время, когда я вижу ошибку OverlappedResult, и всякий раз, когда это происходит, судя по моим журналам, я могу сразу же восстановить данные и отправить команду на устройство. Как я уже говорил выше, это обходной путь к этой проблеме, так как время от времени я все еще получаю сообщение об ошибке, и я до сих пор не знаю, почему, но, по крайней мере, я могу продолжать работать с устройством на этом этапе. Хотелось бы узнать больше по этому вопросу, если у кого-то есть больше идей. Спасибо, и я надеюсь, что это поможет!
2 ответа
Я также столкнулся с ошибкой:
Win32Error:PipeTransferSubmit Ep 0x02
87:The parameter is incorrect.
Я обнаружил, что использовал неправильный WriteEndpointId. Обратитесь к документации API.
НЕ ответ! (Это всего лишь обходной путь для другой проблемы. Он исправляет данную ошибку при закрытии приложения)
Я пишу это здесь, потому что это не будет читаемым как комментарий.(Для кода)
Я только что закомментировал код утилизации, как показано ниже.
#region IDisposable Members
/// <summary>
/// Cancels any pending transfer and frees resources.
/// </summary>
public virtual void Dispose()
{
if (!IsCancelled) Cancel();
//I just commented here.
//int dummy;
//if (!mHasWaitBeenCalled) Wait(out dummy);
if (mPinnedHandle != null) mPinnedHandle.Dispose();
mPinnedHandle = null;
}
#endregion
~UsbTransfer() { Dispose(); }
и я не смог избавиться от этой надоедливой ошибки, я могу отправить первое сообщение, но даже при успешном переподключении к устройству лечения не существует:(
Конечная точка 0x0x1 - это моя конечная точка 0x81 - это устройство, но после получения этой ошибки???? Я не понимаю, почему нет управляемой библиотеки для USB.
05 FA 28 81 02 00 08 94 32 Win32Error:GetOverlappedResult Ep 0x81
31:
Win32Error:PipeTransferSubmit Ep 0x01
22:
Win32Error:DeviceIoControl code 00222058 failed: LibUsbDriverIO
22:
Win32Error:PipeTransferSubmit Ep 0x01
22:
Win32Error:DeviceIoControl code 00222058 failed: LibUsbDriverIO
22:
Win32Error:PipeTransferSubmit Ep 0x01
22:
Win32Error:DeviceIoControl code 00222058 failed: LibUsbDriverIO
22: