Write to USB PORT C# using LibUsbDotNet C# USB Library

13.7k views Asked by At

I want to write some data to a USB port and receive an answer from it. I actually used the same

string cmdLine = "@00WD3000C82B*\r";

and sent it to the same machine with the SerialPort object and by using rs235 port. its do well.. and I got the right answer using these methods:

omronAX.WriteAction("3000", 200.ToString("0000"));

public void WriteAction(string DM_address, string Data)
{
    write_action(DM_address, Data);
}

private void write_action(string DM_address, string Data)
{
    GotData = "";
    Puredata = "";
    EndCode = "";
    try
    {
        int ErCd = Write_2_port("WD", DM_address, Data);
        if (ErCd != 0) { return; }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

private int Write_2_port(string cod_cmd, string Addr, string Data2write)
{
    DReady = false;
    out_data = "";
    end_c = "";

    char cr = Convert.ToChar(13);
    string cmd = "", Dat1 = "", Dat2 = "";
    Mess = "";

    Dat2 = Data2write;
    if (Addr.Trim().Length > 0)
    {
        try
        {
            Dat1 = String.Format("{0:0000}", Convert.ToInt16(Addr));
        }
        catch (FormatException ex)
        {
            Mess = ex.Message;
            return 1;
        }
        catch (OverflowException ex1)
        {
            Mess = ex1.Message;
            return 3;
        }
    }

    int.TryParse(Dat2, out int hex);
    string hexValue = hex.ToString("X");

    cmd = "@" + BakN + cod_cmd + Dat1 + hexValue ;
    string send2port = cmd + Checksm(cmd) + "*" + cr;
    SentCommand = send2port;
    try
    {
        //     if (Sport.IsOpen == false) { Sport.Open(); }
        locking = true;
        Sport.WriteTimeout = 5000;
        Sport.WriteLine(send2port);

        int i = 0;
        while (locking)
        {
            if (i++ == 500)
            {
                throw new TimeoutException("יתכן שיש בעיות תקשורת עם המערכת.");
            }
            Thread.Sleep(10);
        }
        //   T:System.ArgumentNullException:
        //     The str parameter is null.
        //
        //   T:System.InvalidOperationException:
        //     The specified port is not open.
        //
        //   T:System.TimeoutException:
        //     The System.IO.Ports.SerialPort.WriteLine(System.String) method could not write
        //     to the stream.
    }
    catch (TimeoutException ex)
    {
        Mess = ex.Message;
        throw ex;
    }
    catch (Exception ex)
    {
        Mess = ex.Message;
        return 2;
    }
    return 0;
}

for the next code, I try using USB port and write to it the same line... But I got nothing when I read the answer back and I got (bytesRead = 0) in my bytesWritten, I got 15...

using System;
using System.Text;
using System.Text.RegularExpressions;
using LibUsbDotNet;
using LibUsbDotNet.Main;

namespace Examples
{
    internal class ReadWrite
    {
        public static UsbDevice MyUsbDevice;

        #region SET YOUR USB Vendor and Product ID!

        public static UsbDeviceFinder MyUsbFinder = new UsbDeviceFinder(0x0590,0x005B);

        #endregion

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

            try
            {
                // Find and open the USB device.
                MyUsbDevice = UsbDevice.OpenUsbDevice(MyUsbFinder);

                // 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)
                // it will have an IUsbDevice interface. If not (WinUSB) the 
                // variable will be null indicating this is an interface of a 
                // device.
                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(0);
                }

                // open read endpoint 1.
                UsbEndpointReader reader = MyUsbDevice.OpenEndpointReader(ReadEndpointID.Ep01);

                // open write endpoint 1.
                UsbEndpointWriter writer = MyUsbDevice.OpenEndpointWriter(WriteEndpointID.Ep01);

                // Remove the exepath/startup filename text from the begining of the CommandLine.
                //string cmdLine = Regex.Replace(Environment.CommandLine, "^\".+?\"^.*? |^.*? ", "", RegexOptions.Singleline);
                string cmdLine = "@00WD3000A11*\r";
                if (!String.IsNullOrEmpty(cmdLine))
                {
                    int bytesWritten;
                    ec = writer.Write(Encoding.Default.GetBytes(cmdLine), 20000000, out bytesWritten);
                    if (ec != ErrorCode.None) throw new Exception(UsbDevice.LastErrorString);

                    byte[] readBuffer = new byte[1024];
                    while (ec == ErrorCode.None)
                    {
                        int bytesRead;

                        // If the device hasn't sent data in the last 100 milliseconds,
                        // a timeout error (ec = IoTimedOut) will occur. 
                        ec = reader.Read(readBuffer, 100, out bytesRead);

                        if (bytesRead == 0) throw new Exception("No more bytes!");

                        // Write that output to the console.
                        Console.Write(Encoding.Default.GetString(readBuffer, 0, bytesRead));
                    }

                    Console.WriteLine("\r\nDone!\r\n");
                }
                else
                    throw new Exception("Nothing to do.");
            }
            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;

                    // Free usb resources
                    UsbDevice.Exit();

                }

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

I have no idea and I am doing wrong, thanks.

2

There are 2 answers

0
Developing DEV On

I had an issue getting my device to connect with another library because I was using upper case for alphabetic characters in the VID/PID. Have you tried using lower case ("0x005b" instead of "0x005B")?

1
Christian Findlay On

I recommend using Usb.Net (https://github.com/MelbourneDeveloper/Device.Net) instead of LibUsb. The problem with LibUsb is that is just wraps WinUSB calls. So, you are deploying an extra C dll (LibUsb) that just points to an existing Windows C DLL. LibUsb is good if you want to keep the code cross platform with Linux, but otherwise, there's not much point.

Here is sample WinUsb code (https://github.com/MelbourneDeveloper/Device.Net/blob/master/src/Usb.Net/Windows/WindowsUsbDevice.cs)

    public override Task InitializeAsync()
        {
            Dispose();

            int errorCode;

            if (string.IsNullOrEmpty(DeviceId))
            {
                throw new WindowsException($"{nameof(DeviceDefinition)} must be specified before {nameof(InitializeAsync)} can be called.");
            }

            _DeviceHandle = APICalls.CreateFile(DeviceId, (APICalls.GenericWrite | APICalls.GenericRead), APICalls.FileShareRead | APICalls.FileShareWrite, IntPtr.Zero, APICalls.OpenExisting, APICalls.FileAttributeNormal | APICalls.FileFlagOverlapped, IntPtr.Zero);

            if (_DeviceHandle.IsInvalid)
            {
                //TODO: is error code useful here?
                errorCode = Marshal.GetLastWin32Error();
                if (errorCode > 0) throw new Exception($"Device handle no good. Error code: {errorCode}");
            }

            var isSuccess = WinUsbApiCalls.WinUsb_Initialize(_DeviceHandle, out var defaultInterfaceHandle);
            HandleError(isSuccess, "Couldn't initialize device");

            var bufferLength = (uint)Marshal.SizeOf(typeof(USB_DEVICE_DESCRIPTOR));
            isSuccess = WinUsbApiCalls.WinUsb_GetDescriptor(defaultInterfaceHandle, WinUsbApiCalls.DEFAULT_DESCRIPTOR_TYPE, 0, 0, out _UsbDeviceDescriptor, bufferLength, out var lengthTransferred);
            HandleError(isSuccess, "Couldn't get device descriptor");

            byte i = 0;

            //Get the first (default) interface
            var defaultInterface = GetInterface(defaultInterfaceHandle);

            _UsbInterfaces.Add(defaultInterface);

            while (true)
            {
                isSuccess = WinUsbApiCalls.WinUsb_GetAssociatedInterface(defaultInterfaceHandle, i, out var interfacePointer);
                if (!isSuccess)
                {
                    errorCode = Marshal.GetLastWin32Error();
                    if (errorCode == APICalls.ERROR_NO_MORE_ITEMS) break;

                    throw new Exception($"Could not enumerate interfaces for device {DeviceId}. Error code: { errorCode}");
                }

                var associatedInterface = GetInterface(interfacePointer);

                _UsbInterfaces.Add(associatedInterface);

                i++;
            }

            IsInitialized = true;

            RaiseConnected();

            return Task.CompletedTask;
   }

However, I did submit this sample to LibUsbDotNet and it's now the accepted Read/Write sample there (https://github.com/LibUsbDotNet/LibUsbDotNet/blob/master/src/Examples/Read.Write/ReadWrite.cs):

       public static void Main(string[] args)
        {
            using (var context = new UsbContext())
            {
                context.SetDebugLevel(LogLevel.Info);

                //Get a list of all connected devices
                var usbDeviceCollection = context.List();

                //Narrow down the device by vendor and pid
                var selectedDevice = usbDeviceCollection.FirstOrDefault(d => d.ProductId == ProductId && d.VendorId == VendorId);

                //Open the device
                selectedDevice.Open();

                //Get the first config number of the interface
                selectedDevice.ClaimInterface(selectedDevice.Configs[0].Interfaces[0].Number);

                //Open up the endpoints
                var writeEndpoint = selectedDevice.OpenEndpointWriter(WriteEndpointID.Ep01);
                var readEnpoint = selectedDevice.OpenEndpointReader(ReadEndpointID.Ep01);

                //Create a buffer with some data in it
                var buffer = new byte[64];
                buffer[0] = 0x3f;
                buffer[1] = 0x23;
                buffer[2] = 0x23;

                //Write three bytes
                writeEndpoint.Write(buffer, 3000, out var bytesWritten);

                var readBuffer = new byte[64];

                //Read some data
                readEnpoint.Read(readBuffer, 3000, out var readBytes);
            }
        }