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

时间:2013-12-29 06:53:02

标签: c# wpf usb libusb libusbdotnet

我在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电源,它所做的只是打开和关闭几个继电器......

我也尝试过一次又一次地使用大量连续命令对设备进行泛滥,包括垃圾连续命令,但它仍能正常工作,并且只是稍稍崩溃才能正常运行。

对任何建议或想法持开放态度,谢谢!

编辑: 经过多次尝试后,我仍然无法确定问题的根本原因,但我设法达到了我的代码正常工作的程度,并且能够使用重新连接函数从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 个答案:

答案 0 :(得分:1)

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

我在这里写这篇文章是因为它不能作为评论阅读。(代码)

我刚刚注释掉了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(); }

我无法摆脱这个恼人的错误, 我可以发送第一条消息,但即使我重新连接到设备也无法治愈:(

EndPoint 0x0x1是我的终端端点0x81是设备但是在收到此错误后????我不明白为什么没有usb的托管lib。

         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:

答案 1 :(得分:1)

我也遇到了错误:

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

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