Coder Social home page Coder Social logo

hidapi.net's People

Contributors

badcel avatar dependabot[bot] avatar tmittet avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

hidapi.net's Issues

Fatal error. Internal CLR error. (0x80131506) when read data

  while (controller.isConnected)
        {
            try
            {
                var data = controller.HidDevice.Read(32);
                Thread.Sleep(1);
            }
            catch (HidException)
            {
                controller.isConnected = false;
            }
        }

after long time running, Internal CLR error. occurred.

Fatal error. Internal CLR error. (0x80131506)
at HidApi.Device.Read(Int32)
at ControllerSDK.hardware.HidManager._readDataFromDevice(System.Object)
at System.Threading.Thread.StartCallback()

.net version: 8.0.101 and 6.0.321 BOTH Tried

Bump major version and update readme

  • Some changes (e.g. throw different exception type) are breaking the API.
  • Readme: Mention that .net8.0 is supported
  • Readme: Mention .net8.0 version is aot compatible

Read serial number (and other strings) may cause memory corruption

I had that my application crashed during transfers with the exception mentioned in the issue #84. The strange thing was that the crash did not always happen at the same time.

I did a lot of changes to my code that calls the hidapi library to eliminate various possible issues. Also I modified my code that read and write calls are only made from the same thread.

After a while I came to the conclusion, that the error occurs when the runtime dicovers issue with memory corruption. This happens independently to the currently running code.

Problem

After digging into the issue by using the code directly from the repository I've found out that the issue was caused by reading the manufacturer, serial number and product identifier when I opened the device. If I removed the reading of these three strings the applicaton worked stable. So I had a close look at these read methods.

The definiton in the hidapi library for these string reading functions look like this:
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen);
The maxlen parameter description is: The length of the buffer in multiples of wchar_t.

In the library currently a buffer gets allocated by the WCharTString class. The buffer is actually correctly doubled the size of the provided maxmal string length to be able to contain wide chars. The problem is that the value passed to the maxlen parameter is the length of the buffer and not the number of wchars the buffer was created for. This causes that the library asumes that the buffer is larger than it is and probably writes to memory behind the allocated space.

Solution

The solution is to add a parameter "maxLength" to the methods like "GetManufacturerString" in the NativeMethods.cs file. This parameter can than be passed to the invoked call instead of the invalid "buffer.Length" (see below). In the Device.cs the number of allowed characters "maxLength" need then to be passed to the changed methods.

Old:

`
public static int GetManufacturerString(DeviceSafeHandle device, ReadOnlySpan buffer)
{
return GetManufacturerString(device, ref MemoryMarshal.GetReference(buffer), (nuint) buffer.Length);
}

public static int GetProductString(DeviceSafeHandle device, ReadOnlySpan<byte> buffer)
{
    return GetProductString(device, ref MemoryMarshal.GetReference(buffer), (nuint) buffer.Length);
}

public static int GetSerialNumberString(DeviceSafeHandle device, ReadOnlySpan<byte> buffer)
{
    return GetSerialNumberString(device, ref MemoryMarshal.GetReference(buffer), (nuint) buffer.Length);
}

public static int GetIndexedString(DeviceSafeHandle device, int index, ReadOnlySpan<byte> buffer)
{
    return GetIndexedString(device, index, ref MemoryMarshal.GetReference(buffer), (nuint) buffer.Length);
}

`

New:

`
public static int GetManufacturerString(DeviceSafeHandle device, ReadOnlySpan buffer, int maxLength)
{
return GetManufacturerString(device, ref MemoryMarshal.GetReference(buffer), (nuint) maxLength);
}

public static int GetProductString(DeviceSafeHandle device, ReadOnlySpan<byte> buffer, int maxLength)
{
    return GetProductString(device, ref MemoryMarshal.GetReference(buffer), (nuint) maxLength);
}

public static int GetSerialNumberString(DeviceSafeHandle device, ReadOnlySpan<byte> buffer, int maxLength)
{
    return GetSerialNumberString(device, ref MemoryMarshal.GetReference(buffer), (nuint) maxLength);
}

public static int GetIndexedString(DeviceSafeHandle device, int index, ReadOnlySpan<byte> buffer, int maxLength)
{
    return GetIndexedString(device, index, ref MemoryMarshal.GetReference(buffer), (nuint) maxLength);
}

`

Additional Note

The string that is returned by this methods (after fixing the issue) contains a lot of '\0' characters (probably the hidapi sets the full memory area to '\0'). Maybe it would be nice if these '\0' are removed with something like .Trim('\0') before the string is returned.

Additional Note 2

As workaround I found ot that I could read the string s from the DeviceInfo by the method "GetDeviceInfo". That worked without issues.

Define HidApi name per platform

Do not put all possible HidApi binary names into a list of available binaries in "NativeMethods.cs" but initialize the list depending on the current platform.

Create platform specific DLLs internally

Currently during runtime the operating system is checked for several string operations to decide how to decode a pointer of w_char_t data as the size of w_char_t is different between Linux / Mac and Windows.

It is possible to include runtime assemblies in nuget which are separted by runtime and only used during runtime. If the build process would generate a private DLL containing the code for a specific platform to read w_char_t data the operating system check would not need to happen during runtime but while loading the nuget the correct assembly with the correct code would be loaded and no check would need to happen.

See:

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.