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 diff --git a/README.md b/README.md index 6d83f57c..f58c4ec0 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. diff --git a/src/Device.Net.UnitTests/GetFactoryExtensions.cs b/src/Device.Net.UnitTests/GetFactoryExtensions.cs index db14352f..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; @@ -36,7 +37,16 @@ public static IDeviceFactory GetHidDeviceFactory( => filterDeviceDefinition.CreateWindowsHidDeviceFactory( loggerFactory, readReportTransform: readReportTransform, - writeReportTransform: writeReportTransform); + writeReportTransform: writeReportTransform, + createReadConnection: (apiService, deviceId, fileAccessRights, shareMode, creationDisposition) + => apiService.CreateFile( + deviceId, + FileAccessRights.GenericRead, + shareMode, + IntPtr.Zero, + creationDisposition, + Constants.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/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 45bcb118..fab87531 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/WindowsHidDeviceFactoryExtensions.cs b/src/Hid.Net/Windows/WindowsHidDeviceFactoryExtensions.cs index 1d1a294e..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); } /// @@ -114,6 +126,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 +140,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 +176,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..6e21e796 100644 --- a/src/Hid.Net/Windows/WindowsHidHandler.cs +++ b/src/Hid.Net/Windows/WindowsHidHandler.cs @@ -11,9 +11,15 @@ namespace Hid.Net.Windows { + public delegate SafeFileHandle CreateConnection( + IApiService apiService, + string deviceId, + FileAccessRights desiredAccess, + uint shareMode, + uint creationDisposition); + internal class WindowsHidHandler : IHidDeviceHandler { - #region Private Fields private readonly IHidApiService _hidService; @@ -24,6 +30,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 +44,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 +61,12 @@ public WindowsHidHandler( _hidService = hidApiService ?? new WindowsHidApiService(loggerFactory); WriteBufferSize = writeBufferSize; ReadBufferSize = readBufferSize; + + _createReadConnection = createReadConnection ??= (apiService, deviceId, fileAccessRights, shareMode, creationDisposition) + => apiService.CreateReadConnection(deviceId, fileAccessRights); + + _createWriteConnection = createWriteConnection ??= (apiService, deviceId, fileAccessRights, shareMode, creationDisposition) + => apiService.CreateWriteConnection(deviceId); } #endregion Public Constructors