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:
Другие вопросы по тегам