Search code examples
c#usbserial

Virtual USB-serial port always failing after 0x3800 bytes received


I have a device sending a constant stream of data to my PC which is receiving it over a virtual USB-serial port. On the PC I use a C# program to read the virtual USB-serial port. After receiving 0x3800 bytes (14336 bytes or 14 kB) receiving stops. (See source code below on a simple version of the test program)

OS: windows 10 (also tried on a Windows 7 system, same results) Compiler: Visual Studio 2015 Com port settings: COM3, 9600/8/N/1, no handshake.

I used 'serial port monitor' which shows that data is received after 0x3800 bytes, communication over USB between the device and the PC is not breaking down.

I've searched (for several days now) with google in github and SourceForge for possible other solutions, found nothing usefull.

The simplified version of the code below was changed in several ways to check:

  • different port configurations,
  • different buffer sizes at device level,
  • several Nuget packages which provide virtual USB-serial port objects, most read nothing at all or fail at the same point. One package could read 0x4000 bytes.
  • a C++ version (which can connect but does not read one byte).
  • Tried a real RS232 port and another PC with a data sourse. No problems.

How is it possible that a tool like 'serial port monitor' can read without problems and my simple C# program not? There are several assumptions I can make about it:

  • There is a configuration error in my code (which I tried very hard to find).
  • The two use different access paths to get to the virtual USB-serial data. (If so, what other ways are there to connect to a virtual USB-serial port?)

Added a callback OnErrorReceived. This is never trigered.

I'm stuck, I do not know what to try of how to get communication going. Any advise is welcome.

Here is some simple code to show what I use. (Eddited to follow up a suggestion from JHBonarius)

using System;
using System.Threading;

namespace TestConsole
{
    class Program
    {
        const string PORT_NAME = "COM3";
        const int BAUD_RATE = 9600;

        static System.IO.Ports.SerialPort port;

        static void Main(string[] args)
        {
            Console.WriteLine($"] port connect {PORT_NAME}");
            port = new System.IO.Ports.SerialPort(PORT_NAME, BAUD_RATE);
            port.DataReceived += OnRx;
            port.ErrorReceived += OnErrorReceived;
            port.DtrEnable = true;  // required for communiation
            port.Open();

            // and wait forever.
            while (true) Thread.Sleep(1000);
        }

        private static void OnErrorReceived(object sender, System.IO.Ports.SerialErrorReceivedEventArgs e)
        {
            Console.WriteLine();
            Console.WriteLine($"] port error = {e.EventType}");
            Console.WriteLine();
        }

        static void OnRx(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            System.IO.Ports.SerialPort sp = (System.IO.Ports.SerialPort)sender;
            while (0 < sp.BytesToRead)
            {
                var b = sp.ReadByte();
                if (-1 < b) ConsoleWriteByte((byte)b);
                else break;
            }
        }

        const int BYTES_PER_LINE = 16;

        static int count = 0;
        static int line = 0;

        static void ConsoleWriteByte(byte value)
        {
            if (count % BYTES_PER_LINE == 0)
            {
                Console.WriteLine();
                Console.Write($"{line:x6}:");
                count = 0;
                line += BYTES_PER_LINE;
            }

            Console.Write($" {value:x2}");
            count++;
        }
    }
}

Solution

  • I did some more testing on this problem and got a hold on the code used at the sender side.

    It apears that the sender side is transmitting data very fast and is monitoring the connection at USB level. If there are any problems such as buffer overflow the transmission stops.

    If I increase buffer size at the receiving end I can handle more data but the C++ solution runs into problems.

    I do not know how to capture the data faster or in a different way. I can change code at the receiver side but not at the sender side. So, adding handshake signales is (unfortunately) not an option but it would solve the problem.

    Case closed.

    edit 2022-oct-7 hmm... not yet fully closed.

    Today the problem came back to me again. Played around a bit with the code, not changing anyting. The C++ test program was running for more than 60 minutes uniterupted. starting some other applications made it stop.

    Looked around on how to set priority and this. Added a line SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS) and that version ran without problems for more than three hours.

    Changing process priority makes a big difference.