Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow the consumer to specify the call to CreateConnection #228

Draft
wants to merge 7 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
12 changes: 11 additions & 1 deletion src/Device.Net.UnitTests/GetFactoryExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

using Device.Net.Windows;
using Hid.Net;
using Hid.Net.Windows;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -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));
}
}

4 changes: 0 additions & 4 deletions src/Device.Net/Windows/APICalls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 16 additions & 7 deletions src/Device.Net/Windows/ApiService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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);
}

/// <summary>
/// This will probably get refactored away or the others will
/// </summary>
/// <returns></returns>
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
Expand Down
3 changes: 2 additions & 1 deletion src/Device.Net/Windows/IApiService.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
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

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...
Expand Down
30 changes: 24 additions & 6 deletions src/Hid.Net/Windows/WindowsHidDeviceFactoryExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public static class WindowsHidDeviceFactoryExtensions
/// <param name="readTransferTransform">Exposes the raw data from the device (including Report Id) on reads and allows you to format the returned <see cref="TransferResult"/></param>
/// <param name="writeTransferTransform">Given the Report Id and data supplied for the write, allow you to format the raw data that is sent to the device</param>
/// <param name="writeReportTransform">Given the data supplied, allow you to divide the data in to a <see cref="Report"/></param>
/// <param name="createReadConnection">Allows you to specify the API level call to create the Read handle</param>
/// <param name="createWriteConnection">Allows you to specify the API level call to create the Write handle</param>
/// <returns>A factory which enumerates and instantiates devices</returns>
public static IDeviceFactory CreateWindowsHidDeviceFactory(
ILoggerFactory loggerFactory = null,
Expand All @@ -42,7 +44,9 @@ public static IDeviceFactory CreateWindowsHidDeviceFactory(
Func<Report, TransferResult> readReportTransform = null,
Func<TransferResult, Report> readTransferTransform = null,
Func<byte[], byte, byte[]> writeTransferTransform = null,
WriteReportTransform writeReportTransform = null)
WriteReportTransform writeReportTransform = null,
CreateConnection createReadConnection = null,
CreateConnection createWriteConnection = null)
{
return CreateWindowsHidDeviceFactory(
new ReadOnlyCollection<FilterDeviceDefinition>(new List<FilterDeviceDefinition>()),
Expand All @@ -55,7 +59,9 @@ public static IDeviceFactory CreateWindowsHidDeviceFactory(
readReportTransform,
readTransferTransform,
writeTransferTransform,
writeReportTransform: writeReportTransform);
writeReportTransform: writeReportTransform,
createReadConnection,
createWriteConnection);
}

/// <summary>
Expand All @@ -72,6 +78,8 @@ public static IDeviceFactory CreateWindowsHidDeviceFactory(
/// <param name="readReportTransform">Allows you to manually convert the <see cref="Report"/> in to a <see cref="TransferResult"/> so that the Report Id is not discarded on ReadAsync. By default, this inserts the Report Id at index zero of the array.</param>
/// <param name="readTransferTransform">Exposes the raw data from the device (including Report Id) on reads and allows you to format the returned <see cref="TransferResult"/></param>
/// <param name="writeTransferTransform">Given the Report Id and data supplied for the write, allow you to format the raw data that is sent to the device</param>
/// <param name="createReadConnection">Allows you to specify the API level call to create the Read handle</param>
/// <param name="createWriteConnection">Allows you to specify the API level call to create the Write handle</param>
/// <returns>A factory which enumerates and instantiates devices</returns>
public static IDeviceFactory CreateWindowsHidDeviceFactory(
this FilterDeviceDefinition filterDeviceDefinition,
Expand All @@ -84,7 +92,9 @@ public static IDeviceFactory CreateWindowsHidDeviceFactory(
Func<Report, TransferResult> readReportTransform = null,
Func<TransferResult, Report> readTransferTransform = null,
Func<byte[], byte, byte[]> writeTransferTransform = null,
WriteReportTransform writeReportTransform = null)
WriteReportTransform writeReportTransform = null,
CreateConnection createReadConnection = null,
CreateConnection createWriteConnection = null)
{
return CreateWindowsHidDeviceFactory(
new ReadOnlyCollection<FilterDeviceDefinition>(new List<FilterDeviceDefinition> { filterDeviceDefinition }),
Expand All @@ -97,7 +107,9 @@ public static IDeviceFactory CreateWindowsHidDeviceFactory(
readReportTransform,
readTransferTransform,
writeTransferTransform,
writeReportTransform);
writeReportTransform,
createReadConnection,
createWriteConnection);
}

/// <summary>
Expand All @@ -114,6 +126,8 @@ public static IDeviceFactory CreateWindowsHidDeviceFactory(
/// <param name="readTransferTransform">Exposes the raw data from the device (including Report Id) on reads and allows you to format the returned <see cref="TransferResult"/></param>
/// <param name="writeTransferTransform">Given the Report Id and data supplied for the write, allow you to format the raw data that is sent to the device</param>
/// <param name="writeReportTransform">Given the data supplied, allow you to divide the data in to a <see cref="Report"/></param>
/// <param name="createReadConnection">Allows you to specify the API level call to create the Read handle</param>
/// <param name="createWriteConnection">Allows you to specify the API level call to create the Write handle</param>
/// <returns>A factory which enumerates and instantiates devices</returns>
public static IDeviceFactory CreateWindowsHidDeviceFactory(
this IEnumerable<FilterDeviceDefinition> filterDeviceDefinitions,
Expand All @@ -126,7 +140,9 @@ public static IDeviceFactory CreateWindowsHidDeviceFactory(
Func<Report, TransferResult> readReportTransform = null,
Func<TransferResult, Report> readTransferTransform = null,
Func<byte[], byte, byte[]> writeTransferTransform = null,
WriteReportTransform writeReportTransform = null)
WriteReportTransform writeReportTransform = null,
CreateConnection createReadConnection = null,
CreateConnection createWriteConnection = null)
{
if (filterDeviceDefinitions == null) throw new ArgumentNullException(nameof(filterDeviceDefinitions));

Expand Down Expand Up @@ -160,7 +176,9 @@ public static IDeviceFactory CreateWindowsHidDeviceFactory(
hidApiService,
loggerFactory,
readTransferTransform,
writeTransferTransform),
writeTransferTransform,
createReadConnection,
createWriteConnection),
loggerFactory,
readReportTransform,
writeReportTransform
Expand Down
20 changes: 18 additions & 2 deletions src/Hid.Net/Windows/WindowsHidHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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

Expand All @@ -36,7 +44,9 @@ public WindowsHidHandler(
IHidApiService hidApiService = null,
ILoggerFactory loggerFactory = null,
Func<TransferResult, Report> readTransferTransform = null,
Func<byte[], byte, byte[]> writeTransferTransform = null)
Func<byte[], byte, byte[]> writeTransferTransform = null,
CreateConnection createReadConnection = null,
CreateConnection createWriteConnection = null)
{
_logger = (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger<WindowsHidHandler>();
DeviceId = deviceId ?? throw new ArgumentNullException(nameof(deviceId));
Expand All @@ -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
Expand Down