Read Isochronous (Async Transfer Queue)

LibUsbDotNet

LibUsbDotNet 2.2.8 Read Isochronous (Async Transfer Queue)
LibUsbDotNet on SourceForge

To use this example with the benchmark firmware, ensure IS_BENCHMARK_DEVICE is defined at the top of the source file.

Read Isochronous (Async Transfer Queue): Console Application Description
  1. Opens a USB device by vendor and product id.

  2. Opens a UsbEndpointReader class for reading.

  3. Creates a UsbTransferQueue class.

  4. Submits transfers until TRANFER_MAX_OUTSTANDING_IO is reached then waits for the oldest transfer to complete.

  5. Displays information on the completed transfer and repeats the above step until TRANSFER_COUNT is reached.

Example
CopyC#
#define IS_BENCHMARK_DEVICE

using System;
using LibUsbDotNet;
using LibUsbDotNet.Info;
using LibUsbDotNet.Main;

namespace Examples
{
    internal class ReadIsochronous
    {

        #region SET YOUR USB Vendor and Product ID!

        public static UsbDeviceFinder MyUsbFinder = new UsbDeviceFinder(1234, 1);

        #endregion

        /// <summary>Use the first read endpoint</summary>
        public static readonly byte TRANFER_ENDPOINT = UsbConstants.ENDPOINT_DIR_MASK;

        /// <summary>Number of transfers to sumbit before waiting begins</summary>
        public static readonly int TRANFER_MAX_OUTSTANDING_IO = 3;

        /// <summary>Number of transfers before terminating the test</summary>
        public static readonly int TRANSFER_COUNT = 30;

        /// <summary>Size of each transfer</summary>
        public static int TRANFER_SIZE = 4096;

        private static DateTime mStartTime = DateTime.MinValue;
        private static double mTotalBytes = 0.0;
        private static int mTransferCount = 0;
        public static UsbDevice MyUsbDevice;

        public static void Main(string[] args)
        {
            ErrorCode ec = ErrorCode.None;

            try
            {
                // Find and open the usb device.
                UsbRegDeviceList regList = UsbDevice.AllDevices.FindAll(MyUsbFinder);
                if (regList.Count == 0) throw new Exception("Device Not Found.");

                UsbInterfaceInfo usbInterfaceInfo = null;
                UsbEndpointInfo usbEndpointInfo = null;

                // Look through all conected devices with this vid and pid until
                // one is found that has and and endpoint that matches TRANFER_ENDPOINT.
                // 
                foreach (UsbRegistry regDevice in regList)
                {
                    if (regDevice.Open(out MyUsbDevice))
                    {
                        if (MyUsbDevice.Configs.Count > 0)
                        {
                            // if TRANFER_ENDPOINT is 0x80 or 0x00, LookupEndpointInfo will return the 
                            // first read or write (respectively).
                            if (UsbEndpointBase.LookupEndpointInfo(MyUsbDevice.Configs[0],TRANFER_ENDPOINT, 
                                out usbInterfaceInfo, out usbEndpointInfo))
                                break;

                            MyUsbDevice.Close();
                            MyUsbDevice = null;
                        }
                    }
                }

                // If the device is open and ready
                if (MyUsbDevice == null) throw new Exception("Device Not Found.");

                // If this is a "whole" usb device (libusb-win32, linux libusb-1.0)
                // it exposes an IUsbDevice interface. If not (WinUSB) the 
                // 'wholeUsbDevice' variable will be null indicating this is 
                // an interface of a device; it does not require or support 
                // configuration and interface selection.
                IUsbDevice 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.

                    // Select config #1
                    wholeUsbDevice.SetConfiguration(1);

                    // Claim interface #0.
                    wholeUsbDevice.ClaimInterface(usbInterfaceInfo.Descriptor.InterfaceID);
                }

                // open read endpoint.
                UsbEndpointReader reader = MyUsbDevice.OpenEndpointReader(
                    (ReadEndpointID) usbEndpointInfo.Descriptor.EndpointID,
                    0,
                    (EndpointType) (usbEndpointInfo.Descriptor.Attributes & 0x3));

                if (ReferenceEquals(reader, null))
                {
                    throw new Exception("Failed locating read endpoint.");
                }

                reader.Reset();

                // The benchmark device firmware works with this example but it must be put into PC read mode.
#if IS_BENCHMARK_DEVICE
                int transferred;
                byte[] ctrlData=new byte[1];
                UsbSetupPacket setTestTypePacket = 
                    new UsbSetupPacket((byte) (UsbCtrlFlags.Direction_In | UsbCtrlFlags.Recipient_Device | UsbCtrlFlags.RequestType_Vendor),
                        0x0E,0x01,usbInterfaceInfo.Descriptor.InterfaceID,1);
                MyUsbDevice.ControlTransfer(ref setTestTypePacket,ctrlData, 1, out transferred);
#endif
                TRANFER_SIZE -= (TRANFER_SIZE%usbEndpointInfo.Descriptor.MaxPacketSize);

                UsbTransferQueue transferQeue = new UsbTransferQueue(reader,
                                                                     TRANFER_MAX_OUTSTANDING_IO,
                                                                     TRANFER_SIZE,
                                                                     5000,
                                                                     usbEndpointInfo.Descriptor.MaxPacketSize);

                do
                {
                    UsbTransferQueue.Handle handle;

                    // Begin submitting transfers until TRANFER_MAX_OUTSTANDING_IO has benn reached.
                    // then wait for the oldest outstanding transfer to complete.
                    // 
                    ec = transferQeue.Transfer(out handle);
                    if (ec != ErrorCode.Success)
                        throw new Exception("Failed getting async result");

                    // Show some information on the completed transfer.
                    showTransfer(handle, mTransferCount);
                } while (mTransferCount++ < TRANSFER_COUNT);

                // Cancels any oustanding transfers and free's the transfer queue handles.
                // NOTE: A transfer queue can be reused after it's freed.
                transferQeue.Free();

                Console.WriteLine("\r\nDone!\r\n");
            }
            catch (Exception ex)
            {
                Console.WriteLine();
                Console.WriteLine((ec != ErrorCode.None ? ec + ":" : String.Empty) + ex.Message);
            }
            finally
            {
                if (MyUsbDevice != null)
                {
                    if (MyUsbDevice.IsOpen)
                    {
                        // If this is a "whole" usb device (libusb-win32, linux libusb-1.0)
                        // it exposes an IUsbDevice interface. If not (WinUSB) the 
                        // 'wholeUsbDevice' variable will be null indicating this is 
                        // an interface of a device; it does not require or support 
                        // configuration and interface selection.
                        IUsbDevice wholeUsbDevice = MyUsbDevice as IUsbDevice;
                        if (!ReferenceEquals(wholeUsbDevice, null))
                        {
                            // Release interface #0.
                            wholeUsbDevice.ReleaseInterface(0);
                        }

                        MyUsbDevice.Close();
                    }
                    MyUsbDevice = null;
                }

                // Wait for user input..
                Console.ReadKey();

                // Free usb resources
                UsbDevice.Exit();
            }
        }

        private static void showTransfer(UsbTransferQueue.Handle handle, int transferIndex)
        {
            if (mStartTime == DateTime.MinValue)
            {
                mStartTime = DateTime.Now;
                Console.WriteLine("Synchronizing..");
                return;
            }

            mTotalBytes += handle.Transferred;
            double bytesSec = mTotalBytes/(DateTime.Now - mStartTime).TotalSeconds;

            Console.WriteLine("#{0} complete. {1} bytes/sec ({2} bytes) Data[1]={3:X2}",
                              transferIndex,
                              Math.Round(bytesSec, 2),
                              handle.Transferred,
                              handle.Data[1]);
        }
    }
}
Example
CopyVB.NET
#Define IS_BENCHMARK_DEVICE

Imports System
Imports LibUsbDotNet
Imports LibUsbDotNet.Info
Imports LibUsbDotNet.Main

Namespace Examples
    Friend Class ReadIsochronous

        #Region "SET YOUR USB Vendor and Product ID!"

        Public Shared MyUsbFinder As New UsbDeviceFinder(1234, 1)

        #End Region

        ''' <summary>Use the first read endpoint</summary>
        Public Shared ReadOnly TRANFER_ENDPOINT As Byte = UsbConstants.ENDPOINT_DIR_MASK

        ''' <summary>Number of transfers to sumbit before waiting begins</summary>
        Public Shared ReadOnly TRANFER_MAX_OUTSTANDING_IO As Integer = 3

        ''' <summary>Number of transfers before terminating the test</summary>
        Public Shared ReadOnly TRANSFER_COUNT As Integer = 30

        ''' <summary>Size of each transfer</summary>
        Public Shared TRANFER_SIZE As Integer = 4096

        Private Shared mStartTime As DateTime = DateTime.MinValue
        Private Shared mTotalBytes As Double = 0
        Private Shared mTransferCount As Integer = 0
        Public Shared MyUsbDevice As UsbDevice

        Public Shared Sub Main(args As String())
            Dim ec As ErrorCode = ErrorCode.None

            Try
                ' Find and open the usb device.
                Dim regList As UsbRegDeviceList = UsbDevice.AllDevices.FindAll(MyUsbFinder)
                If regList.Count = 0 Then
                    Throw New Exception("Device Not Found.")
                End If

                Dim usbInterfaceInfo As UsbInterfaceInfo = Nothing
                Dim usbEndpointInfo As UsbEndpointInfo = Nothing

                ' Look through all conected devices with this vid and pid until
                ' one is found that has and and endpoint that matches TRANFER_ENDPOINT.
                '
                For Each regDevice As UsbRegistry In regList
                    If regDevice.Open(MyUsbDevice) Then
                        If MyUsbDevice.Configs.Count > 0 Then
                            ' if TRANFER_ENDPOINT is 0x80 or 0x00, LookupEndpointInfo will return the 
                            ' first read or write (respectively).
                            If UsbEndpointBase.LookupEndpointInfo(MyUsbDevice.Configs(0), TRANFER_ENDPOINT, usbInterfaceInfo, usbEndpointInfo) Then
                                Exit For
                            End If

                            MyUsbDevice.Close()
                            MyUsbDevice = Nothing
                        End If
                    End If
                Next

                ' If the device is open and ready
                If MyUsbDevice Is Nothing Then
                    Throw New Exception("Device Not Found.")
                End If

                ' If this is a "whole" usb device (libusb-win32, linux libusb-1.0)
                ' it exposes an IUsbDevice interface. If not (WinUSB) the 
                ' 'wholeUsbDevice' variable will be null indicating this is 
                ' an interface of a device; it does not require or support 
                ' configuration and interface selection.
                Dim wholeUsbDevice As IUsbDevice = TryCast(MyUsbDevice, IUsbDevice)
                If Not ReferenceEquals(wholeUsbDevice, Nothing) Then
                    ' This is a "whole" USB device. Before it can be used, 
                    ' the desired configuration and interface must be selected.


                    ' Select config #1
                    wholeUsbDevice.SetConfiguration(1)

                    ' Claim interface #0.
                    wholeUsbDevice.ClaimInterface(usbInterfaceInfo.Descriptor.InterfaceID)
                End If

                ' open read endpoint.
                Dim reader As UsbEndpointReader = MyUsbDevice.OpenEndpointReader(DirectCast(usbEndpointInfo.Descriptor.EndpointID, ReadEndpointID), 0, DirectCast((usbEndpointInfo.Descriptor.Attributes And &H3), EndpointType))

                If ReferenceEquals(reader, Nothing) Then
                    Throw New Exception("Failed locating read endpoint.")
                End If

                reader.Reset()

                ' The benchmark device firmware works with this example but it must be put into PC read mode.
                #If IS_BENCHMARK_DEVICE Then
                Dim transferred As Integer
                Dim ctrlData As Byte() = New Byte(0) {}
                Dim setTestTypePacket As New UsbSetupPacket(CByte((UsbCtrlFlags.Direction_In Or UsbCtrlFlags.Recipient_Device Or UsbCtrlFlags.RequestType_Vendor)), &He, &H1, usbInterfaceInfo.Descriptor.InterfaceID, 1)
                MyUsbDevice.ControlTransfer(setTestTypePacket, ctrlData, 1, transferred)
                #End If
                TRANFER_SIZE -= (TRANFER_SIZE Mod usbEndpointInfo.Descriptor.MaxPacketSize)

                Dim transferQeue As New UsbTransferQueue(reader, TRANFER_MAX_OUTSTANDING_IO, TRANFER_SIZE, 5000, usbEndpointInfo.Descriptor.MaxPacketSize)

                Do
                    Dim handle As UsbTransferQueue.Handle

                    ' Begin submitting transfers until TRANFER_MAX_OUTSTANDING_IO has benn reached.
                    ' then wait for the oldest outstanding transfer to complete.
                    '
                    ec = transferQeue.Transfer(handle)
                    If ec <> ErrorCode.Success Then
                        Throw New Exception("Failed getting async result")
                    End If

                    ' Show some information on the completed transfer.
                    showTransfer(handle, mTransferCount)
                Loop While System.Math.Max(System.Threading.Interlocked.Increment(mTransferCount),mTransferCount - 1) < TRANSFER_COUNT

                ' Cancels any oustanding transfers and free's the transfer queue handles.
                ' NOTE: A transfer queue can be reused after it's freed.
                transferQeue.Free()

                Console.WriteLine(vbCr & vbLf & "Done!" & vbCr & vbLf)
            Catch ex As Exception
                Console.WriteLine()
                Console.WriteLine((If(ec <> ErrorCode.None, ec & ":", [String].Empty)) & ex.Message)
            Finally
                If MyUsbDevice IsNot Nothing Then
                    If MyUsbDevice.IsOpen Then
                        ' If this is a "whole" usb device (libusb-win32, linux libusb-1.0)
                        ' it exposes an IUsbDevice interface. If not (WinUSB) the 
                        ' 'wholeUsbDevice' variable will be null indicating this is 
                        ' an interface of a device; it does not require or support 
                        ' configuration and interface selection.
                        Dim wholeUsbDevice As IUsbDevice = TryCast(MyUsbDevice, IUsbDevice)
                        If Not ReferenceEquals(wholeUsbDevice, Nothing) Then
                            ' Release interface #0.
                            wholeUsbDevice.ReleaseInterface(0)
                        End If

                        MyUsbDevice.Close()
                    End If
                    MyUsbDevice = Nothing
                End If

                ' Wait for user input..
                Console.ReadKey()

                ' Free usb resources
                UsbDevice.[Exit]()
            End Try
        End Sub

        Private Shared Sub showTransfer(handle As UsbTransferQueue.Handle, transferIndex As Integer)
            If mStartTime = DateTime.MinValue Then
                mStartTime = DateTime.Now
                Console.WriteLine("Synchronizing..")
                Return
            End If

            mTotalBytes += handle.Transferred
            Dim bytesSec As Double = mTotalBytes / (DateTime.Now - mStartTime).TotalSeconds

            Console.WriteLine("#{0} complete. {1} bytes/sec ({2} bytes) Data[1]={3:X2}", transferIndex, Math.Round(bytesSec, 2), handle.Transferred, handle.Data(1))
        End Sub
    End Class
End Namespace
Compiling the Code
  1. Create a new console application in your favorite designer.

  2. Verify your project references:

    • System.dll

    • LibUsbDotNet.dll

  3. Add/edit the main class. Copy/Paste code from one of the examples above.

Note: Example usb device firmware is located in the [InstallDirectory]\Benchmark\Firmware\[Manufacturer] directory.