C# LibUSBDotNet:使用USB设备一段时间后出现奇怪的错误

C# LibUSBDotNet:使用USB设备一段时间后出现奇怪的错误,c#,wpf,usb,libusb,libusbdotnet,C#,Wpf,Usb,Libusb,Libusbdotnet,我正在WPF应用程序中使用LibUSBDotNet库,该应用程序与一个简单的USB设备通信。我只将3个字节作为一个命令发送到设备,没有预期的响应,我的代码就像一个符咒: MyUsbFinder = new UsbDeviceFinder(vid, pid); MyUsbDevice = UsbDevice.OpenUsbDevice(MyUsbFinder); wholeUsbDevice = MyUsbDevice as IUsbDevice; if (!ReferenceEquals(who

我正在WPF应用程序中使用LibUSBDotNet库,该应用程序与一个简单的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.
通常,我需要在设备/应用程序重新启动几次后,它才能重新开始工作,然后又像魔咒一样工作了几个小时后,它才会再次出现。。。到目前为止,我也无法在测试环境中复制崩溃

我做了很多研究,试图找到一个与我类似的问题/解决方案,但没有成功。我留下的唯一建议是,在某一点上,设备没有足够的电源,它会进入这种错误模式,但即使这样似乎也不太可能,因为它有一个单独的12V电源,它所做的只是打开和关闭几个继电器

我还尝试过用一个接一个的大量连续命令(包括垃圾命令)淹没设备,但它仍然可以正常工作和行为,只会在稍后崩溃

欢迎任何建议或想法,谢谢

编辑: 在多次尝试之后,我仍然无法确定问题的根本原因,但我成功地找到了代码工作的地方,并且能够使用重新连接功能从重叠结果错误中恢复,该功能尝试在设备开始出现故障时重置设备。我在下面发布了一些代码,希望有人能够缩小问题范围,找出错误的原因

初始化过程中的一些代码:

        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的组合减少了我看到重叠结果错误的次数,无论何时,从我的日志判断,我都能够立即恢复并将命令重新发送到设备。正如我上面所说的,这是一个解决问题的方法,因为我仍然时不时地得到错误,我仍然不知道为什么,但至少我能够在这一点上继续使用设备。如果有人有更多的见解,我很想了解更多关于这个问题的信息。谢谢,我希望这对你有帮助

不是答案! (这只是另一个问题的解决方法。它在关闭应用程序时修复了给定的错误)

我在这里写这篇文章是因为它不能作为注释阅读

我刚刚注释掉了dispose上的代码,如下所示

    #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(); }

我还遇到了错误:

Win32Error:PipeTransferSubmit Ep 0x02
87:The parameter is incorrect.

我发现我使用了错误的WriteEndpointId。请参阅。

我也有同样的问题。你找到解决办法了吗?我认为在调用内核方法或主机设备等待一些我没有及时发送的数据时,可能是变量类型不兼容。您好,您使用的是哪种设备?只是想知道它是否和我的一样。在代码中经过多次测试和调整后,我现在已经让设备在生产中运行了,几乎没有出现错误,几天都没有出现问题。它仍然会时不时地给出重叠的结果,但我成功地编写了代码,这样它就可以在不需要人工交互的情况下恢复。我将在周末查看代码,并在这里发布更新和我的更改。希望这会有帮助!嗨,这是WelchAllyn的Propaq LT,一种医疗病人护理设备。正如你在得到OverlappedResult错误后对问题所说的那样,我无法得到任何进一步有意义的回答。它研究了重叠结果误差。如果您能在这里分享您的解决方案,那就太好了。如果你想和我聊天并使用skype,davut06是我的skype。祝你好运!你好,我的是完全不同的-简单的继电器控制器,但问题是相同的。我将在上面发布一些代码,向您展示我如何解决这个问题。我还没有找到问题的根本原因,但至少我的代码可以正常工作,而且我几乎总能从重叠的结果中恢复过来,继续工作,而无需使用重新连接功能进行人机交互,并在设备出现错误时尝试重设设备。我将在代码中添加一些注释来解释我使用了什么以及为什么使用。如果您有任何问题,请告诉我,我们可以在skype上聊天。祝您好运!我认为这个项目不是托管代码。它依赖于一些内核调用,在一些多线程作业上可能会失败。据我记忆所及(现在这是一个老问题),我曾尝试使用不同的WriteEndPointId,但偶尔会在所有这些点上出错。您确定更改WriteEndpointId一段时间后不会遇到此问题吗?我曾经确定正确的WriteEndpointId。
Win32Error:PipeTransferSubmit Ep 0x02
87:The parameter is incorrect.