我在与简单 USB 设备通信的 WPF 应用程序中使用 LibUSBDotNet 库。我只向设备发送 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.
通常我需要重新启动设备/应用程序几次,然后它才能再次开始工作,然后它又像魅力一样工作了几个小时,然后再次发生......到目前为止,我还无法在测试环境中复制崩溃.
我做了很多研究,试图找到与我类似的问题/解决方案,但没有成功。我留下的唯一建议是,在某些时候设备没有足够的电源,它会进入这种错误模式,但即使这样似乎也不太可能,因为它有一个单独的 12V 电源,它所做的只是打开和关闭几个继电器...
我也尝试过用很多连续的命令一个接一个地淹没设备,包括垃圾命令,但它仍然可以工作并且行为正常,只是稍后会崩溃。
欢迎任何建议或想法,谢谢!
编辑:经过多次尝试,我仍然无法确定问题的根本原因,但我设法达到了我的代码正在工作的地步,并且能够使用尝试重置设备的重新连接函数从 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();
}
上面的“更新”是一个字节数组,我用适当的命令发送到我的设备,而 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 错误的时间,无论何时发生这种情况,从我的日志来看,我都能立即恢复并将命令重新发送到设备。正如我上面所说,这是解决问题的方法,因为我仍然不时遇到错误,我仍然不知道为什么,但至少我现在能够继续使用该设备。如果有人有更多见解,我很想了解更多关于这个问题的信息。谢谢,我希望这会有所帮助!