MelbourneDeveloper / Device.Net

A C# cross platform connected device framework
MIT License
620 stars 119 forks source link

PR#215 Breaking on .Net Framework 4.8 #222

Open andyvorld opened 2 years ago

andyvorld commented 2 years ago

Describe the issue https://github.com/MelbourneDeveloper/Device.Net/pull/215 seems to be causing some issues with on .Net Framework 4.8. WriteAsync and WriteReadAsync seems to fail silently, with nothing written to the HID device, probed with USBPcap/wireshark. Using HID.Net 4.2.1 on .Net 5 or downgrading to 4.0.0 seems to solve the issue.

From what I can tell, this issue for .Net 4.8 occured at commit a45152ea52a699100c704cc23c90ed4a4a6912aa, using git bisect.

This maybe just be an issue with my specific HID device (Logitech G403).

Your Code The following code is sending an invalid probe to a Logitech HID++ 2.0 device.

        static void Main()
        {
            MainAsync();

            while (true)
            {
                Thread.Sleep(100);
            }
        }

        static async Task MainAsync()
        {
            var factories =
                new FilterDeviceDefinition(vendorId: 0x046D, usagePage: 0xFF00)
                .CreateWindowsHidDeviceFactory();

            //----------------------

            //Get connected device definitions
            var deviceDefinitions = (factories.GetConnectedDeviceDefinitionsAsync().Result).ToList();

            if (deviceDefinitions.Count == 0)
            {
                //No devices were found
                return;
            }

            //Get the device from its definition
            var trezorDevice = factories.GetDeviceAsync(deviceDefinitions.First(x => x.ReadBufferSize == 20)).Result;

            //Initialize the device
            trezorDevice.InitializeAsync().Wait();

            //Create the request buffer
            var buffer = new byte[20];
            buffer[0] = 0x11;
            buffer[1] = 0xFF;
            buffer[2] = 0x00;
            buffer[3] = 0x01;

            await trezorDevice.WriteAsync(buffer);
        }
    }

Info

MelbourneDeveloper commented 2 years ago

@andyvorld do you think it could be solved with #ifs?

andyvorld commented 2 years ago

I just tried with the following,

Device.Net\Windows\ApiService.cs

#if NETFRAMEWORK
        private const uint FILE_FLAG_OVERLAPPED = 0;
#else
        private const uint FILE_FLAG_OVERLAPPED = 0x40000000;
#endif

Hid.Net\Windows\WindowsHidApiService.cs

#if NETFRAMEWORK
        private const bool _isAsync = false;
#else
        private const bool _isAsync = true;
#endif
        public Stream OpenRead(SafeFileHandle readSafeFileHandle, ushort readBufferSize) => new FileStream(readSafeFileHandle, FileAccess.Read, readBufferSize, _isAsync);

        public Stream OpenWrite(SafeFileHandle writeSafeFileHandle, ushort writeBufferSize) => new FileStream(writeSafeFileHandle, FileAccess.ReadWrite, writeBufferSize, _isAsync);

That seems to have fixed my issue not having anything written, only when including the net45 build, while the netstandard2.0 builds still have the same issue.

MelbourneDeveloper commented 2 years ago

@andyvorld does the same issue occur if you target .net 5?

MelbourneDeveloper commented 2 years ago

@andyvorld you could submit a PR. I will probably do a new release fairly soon.

andyvorld commented 2 years ago

@andyvorld does the same issue occur if you target .net 5?

Using the nuget packaged 4.2.1, it works fine.

@andyvorld you could submit a PR. I will probably do a new release fairly soon.

EDIT2: Sorry I forgot to clean the build cache, so there were some conflicts between the binaries, rebuilt my test script in .Net5 with the changes and it works find with _isAsync = True.

Ill make a pull request now with my edits.

I am not sure if I am using the compiled dlls as expected, as for my .Net 5 test, using the binaries from the standard2.0 output of HID.Net fails at run time, while the net45 binaries works.

Which after going through visual studio's debugger showed that the _isAsync flag in WindowsHidApiService is set to false, which would break the initially working functionality for .Net 5.

EDIT: The specific error image

System.MissingMethodException
  HResult=0x80131513
  Message=Method not found: 'Void Device.Net.DeviceFactory..ctor(Microsoft.Extensions.Logging.ILoggerFactory, Device.Net.GetConnectedDeviceDefinitionsAsync, Device.Net.GetDeviceAsync, System.Func`3<Device.Net.ConnectedDeviceDefinition,System.Threading.CancellationToken,System.Threading.Tasks.Task`1<Boolean>>)'.
  Source=Hid.Net
  StackTrace:
   at Hid.Net.Windows.WindowsHidDeviceFactoryExtensions.CreateWindowsHidDeviceFactory(IEnumerable`1 filterDeviceDefinitions, ILoggerFactory loggerFactory, IHidApiService hidApiService, Nullable`1 classGuid, Nullable`1 readBufferSize, Nullable`1 writeBufferSize, GetConnectedDeviceDefinitionsAsync getConnectedDeviceDefinitionsAsync, Func`2 readReportTransform, Func`2 readTransferTransform, Func`3 writeTransferTransform, WriteReportTransform writeReportTransform) in /_/src/Hid.Net/Windows/WindowsHidDeviceFactoryExtensions.cs:line 169
   at Hid.Net.Windows.WindowsHidDeviceFactoryExtensions.CreateWindowsHidDeviceFactory(FilterDeviceDefinition filterDeviceDefinition, ILoggerFactory loggerFactory, IHidApiService hidApiService, Nullable`1 classGuid, Nullable`1 readBufferSize, Nullable`1 writeBufferSize, GetConnectedDeviceDefinitionsAsync getConnectedDeviceDefinitionsAsync, Func`2 readReportTransform, Func`2 readTransferTransform, Func`3 writeTransferTransform, WriteReportTransform writeReportTransform) in /_/src/Hid.Net/Windows/WindowsHidDeviceFactoryExtensions.cs:line 89
   at ConsoleApp3.Program.MainAsync() in C:\Users\Andrew\source\repos\ConsoleApp3\ConsoleApp1\Program.cs:line 27
   at ConsoleApp3.Program.Main() in C:\Users\Andrew\source\repos\ConsoleApp3\ConsoleApp1\Program.cs:line 17