From b277960acd23a43e24d0cced488a1a8dc56147c5 Mon Sep 17 00:00:00 2001 From: Christian Findlay Date: Fri, 12 Nov 2021 06:54:37 +1100 Subject: [PATCH 1/6] Allow the consumer to specify the call to CreateConnection --- .../Windows/WindowsHidDeviceFactoryExtensions.cs | 10 ++++++++-- src/Hid.Net/Windows/WindowsHidHandler.cs | 15 +++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/Hid.Net/Windows/WindowsHidDeviceFactoryExtensions.cs b/src/Hid.Net/Windows/WindowsHidDeviceFactoryExtensions.cs index 1d1a294e..72c000dd 100644 --- a/src/Hid.Net/Windows/WindowsHidDeviceFactoryExtensions.cs +++ b/src/Hid.Net/Windows/WindowsHidDeviceFactoryExtensions.cs @@ -114,6 +114,8 @@ public static IDeviceFactory CreateWindowsHidDeviceFactory( /// Exposes the raw data from the device (including Report Id) on reads and allows you to format the returned /// Given the Report Id and data supplied for the write, allow you to format the raw data that is sent to the device /// Given the data supplied, allow you to divide the data in to a + /// Allows you to specify the API level call to create the Read handle + /// Allows you to specify the API level call to create the Write handle /// A factory which enumerates and instantiates devices public static IDeviceFactory CreateWindowsHidDeviceFactory( this IEnumerable filterDeviceDefinitions, @@ -126,7 +128,9 @@ public static IDeviceFactory CreateWindowsHidDeviceFactory( Func readReportTransform = null, Func readTransferTransform = null, Func writeTransferTransform = null, - WriteReportTransform writeReportTransform = null) + WriteReportTransform writeReportTransform = null, + CreateConnection createReadConnection = null, + CreateConnection createWriteConnection = null) { if (filterDeviceDefinitions == null) throw new ArgumentNullException(nameof(filterDeviceDefinitions)); @@ -160,7 +164,9 @@ public static IDeviceFactory CreateWindowsHidDeviceFactory( hidApiService, loggerFactory, readTransferTransform, - writeTransferTransform), + writeTransferTransform, + createReadConnection, + createWriteConnection), loggerFactory, readReportTransform, writeReportTransform diff --git a/src/Hid.Net/Windows/WindowsHidHandler.cs b/src/Hid.Net/Windows/WindowsHidHandler.cs index bf4a571a..772435be 100644 --- a/src/Hid.Net/Windows/WindowsHidHandler.cs +++ b/src/Hid.Net/Windows/WindowsHidHandler.cs @@ -11,9 +11,10 @@ namespace Hid.Net.Windows { + public delegate SafeFileHandle CreateConnection(string deviceId, FileAccessRights desiredAccess, uint shareMode, uint creationDisposition); + internal class WindowsHidHandler : IHidDeviceHandler { - #region Private Fields private readonly IHidApiService _hidService; @@ -24,6 +25,8 @@ internal class WindowsHidHandler : IHidDeviceHandler private SafeFileHandle _readSafeFileHandle; private Stream _writeFileStream; private SafeFileHandle _writeSafeFileHandle; + private readonly CreateConnection _createReadConnection; + private readonly CreateConnection _createWriteConnection; #endregion Private Fields @@ -36,7 +39,9 @@ public WindowsHidHandler( IHidApiService hidApiService = null, ILoggerFactory loggerFactory = null, Func readTransferTransform = null, - Func writeTransferTransform = null) + Func writeTransferTransform = null, + CreateConnection createReadConnection = null, + CreateConnection createWriteConnection = null) { _logger = (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger(); DeviceId = deviceId ?? throw new ArgumentNullException(nameof(deviceId)); @@ -51,6 +56,12 @@ public WindowsHidHandler( _hidService = hidApiService ?? new WindowsHidApiService(loggerFactory); WriteBufferSize = writeBufferSize; ReadBufferSize = readBufferSize; + + _createReadConnection = createReadConnection ??= (deviceId, fileAccessRights, shareMode, creationDisposition) + => hidApiService.CreateReadConnection(deviceId, fileAccessRights); + + _createWriteConnection = createWriteConnection ??= (deviceId, fileAccessRights, shareMode, creationDisposition) + => hidApiService.CreateWriteConnection(deviceId); } #endregion Public Constructors From 150a3d0aae26c56fe2dc0f6a71913631b0483042 Mon Sep 17 00:00:00 2001 From: Christian Findlay Date: Fri, 12 Nov 2021 07:00:32 +1100 Subject: [PATCH 2/6] Add some parameters to the overloads --- .../WindowsHidDeviceFactoryExtensions.cs | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/Hid.Net/Windows/WindowsHidDeviceFactoryExtensions.cs b/src/Hid.Net/Windows/WindowsHidDeviceFactoryExtensions.cs index 72c000dd..f378cc53 100644 --- a/src/Hid.Net/Windows/WindowsHidDeviceFactoryExtensions.cs +++ b/src/Hid.Net/Windows/WindowsHidDeviceFactoryExtensions.cs @@ -31,6 +31,8 @@ public static class WindowsHidDeviceFactoryExtensions /// Exposes the raw data from the device (including Report Id) on reads and allows you to format the returned /// Given the Report Id and data supplied for the write, allow you to format the raw data that is sent to the device /// Given the data supplied, allow you to divide the data in to a + /// Allows you to specify the API level call to create the Read handle + /// Allows you to specify the API level call to create the Write handle /// A factory which enumerates and instantiates devices public static IDeviceFactory CreateWindowsHidDeviceFactory( ILoggerFactory loggerFactory = null, @@ -42,7 +44,9 @@ public static IDeviceFactory CreateWindowsHidDeviceFactory( Func readReportTransform = null, Func readTransferTransform = null, Func writeTransferTransform = null, - WriteReportTransform writeReportTransform = null) + WriteReportTransform writeReportTransform = null, + CreateConnection createReadConnection = null, + CreateConnection createWriteConnection = null) { return CreateWindowsHidDeviceFactory( new ReadOnlyCollection(new List()), @@ -55,7 +59,9 @@ public static IDeviceFactory CreateWindowsHidDeviceFactory( readReportTransform, readTransferTransform, writeTransferTransform, - writeReportTransform: writeReportTransform); + writeReportTransform: writeReportTransform, + createReadConnection, + createWriteConnection); } /// @@ -72,6 +78,8 @@ public static IDeviceFactory CreateWindowsHidDeviceFactory( /// Allows you to manually convert the in to a so that the Report Id is not discarded on ReadAsync. By default, this inserts the Report Id at index zero of the array. /// Exposes the raw data from the device (including Report Id) on reads and allows you to format the returned /// Given the Report Id and data supplied for the write, allow you to format the raw data that is sent to the device + /// Allows you to specify the API level call to create the Read handle + /// Allows you to specify the API level call to create the Write handle /// A factory which enumerates and instantiates devices public static IDeviceFactory CreateWindowsHidDeviceFactory( this FilterDeviceDefinition filterDeviceDefinition, @@ -84,7 +92,9 @@ public static IDeviceFactory CreateWindowsHidDeviceFactory( Func readReportTransform = null, Func readTransferTransform = null, Func writeTransferTransform = null, - WriteReportTransform writeReportTransform = null) + WriteReportTransform writeReportTransform = null, + CreateConnection createReadConnection = null, + CreateConnection createWriteConnection = null) { return CreateWindowsHidDeviceFactory( new ReadOnlyCollection(new List { filterDeviceDefinition }), @@ -97,7 +107,9 @@ public static IDeviceFactory CreateWindowsHidDeviceFactory( readReportTransform, readTransferTransform, writeTransferTransform, - writeReportTransform); + writeReportTransform, + createReadConnection, + createWriteConnection); } /// From 75ddd43f36f74c32dda129c636b25b335b3144c9 Mon Sep 17 00:00:00 2001 From: Christian Findlay Date: Fri, 12 Nov 2021 07:14:11 +1100 Subject: [PATCH 3/6] Sample code --- src/Device.Net.UnitTests/GetFactoryExtensions.cs | 11 ++++++++++- src/Device.Net/Windows/APICalls.cs | 4 ---- src/Device.Net/Windows/IApiService.cs | 3 ++- src/Hid.Net/Windows/WindowsHidHandler.cs | 15 ++++++++++----- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/Device.Net.UnitTests/GetFactoryExtensions.cs b/src/Device.Net.UnitTests/GetFactoryExtensions.cs index db14352f..543f14c0 100644 --- a/src/Device.Net.UnitTests/GetFactoryExtensions.cs +++ b/src/Device.Net.UnitTests/GetFactoryExtensions.cs @@ -36,7 +36,16 @@ public static IDeviceFactory GetHidDeviceFactory( => filterDeviceDefinition.CreateWindowsHidDeviceFactory( loggerFactory, readReportTransform: readReportTransform, - writeReportTransform: writeReportTransform); + writeReportTransform: writeReportTransform, + createReadConnection: (apiService, deviceId, fileAccessRights, shareMode, creationDisposition) + => apiService.CreateFile( + deviceId, + Windows.FileAccessRights.GenericRead, + shareMode, + IntPtr.Zero, + creationDisposition, + FILE_FLAG_OVERLAPPED, + IntPtr.Zero)); } } diff --git a/src/Device.Net/Windows/APICalls.cs b/src/Device.Net/Windows/APICalls.cs index 2072f0ce..66b8624f 100644 --- a/src/Device.Net/Windows/APICalls.cs +++ b/src/Device.Net/Windows/APICalls.cs @@ -5,11 +5,7 @@ using System; using System.Runtime.InteropServices; -#pragma warning disable CA1707 // Identifiers should not contain underscores -#pragma warning disable CA1021 // Avoid out parameters -#pragma warning disable CA1401 // P/Invokes should not be visible #pragma warning disable CA5392 // Use DefaultDllImportSearchPaths attribute for P/Invokes -#pragma warning disable CA1045 // Do not pass types by reference #pragma warning disable CA1060 // Move pinvokes to native methods class namespace Device.Net.Windows diff --git a/src/Device.Net/Windows/IApiService.cs b/src/Device.Net/Windows/IApiService.cs index 45bcb118..313eded7 100644 --- a/src/Device.Net/Windows/IApiService.cs +++ b/src/Device.Net/Windows/IApiService.cs @@ -1,6 +1,6 @@ using Microsoft.Win32.SafeHandles; +using System; -#pragma warning disable CA1707 // Identifiers should not contain underscores #pragma warning disable CA1021 // Avoid out parameters #pragma warning disable CA1045 // Do not pass types by reference @@ -8,6 +8,7 @@ namespace Device.Net.Windows { public interface IApiService { + SafeFileHandle CreateFile(string lpFileName, FileAccessRights dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile) SafeFileHandle CreateWriteConnection(string deviceId); SafeFileHandle CreateReadConnection(string deviceId, FileAccessRights desiredAccess); //TODO: Get rid of read/write. They can be done with file streams... diff --git a/src/Hid.Net/Windows/WindowsHidHandler.cs b/src/Hid.Net/Windows/WindowsHidHandler.cs index 772435be..e254eaf5 100644 --- a/src/Hid.Net/Windows/WindowsHidHandler.cs +++ b/src/Hid.Net/Windows/WindowsHidHandler.cs @@ -11,7 +11,12 @@ namespace Hid.Net.Windows { - public delegate SafeFileHandle CreateConnection(string deviceId, FileAccessRights desiredAccess, uint shareMode, uint creationDisposition); + public delegate SafeFileHandle CreateConnection( + IHidApiService apiService, + string deviceId, + FileAccessRights desiredAccess, + uint shareMode, + uint creationDisposition); internal class WindowsHidHandler : IHidDeviceHandler { @@ -57,11 +62,11 @@ public WindowsHidHandler( WriteBufferSize = writeBufferSize; ReadBufferSize = readBufferSize; - _createReadConnection = createReadConnection ??= (deviceId, fileAccessRights, shareMode, creationDisposition) - => hidApiService.CreateReadConnection(deviceId, fileAccessRights); + _createReadConnection = createReadConnection ??= (apiService, deviceId, fileAccessRights, shareMode, creationDisposition) + => apiService.CreateReadConnection(deviceId, fileAccessRights); - _createWriteConnection = createWriteConnection ??= (deviceId, fileAccessRights, shareMode, creationDisposition) - => hidApiService.CreateWriteConnection(deviceId); + _createWriteConnection = createWriteConnection ??= (apiService, deviceId, fileAccessRights, shareMode, creationDisposition) + => apiService.CreateWriteConnection(deviceId); } #endregion Public Constructors From b3cb0e2a716f8ded4aef1ab4d80ee311ccbce303 Mon Sep 17 00:00:00 2001 From: Christian Findlay Date: Wed, 1 Dec 2021 11:12:27 +1100 Subject: [PATCH 4/6] Abstract out connection --- .../GetFactoryExtensions.cs | 5 ++-- src/Device.Net/Windows/ApiService.cs | 23 +++++++++++++------ src/Device.Net/Windows/IApiService.cs | 2 +- src/Hid.Net/Windows/WindowsHidHandler.cs | 2 +- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/Device.Net.UnitTests/GetFactoryExtensions.cs b/src/Device.Net.UnitTests/GetFactoryExtensions.cs index 543f14c0..9f19a8ff 100644 --- a/src/Device.Net.UnitTests/GetFactoryExtensions.cs +++ b/src/Device.Net.UnitTests/GetFactoryExtensions.cs @@ -1,4 +1,5 @@  +using Device.Net.Windows; using Hid.Net; using Hid.Net.Windows; using Microsoft.Extensions.Logging; @@ -40,11 +41,11 @@ public static IDeviceFactory GetHidDeviceFactory( createReadConnection: (apiService, deviceId, fileAccessRights, shareMode, creationDisposition) => apiService.CreateFile( deviceId, - Windows.FileAccessRights.GenericRead, + FileAccessRights.GenericRead, shareMode, IntPtr.Zero, creationDisposition, - FILE_FLAG_OVERLAPPED, + Constants.FILE_FLAG_OVERLAPPED, IntPtr.Zero)); } } diff --git a/src/Device.Net/Windows/ApiService.cs b/src/Device.Net/Windows/ApiService.cs index a3ecc11a..3899efc1 100644 --- a/src/Device.Net/Windows/ApiService.cs +++ b/src/Device.Net/Windows/ApiService.cs @@ -4,22 +4,24 @@ using System; using System.Runtime.InteropServices; -#pragma warning disable CA1707 // Identifiers should not contain underscores -#pragma warning disable CA1021 // Avoid out parameters #pragma warning disable CA5392 // Use DefaultDllImportSearchPaths attribute for P/Invokes #pragma warning disable CA1060 // Move pinvokes to native methods class +#pragma warning disable CA1707 // Identifiers should not contain underscores namespace Device.Net.Windows { - internal class ApiService : IApiService + public static class Constants { - #region Fields #if NETFRAMEWORK - private const uint FILE_FLAG_OVERLAPPED = 0; + public const uint FILE_FLAG_OVERLAPPED = 0; #else - private const uint FILE_FLAG_OVERLAPPED = 0x40000000; + public const uint FILE_FLAG_OVERLAPPED = 0x40000000; #endif + } + internal class ApiService : IApiService + { + #region Fields protected ILogger Logger { get; } #endregion @@ -44,8 +46,15 @@ internal class ApiService : IApiService private SafeFileHandle CreateConnection(string deviceId, FileAccessRights desiredAccess, uint shareMode, uint creationDisposition) { Logger.LogInformation("Calling {call} Area: {area} for DeviceId: {deviceId}. Desired Access: {desiredAccess}. Share mode: {shareMode}. Creation Disposition: {creationDisposition}", nameof(APICalls.CreateFile), nameof(ApiService), deviceId, desiredAccess, shareMode, creationDisposition); - return APICalls.CreateFile(deviceId, desiredAccess, shareMode, IntPtr.Zero, creationDisposition, FILE_FLAG_OVERLAPPED, IntPtr.Zero); + return CreateFile(deviceId, desiredAccess, shareMode, IntPtr.Zero, creationDisposition, Constants.FILE_FLAG_OVERLAPPED, IntPtr.Zero); } + + /// + /// This will probably get refactored away or the others will + /// + /// + public SafeFileHandle CreateFile(string lpFileName, FileAccessRights dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile) + => APICalls.CreateFile(lpFileName, dwDesiredAccess, dwShareMode, IntPtr.Zero, dwCreationDisposition, dwFlagsAndAttributes, IntPtr.Zero); #endregion #region DLL Imports diff --git a/src/Device.Net/Windows/IApiService.cs b/src/Device.Net/Windows/IApiService.cs index 313eded7..fab87531 100644 --- a/src/Device.Net/Windows/IApiService.cs +++ b/src/Device.Net/Windows/IApiService.cs @@ -8,7 +8,7 @@ namespace Device.Net.Windows { public interface IApiService { - SafeFileHandle CreateFile(string lpFileName, FileAccessRights dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile) + SafeFileHandle CreateFile(string lpFileName, FileAccessRights dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); SafeFileHandle CreateWriteConnection(string deviceId); SafeFileHandle CreateReadConnection(string deviceId, FileAccessRights desiredAccess); //TODO: Get rid of read/write. They can be done with file streams... diff --git a/src/Hid.Net/Windows/WindowsHidHandler.cs b/src/Hid.Net/Windows/WindowsHidHandler.cs index e254eaf5..6e21e796 100644 --- a/src/Hid.Net/Windows/WindowsHidHandler.cs +++ b/src/Hid.Net/Windows/WindowsHidHandler.cs @@ -12,7 +12,7 @@ namespace Hid.Net.Windows { public delegate SafeFileHandle CreateConnection( - IHidApiService apiService, + IApiService apiService, string deviceId, FileAccessRights desiredAccess, uint shareMode, From cf17fd4d5e19348e8ff85b20f60184ea4033d111 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Sat, 21 May 2022 07:52:57 +1000 Subject: [PATCH 5/6] Update README.md --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index c35cd96d..a6f9e551 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,6 @@ **Cross-platform .NET framework for talking to connected devices such as USB, Serial Port and Hid devices** -### [Hire Me](https://christianfindlay.com/hire-me/) - -Don't waste your time with the obscurities of connecting to devices and learning their protocol. I've done this plenty of times and I can fast track you to building an app or getting something to work. - ### Version 4.x is live on [Nuget.org](https://www.nuget.org/packages/Device.Net)! Take a look at the [4.0 project](https://github.com/MelbourneDeveloper/Device.Net/projects/11) to see new features and fixes. Version 4 has public interface changes. You will need to read through the documentation to upgrade from version 3 to version 4. From 9bb7c76e41f23334303fbf47a80005b60692d03d Mon Sep 17 00:00:00 2001 From: Christian Findlay Date: Sat, 9 Jul 2022 19:23:48 +1000 Subject: [PATCH 6/6] ignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 95f6c481..1ca63851 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,5 @@ src/Hid.Net.UWP/Hid.Net.UWP.xml src/Usb.Net.UWP/Usb.Net.UWP.xml src/Usb.Net.Android/Usb.Net.Android.xml + +.DS_Store