-1

一括転送を使用して PIC4550 と通信するために C# で WinUSB を使用していますが、奇妙な問題が発生しています。

現在のコードは正しく動作しますが、コードが乱雑になっているため、削除したいデバッグ Console.Write() 行がまだいくつか含まれています。それらを削除し、デバッガーでコードをステップ実行することも正しく機能します。

残念ながら、デバッグ行を削除すると、コードが機能しなくなります。「結果」バイト配列は null として返され、null 参照例外がスローされます。

何が起きてる?

    public static ulong GetBulkData(Device d, ref byte[] result)
    {

        byte _inPipe = 0x81;
        ulong bufferlength = 64;


        NativeOverlapped gOverlapped = new NativeOverlapped();
        GCHandle pinnedOverlap = new GCHandle();

        gOverlapped.InternalLow = IntPtr.Zero;
        gOverlapped.InternalHigh = IntPtr.Zero;
        gOverlapped.OffsetLow = 0;
        gOverlapped.OffsetHigh = 0;
        gOverlapped.EventHandle = Win32.CreateEvent(IntPtr.Zero, true, false, IntPtr.Zero);
        pinnedOverlap = GCHandle.Alloc(gOverlapped, GCHandleType.Pinned);



        ulong lengthtransferred = 0;
        Array.Clear(result, 0, result.Length);
        GCHandle pinnedBuffer = GCHandle.Alloc(result, GCHandleType.Pinned);
        Win32.WinUsb_ReadPipe(d._handle, _inPipe, pinnedBuffer.AddrOfPinnedObject(), bufferlength, ref lengthtransferred, pinnedOverlap.AddrOfPinnedObject());
        int hr = Win32.GetLastError();

        bool bResult = (hr == 0);
        pinnedOverlap.Free();
        if (bResult)
        {
            foreach (byte b in result)
                Console.Write(" " + b);
            return lengthtransferred;
        }
        else
        {
            Console.WriteLine("USB Error Code " + hr);
            uint pLength = 0;
            // Deal with the error code
            switch (hr)
            {
                case Win32.ERROR_IO_PENDING:
                    // Asynchronous I/O is still in progress... wait for it to complete
                    int evt = Win32.WaitForSingleObject(gOverlapped.EventHandle, 10);
                    switch (evt)
                    {
                        case Win32.WAIT_OBJECT_0:

                            // I/O completed.
                            // Check on the results of the asynchronous read and update the nBytesRead
                            bResult = Win32.WinUsb_GetOverlappedResult(d._handle, pinnedBuffer.AddrOfPinnedObject(), out pLength, true);
                            if (bResult)
                            {

                                // Success
                                Console.WriteLine("USB overlap received");
                            }

                            break;

                        case Win32.WAIT_TIMEOUT:
                        default:

                            // I/O error or timeout.  Cancel outstanding I/O.
                            Win32.CancelIo(d._handle);
                            break;
                    }
                    break;

            }
            pinnedBuffer.Free();
            return pLength;
        }

    }
4

2 に答える 2

0

後でこれに出くわした人のための解決策。タイミングの問題だったようです。転送が成功したため、bResult は true を返していましたが、実際には、GCHandle で参照していたバイト配列に情報が反映されていませんでした。

解決策は、重複したハンドルをヌル ポインターに変更することにより、Winusb に同期的に送信させることでした。WinUsb_ReadPipe 行は次のように変更されました。

    Win32.WinUsb_ReadPipe(d._handle, _inPipe, pinnedBuffer.AddrOfPinnedObject(), bufferlength, ref lengthtransferred, IntPtr.Zero);

そして、それは完璧に機能します。

この記事にインスパイアされた

于 2016-01-07T00:45:38.953 に答える
0

次の行で行うことができます:

foreach (byte b in result)
            Console.Write(" " + b);
        return lengthtransferred;

現在、foreach でコンソールに書き込むだけです。foreach ループも削除する必要がある場合があります。

于 2015-12-23T22:24:58.657 に答える