HidLibrary icon indicating copy to clipboard operation
HidLibrary copied to clipboard

ReadReport loosing data

Open DevLocus opened this issue 8 years ago • 5 comments

It seems like ReadReport is loosing data when a lot of data is sent to the Host in a short amount of time. In my case about 60KB to 100KB is being sent at full speed on a USB 2.0 port in high speed mode. This is likely because the buffer is too small and the ReadReport function takes too long. I see there is a HidFastReadDevice with a faster read function, but no way to create an instance of the class. There is also nothing exposed in the OpenDevice function to allow overriding the default buffer size to fit the application.

What is the best fix for this? Do I need to download the source code and change it myself?

DevLocus avatar Feb 01 '17 22:02 DevLocus

The latest code on the master branch includes the HidFastReadEnumerator class that will instantiateHidFastReadDevice objects.

amullins83 avatar Feb 01 '17 23:02 amullins83

I ending up adding the below code to the HidDevices.cs file to get around the issue. It turned out the buffer was too small and this code allows me to change the buffer to a more reasonable number for my application.

public int InputBuffer { get { int i = 0; NativeMethods.HidD_GetNumInputBuffers(Handle, ref i); return i; } set { if (value > 31) { NativeMethods.HidD_SetNumInputBuffers(Handle, value); } else { throw new ArgumentOutOfRangeException(string.Concat(value, " is too low of a value.")); } } }

DevLocus avatar Feb 03 '17 03:02 DevLocus

I have similar issue with fast incoming data. My device sends reports with two different ReportId, each report sending cycle is 5ms. But host PC lose some of them: image I'd say it is HID device issue, but i can see all reports coming in Wireshark. I use HidFastReadDevice and FastReadReport, but not sure if i do it right:

        static public void Connect(HidDevice device)
        {
            hidDevice = device;

            HidFastReadEnumerator enumerator = new HidFastReadEnumerator();
            fastDevice = (HidFastReadDevice)enumerator.GetDevice(hidDevice.DevicePath);

            if (!fastDevice.IsOpen)
            {
                fastDevice.OpenDevice();

                hidDevice.MonitorDeviceEvents = true;
                hidDevice.Inserted += HidDeviceAddedEventHandler;
                hidDevice.Removed += HidDeviceRemovedEventHandler;

                fastDevice.MonitorDeviceEvents = false;
                fastDevice.FastReadReport(ReadReportCallback);
            }
        }

        static private void ReadReportCallback(HidReport report)
        {
            HidReport hr = report;

            // wait for new packet
            if (fastDevice.IsConnected)
            {
                fastDevice.FastReadReport(ReadReportCallback);
            }

            Console.WriteLine("Report " + hr.ReportId + " received " + Environment.TickCount);
            // raise event for received packet
            PacketReceived?.Invoke(hr);
        }

vostrenkov avatar Jul 20 '20 16:07 vostrenkov

The purpose of the "Fast" subclass was to avoid checking "IsConnected" every time a packet comes in. The check is fairly slow (I can't remember why, I haven't touched this in years). I would say try it without the IsConnected check.

Also, why are you turning MonitorDeviceEvents on and off?

amullins83 avatar Jul 20 '20 20:07 amullins83

Thank you for the fast answer. I have tried this without checking IsConnected and looks like receiving works better though my GUI is stalling when HID device connected. I guess i should find a way to run all HID stuff in other thread to fix it.

I thought DeviceEvents are different for instances of HidDevice and HidFastReadDevice (and HidDevice is passed to the event as argument) so i decided to monitor plugging/unplugging through hidDevice (HidDevice instance) while reading/writing is managed through fastDevice (HidFastReadDevice instance). It seem not working quite good but i want to reach proper report receiving first

vostrenkov avatar Jul 20 '20 20:07 vostrenkov