diff --git a/src/Device.Net - All.sln b/src/Device.Net - All.sln
index 314122a3..a1aeedb4 100644
--- a/src/Device.Net - All.sln
+++ b/src/Device.Net - All.sln
@@ -72,6 +72,8 @@ Global
{8E29E247-78B7-4FC8-AF1C-DA273050978C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8E29E247-78B7-4FC8-AF1C-DA273050978C}.Release|Any CPU.Build.0 = Release|Any CPU
{63695F84-3EC6-4F6A-8C8C-5219D75EDB68}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {63695F84-3EC6-4F6A-8C8C-5219D75EDB68}.Debug|Any CPU.Build.0 = Debug|x86
+ {63695F84-3EC6-4F6A-8C8C-5219D75EDB68}.Debug|Any CPU.Deploy.0 = Debug|x86
{63695F84-3EC6-4F6A-8C8C-5219D75EDB68}.Release|Any CPU.ActiveCfg = Release|x86
{63695F84-3EC6-4F6A-8C8C-5219D75EDB68}.Release|Any CPU.Build.0 = Release|x86
{63695F84-3EC6-4F6A-8C8C-5219D75EDB68}.Release|Any CPU.Deploy.0 = Release|x86
diff --git a/src/Device.Net - All.sln.DotSettings b/src/Device.Net - All.sln.DotSettings
new file mode 100644
index 00000000..3c2eccfe
--- /dev/null
+++ b/src/Device.Net - All.sln.DotSettings
@@ -0,0 +1,5 @@
+
+ True
+ True
+ True
+ True
\ No newline at end of file
diff --git a/src/Device.Net.LibUsb/LibUsbDevice.cs b/src/Device.Net.LibUsb/LibUsbDevice.cs
index ad0c9712..bf43bac7 100644
--- a/src/Device.Net.LibUsb/LibUsbDevice.cs
+++ b/src/Device.Net.LibUsb/LibUsbDevice.cs
@@ -3,19 +3,21 @@
using LibUsbDotNet.Main;
using LibUsbDotNet.WinUsb;
using System;
+using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace Device.Net.LibUsb
{
- public class LibUsbDevice : IDevice
+ public class LibUsbDevice : DeviceBase, IDevice
{
#region Fields
private UsbEndpointReader _UsbEndpointReader;
private UsbEndpointWriter _UsbEndpointWriter;
private int ReadPacketSize;
- private SemaphoreSlim _WriteAndReadLock = new SemaphoreSlim(1, 1);
+ private readonly SemaphoreSlim _WriteAndReadLock = new SemaphoreSlim(1, 1);
private bool disposed;
+ private bool _IsInitialized;
#endregion
#region Public Properties
@@ -23,19 +25,17 @@ public class LibUsbDevice : IDevice
public int VendorId => GetVendorId(UsbDevice);
public int ProductId => GetProductId(UsbDevice);
public int Timeout { get; }
- public bool IsInitialized { get; private set; }
- public ConnectedDeviceDefinitionBase ConnectedDeviceDefinition => throw new NotImplementedException();
- public string DeviceId => UsbDevice.DevicePath;
- public ILogger Logger { get; set; }
- #endregion
-
- #region Events
- public event EventHandler Connected;
- public event EventHandler Disconnected;
+ public override bool IsInitialized => _IsInitialized;
+ public override ushort WriteBufferSize => throw new NotImplementedException();
+ public override ushort ReadBufferSize => throw new NotImplementedException();
#endregion
#region Constructor
- public LibUsbDevice(UsbDevice usbDevice, int timeout)
+ public LibUsbDevice(UsbDevice usbDevice, int timeout) : this(usbDevice, timeout, null, null)
+ {
+ }
+
+ public LibUsbDevice(UsbDevice usbDevice, int timeout, ILogger logger, ITracer tracer) : base(logger, tracer)
{
UsbDevice = usbDevice;
Timeout = timeout;
@@ -48,7 +48,7 @@ public void Close()
UsbDevice?.Close();
}
- public void Dispose()
+ public override void Dispose()
{
if (disposed) return;
disposed = true;
@@ -56,6 +56,10 @@ public void Dispose()
_WriteAndReadLock.Dispose();
Close();
+
+ base.Dispose();
+
+ GC.SuppressFinalize(this);
}
public async Task InitializeAsync()
@@ -86,11 +90,11 @@ public async Task InitializeAsync()
_UsbEndpointReader = UsbDevice.OpenEndpointReader(ReadEndpointID.Ep01);
ReadPacketSize = _UsbEndpointReader.EndpointInfo.Descriptor.MaxPacketSize;
- IsInitialized = true;
+ _IsInitialized = true;
});
}
- public async Task ReadAsync()
+ public override async Task ReadAsync()
{
await _WriteAndReadLock.WaitAsync();
@@ -98,11 +102,13 @@ public async Task ReadAsync()
{
return await Task.Run(() =>
{
- var buffer = new byte[ReadPacketSize];
+ var data = new byte[ReadPacketSize];
+
+ _UsbEndpointReader.Read(data, Timeout, out var bytesRead);
- _UsbEndpointReader.Read(buffer, Timeout, out var bytesRead);
+ Tracer?.Trace(false, data);
- return buffer;
+ return data;
});
}
finally
@@ -111,7 +117,7 @@ public async Task ReadAsync()
}
}
- public async Task WriteAsync(byte[] data)
+ public override async Task WriteAsync(byte[] data)
{
await _WriteAndReadLock.WaitAsync();
@@ -119,7 +125,17 @@ public async Task WriteAsync(byte[] data)
{
await Task.Run(() =>
{
- _UsbEndpointWriter.Write(data, Timeout, out var bytesWritten);
+ var errorCode = _UsbEndpointWriter.Write(data, Timeout, out var bytesWritten);
+ if (errorCode == ErrorCode.Ok || errorCode == ErrorCode.Success)
+ {
+ Tracer?.Trace(true, data);
+ }
+ else
+ {
+ var message = $"Error. Write error code: {errorCode}";
+ Logger?.Log(message, GetType().Name, null, LogLevel.Error);
+ throw new IOException(message);
+ }
});
}
finally
@@ -128,11 +144,6 @@ public async Task WriteAsync(byte[] data)
}
}
- public async Task WriteAndReadAsync(byte[] writeBuffer)
- {
- await WriteAsync(writeBuffer);
- return await ReadAsync();
- }
#endregion
#region Public Static Methods
diff --git a/src/Device.Net.LibUsb/LibUsbDeviceFactoryBase.cs b/src/Device.Net.LibUsb/LibUsbDeviceFactoryBase.cs
index cce9b530..26589a2f 100644
--- a/src/Device.Net.LibUsb/LibUsbDeviceFactoryBase.cs
+++ b/src/Device.Net.LibUsb/LibUsbDeviceFactoryBase.cs
@@ -9,7 +9,8 @@ namespace Device.Net.LibUsb
public abstract class LibUsbDeviceFactoryBase : IDeviceFactory
{
#region Public Properties
- public ILogger Logger { get; set; }
+ public ILogger Logger { get; }
+ public ITracer Tracer { get; }
#endregion
#region Public Abstraction Properties
@@ -23,32 +24,26 @@ public async Task> GetConnectedDeviceDefi
{
IEnumerable devices = UsbDevice.AllDevices;
- if (deviceDefinition != null)
- {
- if (deviceDefinition.VendorId.HasValue)
- {
- devices = devices.Where(d => d.Vid == deviceDefinition.VendorId.Value);
- }
+ if (deviceDefinition == null)
- if (deviceDefinition.VendorId.HasValue)
+ return devices.Select(usbRegistry => new ConnectedDeviceDefinition(usbRegistry.DevicePath)
{
- devices = devices.Where(d => d.Pid == deviceDefinition.ProductId.Value);
- }
- }
+ VendorId = (uint) usbRegistry.Vid,
+ ProductId = (uint) usbRegistry.Pid,
+ DeviceType = DeviceType
+ }).ToList();
- var retVal = new List();
+ if (deviceDefinition.VendorId.HasValue)
+ {
+ devices = devices.Where(d => d.Vid == deviceDefinition.VendorId.Value);
+ }
- foreach (var usbRegistry in devices)
+ if (deviceDefinition.VendorId.HasValue)
{
- retVal.Add(new ConnectedDeviceDefinition(usbRegistry.DevicePath)
- {
- VendorId = (uint)usbRegistry.Vid,
- ProductId = (uint)usbRegistry.Pid,
- DeviceType = DeviceType
- });
+ devices = devices.Where(d => d.Pid == deviceDefinition.ProductId.Value);
}
- return retVal;
+ return devices.Select(usbRegistry => new ConnectedDeviceDefinition(usbRegistry.DevicePath) {VendorId = (uint) usbRegistry.Vid, ProductId = (uint) usbRegistry.Pid, DeviceType = DeviceType}).ToList();
});
}
@@ -56,7 +51,15 @@ public IDevice GetDevice(ConnectedDeviceDefinition deviceDefinition)
{
var usbDeviceFinder = new UsbDeviceFinder((int)deviceDefinition.VendorId.Value, (int)deviceDefinition.ProductId.Value);
var usbDevice = UsbDevice.OpenUsbDevice(usbDeviceFinder);
- return usbDevice != null ? new LibUsbDevice(usbDevice, 3000) { Logger = Logger } : null;
+ return usbDevice != null ? new LibUsbDevice(usbDevice, 3000, Logger, Tracer) : null;
+ }
+ #endregion
+
+ #region Constructor
+ protected LibUsbDeviceFactoryBase(ILogger logger, ITracer tracer)
+ {
+ Logger = logger;
+ Tracer = tracer;
}
#endregion
}
diff --git a/src/Device.Net.LibUsb/LibUsbUsbDeviceFactory.cs b/src/Device.Net.LibUsb/LibUsbUsbDeviceFactory.cs
index 933e5686..2296806d 100644
--- a/src/Device.Net.LibUsb/LibUsbUsbDeviceFactory.cs
+++ b/src/Device.Net.LibUsb/LibUsbUsbDeviceFactory.cs
@@ -2,16 +2,18 @@
{
public class LibUsbUsbDeviceFactory : LibUsbDeviceFactoryBase
{
- public override DeviceType DeviceType => DeviceType.Usb;
-
- public static void Register()
+ public LibUsbUsbDeviceFactory(ILogger logger, ITracer tracer) : base(logger, tracer)
{
- Register(null);
}
- public static void Register(ILogger logger)
+ public override DeviceType DeviceType => DeviceType.Usb;
+
+ ///
+ /// Register the factory for enumerating USB devices.
+ ///
+ public static void Register(ILogger logger, ITracer tracer)
{
- DeviceManager.Current.DeviceFactories.Add(new LibUsbUsbDeviceFactory() { Logger = logger });
+ DeviceManager.Current.DeviceFactories.Add(new LibUsbUsbDeviceFactory(logger, tracer));
}
}
}
diff --git a/src/Device.Net.UWP/Device.Net.UWP.csproj b/src/Device.Net.UWP/Device.Net.UWP.csproj
index 68519f57..6c5bf740 100644
--- a/src/Device.Net.UWP/Device.Net.UWP.csproj
+++ b/src/Device.Net.UWP/Device.Net.UWP.csproj
@@ -27,11 +27,11 @@
DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
prompt
4
- true
+ false
../Device.Net/Device.Net.pfx
- true
+ true
AnyCPU
pdbonly
true
@@ -54,7 +54,7 @@
- 2.6.3
+ 2.9.3
runtime; build; native; contentfiles; analyzers
all
diff --git a/src/Device.Net.UWP/UWPDeviceBase - Generic.cs b/src/Device.Net.UWP/UWPDeviceBase - Generic.cs
index f111e36d..ad8c58d3 100644
--- a/src/Device.Net.UWP/UWPDeviceBase - Generic.cs
+++ b/src/Device.Net.UWP/UWPDeviceBase - Generic.cs
@@ -1,4 +1,5 @@
-using System;
+using Device.Net.Exceptions;
+using System;
using System.Threading.Tasks;
using Windows.Foundation;
@@ -12,16 +13,11 @@ public abstract class UWPDeviceBase : UWPDeviceBase, IDevice
#region Protected Properties
protected T ConnectedDevice { get; private set; }
- protected bool Disposed { get; private set; } = false;
+ protected bool Disposed { get; private set; }
#endregion
#region Constructor
- protected UWPDeviceBase()
- {
-
- }
-
- protected UWPDeviceBase(string deviceId)
+ protected UWPDeviceBase(string deviceId, ILogger logger, ITracer tracer) : base(logger, tracer)
{
DeviceId = deviceId;
}
@@ -45,7 +41,7 @@ public override async Task ReadAsync()
{
if (IsReading)
{
- throw new Exception("Reentry");
+ throw new AsyncException(Messages.ErrorMessageReentry);
}
//TODO: this should be a semaphore not a lock
@@ -53,16 +49,19 @@ public override async Task ReadAsync()
{
if (Chunks.Count > 0)
{
- var retVal = Chunks[0];
- Tracer?.Trace(false, retVal);
+ var data2 = Chunks[0];
+ Logger?.Log("Received data from device", GetType().Name, null, LogLevel.Information);
Chunks.RemoveAt(0);
- return retVal;
+ Tracer?.Trace(false, data2);
+ return data2;
}
}
IsReading = true;
ReadChunkTaskCompletionSource = new TaskCompletionSource();
- return await ReadChunkTaskCompletionSource.Task;
+ var data = await ReadChunkTaskCompletionSource.Task;
+ Tracer?.Trace(false, data);
+ return data;
}
#endregion
diff --git a/src/Device.Net.UWP/UWPDeviceBase.cs b/src/Device.Net.UWP/UWPDeviceBase.cs
index 03f66396..5e3863bb 100644
--- a/src/Device.Net.UWP/UWPDeviceBase.cs
+++ b/src/Device.Net.UWP/UWPDeviceBase.cs
@@ -35,5 +35,11 @@ protected void HandleDataReceived(byte[] bytes)
#region Public Abstract Methods
public abstract Task InitializeAsync();
#endregion
+
+ #region Constructor
+ protected UWPDeviceBase(ILogger logger, ITracer tracer) : base(logger, tracer)
+ {
+ }
+ #endregion
}
}
diff --git a/src/Device.Net.UWP/UWPDeviceFactoryBase.cs b/src/Device.Net.UWP/UWPDeviceFactoryBase.cs
index 46ce9f4e..e883de88 100644
--- a/src/Device.Net.UWP/UWPDeviceFactoryBase.cs
+++ b/src/Device.Net.UWP/UWPDeviceFactoryBase.cs
@@ -23,7 +23,8 @@ public abstract class UWPDeviceFactoryBase
#endregion
#region Public Properties
- public ILogger Logger { get; set; }
+ public ILogger Logger { get; }
+ public ITracer Tracer { get; }
#endregion
#region Public Abstract Properties
@@ -34,6 +35,14 @@ public abstract class UWPDeviceFactoryBase
protected abstract string GetAqsFilter(uint? vendorId, uint? productId);
#endregion
+ #region Constructor
+ protected UWPDeviceFactoryBase(ILogger logger, ITracer tracer)
+ {
+ Logger = logger;
+ Tracer = tracer;
+ }
+ #endregion
+
#region Abstraction Methods
protected string GetVendorPart(uint? vendorId)
{
@@ -101,6 +110,8 @@ public async Task> GetConnectedDeviceDefi
#region Public Static Methods
public static ConnectedDeviceDefinition GetDeviceInformation(wde.DeviceInformation deviceInformation, DeviceType deviceType)
{
+ if (deviceInformation == null) throw new ArgumentNullException(nameof(deviceInformation));
+
var retVal = WindowsDeviceFactoryBase.GetDeviceDefinitionFromWindowsDeviceId(deviceInformation.Id, deviceType);
//foreach (var keyValuePair in deviceInformation.Properties)
diff --git a/src/Device.Net.UnitTests/MockDeviceBase.cs b/src/Device.Net.UnitTests/MockDeviceBase.cs
index e41b4680..4a9a448e 100644
--- a/src/Device.Net.UnitTests/MockDeviceBase.cs
+++ b/src/Device.Net.UnitTests/MockDeviceBase.cs
@@ -11,6 +11,11 @@ public abstract class MockDeviceBase : DeviceBase, IDevice
public override bool IsInitialized => _IsInitialized;
+ protected MockDeviceBase(ILogger logger, ITracer tracer) : base(logger, tracer)
+ {
+
+ }
+
public void Close()
{
}
@@ -23,16 +28,22 @@ public Task InitializeAsync()
private byte[] LastWrittenBuffer;
- public async override Task ReadAsync()
+ public override async Task ReadAsync()
{
- if (LastWrittenBuffer != null) return LastWrittenBuffer;
-
- return await Task.FromResult(new byte[64] { 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
+ if (LastWrittenBuffer != null)
+ {
+ Tracer.Trace(false, LastWrittenBuffer);
+ return LastWrittenBuffer;
+ }
+ var data = new byte[64] { 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ Tracer.Trace(false, data);
+ return await Task.FromResult(data);
}
public override Task WriteAsync(byte[] data)
{
LastWrittenBuffer = data;
+ Tracer.Trace(true, data);
return Task.FromResult(true);
}
}
diff --git a/src/Device.Net.UnitTests/MockFactoryBase.cs b/src/Device.Net.UnitTests/MockFactoryBase.cs
index 47b79f5b..50f677cb 100644
--- a/src/Device.Net.UnitTests/MockFactoryBase.cs
+++ b/src/Device.Net.UnitTests/MockFactoryBase.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Threading.Tasks;
namespace Device.Net.UnitTests
@@ -12,7 +11,14 @@ public abstract class MockFactoryBase : IDeviceFactory
public abstract DeviceType DeviceType { get; }
- public ILogger Logger { get; protected set; }
+ public ILogger Logger { get; }
+ public ITracer Tracer { get; }
+
+ protected MockFactoryBase(ILogger logger, ITracer tracer)
+ {
+ Logger = logger;
+ Tracer = tracer;
+ }
public abstract uint ProductId { get; }
public abstract uint VendorId { get; }
@@ -21,14 +27,19 @@ public Task> GetConnectedDeviceDefinition
{
var result = new List();
- var mockConnectedDeviceDefinition = new ConnectedDeviceDefinition(DeviceId) { ProductId = ProductId, VendorId = VendorId };
+ var mockConnectedDeviceDefinition = new ConnectedDeviceDefinition(DeviceId)
+ {
+ ProductId = ProductId,
+ VendorId = VendorId,
+ DeviceType = this is MockHidFactory ? DeviceType.Hid : DeviceType.Usb
+ };
+
+
+ if (!IsConnected) return Task.FromResult>(result);
- if (IsConnected)
+ if (DeviceManager.IsDefinitionMatch(deviceDefinition, mockConnectedDeviceDefinition))
{
- if (DeviceManager.IsDefinitionMatch(deviceDefinition, mockConnectedDeviceDefinition))
- {
- result.Add(mockConnectedDeviceDefinition);
- }
+ result.Add(mockConnectedDeviceDefinition);
}
return Task.FromResult>(result);
diff --git a/src/Device.Net.UnitTests/MockHidDevice.cs b/src/Device.Net.UnitTests/MockHidDevice.cs
index 0331988f..efdfb8d7 100644
--- a/src/Device.Net.UnitTests/MockHidDevice.cs
+++ b/src/Device.Net.UnitTests/MockHidDevice.cs
@@ -1,16 +1,15 @@
namespace Device.Net.UnitTests
{
- public class MockHidDevice : MockDeviceBase, IDevice
+ public class MockHidDevice : MockDeviceBase
{
public const uint ProductId = 1;
public const uint VendorId = 1;
public const string MockedDeviceId = "123";
- public MockHidDevice()
+ public MockHidDevice(ILogger logger, ITracer tracer) : base(logger, tracer)
{
DeviceId = MockedDeviceId;
- ConnectedDeviceDefinition = new ConnectedDeviceDefinition(DeviceId) { ProductId = ProductId, VendorId = VendorId };
- Logger = new DebugLogger { LogToConsole = true };
+ ConnectedDeviceDefinition = new ConnectedDeviceDefinition(DeviceId) { ProductId = ProductId, VendorId = VendorId, DeviceType = DeviceType.Hid };
}
}
}
diff --git a/src/Device.Net.UnitTests/MockHidFactory.cs b/src/Device.Net.UnitTests/MockHidFactory.cs
index 02438ada..69bacb56 100644
--- a/src/Device.Net.UnitTests/MockHidFactory.cs
+++ b/src/Device.Net.UnitTests/MockHidFactory.cs
@@ -1,12 +1,11 @@
-using System;
-
-namespace Device.Net.UnitTests
+namespace Device.Net.UnitTests
{
- public class MockHidFactory : MockFactoryBase, IDeviceFactory
+ public class MockHidFactory : MockFactoryBase
{
- public MockHidFactory()
+ public const string FoundMessage = "Found device {0}";
+
+ public MockHidFactory(ILogger logger, ITracer tracer) : base(logger, tracer)
{
- Logger = new DebugLogger { LogToConsole = true };
}
public override string DeviceId => MockHidDevice.MockedDeviceId;
@@ -21,22 +20,22 @@ public MockHidFactory()
public override uint VendorId => MockHidDevice.VendorId;
- public static void Register(ILogger logger)
+ public static void Register(ILogger logger, ITracer tracer)
{
- DeviceManager.Current.DeviceFactories.Add(new MockHidFactory() { Logger = logger });
+ DeviceManager.Current.DeviceFactories.Add(new MockHidFactory(logger, tracer));
}
public override IDevice GetDevice(ConnectedDeviceDefinition deviceDefinition)
{
- if (deviceDefinition != null)
- {
- if (deviceDefinition.DeviceId == DeviceId)
- {
- if (!deviceDefinition.DeviceType.HasValue || deviceDefinition.DeviceType == DeviceType.Hid) return new MockHidDevice();
- }
- }
-
- throw new Exception("Couldn't get a device");
+ if (deviceDefinition == null) return null;
+
+ if (deviceDefinition.DeviceId != DeviceId) return null;
+
+ if (deviceDefinition.DeviceType.HasValue && deviceDefinition.DeviceType != DeviceType.Hid) return null;
+
+ Logger?.Log(string.Format(FoundMessage, DeviceId), nameof(MockHidFactory), null, LogLevel.Information);
+
+ return new MockHidDevice(Logger, Tracer);
}
}
}
diff --git a/src/Device.Net.UnitTests/MockLogger.cs b/src/Device.Net.UnitTests/MockLogger.cs
new file mode 100644
index 00000000..7253df34
--- /dev/null
+++ b/src/Device.Net.UnitTests/MockLogger.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Text;
+
+namespace Device.Net.UnitTests
+{
+ internal class MockLogger : ILogger
+ {
+ readonly StringBuilder _stringBuilder = new StringBuilder();
+
+ public string LogText => _stringBuilder.ToString();
+
+ public void Log(string message, string region, Exception ex, LogLevel logLevel)
+ {
+ _stringBuilder.Append(message);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Device.Net.UnitTests/MockTracer.cs b/src/Device.Net.UnitTests/MockTracer.cs
new file mode 100644
index 00000000..ff4e471d
--- /dev/null
+++ b/src/Device.Net.UnitTests/MockTracer.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Device.Net.UnitTests
+{
+ public class MockTracer : ITracer
+ {
+ public int WriteCount { get; private set; }
+ public int ReadCount { get; private set; }
+
+ public void Trace(bool isWrite, byte[] data)
+ {
+ if (data == null) throw new Exception("data must not be null");
+ if (isWrite) WriteCount++;
+ if (!isWrite) ReadCount++;
+ }
+ }
+}
diff --git a/src/Device.Net.UnitTests/MockUsbDevice.cs b/src/Device.Net.UnitTests/MockUsbDevice.cs
index 0623e60c..a95c78fa 100644
--- a/src/Device.Net.UnitTests/MockUsbDevice.cs
+++ b/src/Device.Net.UnitTests/MockUsbDevice.cs
@@ -1,16 +1,15 @@
namespace Device.Net.UnitTests
{
- public class MockUsbDevice : MockDeviceBase, IDevice
+ public class MockUsbDevice : MockDeviceBase
{
public const uint ProductId = 2;
public const uint VendorId = 2;
public const string MockedDeviceId = "321";
- public MockUsbDevice()
+ public MockUsbDevice(ILogger logger, ITracer tracer) : base(logger, tracer)
{
DeviceId = MockedDeviceId;
- ConnectedDeviceDefinition = new ConnectedDeviceDefinition(DeviceId) { ProductId = ProductId, VendorId = VendorId };
- Logger = new DebugLogger { LogToConsole = true };
+ ConnectedDeviceDefinition = new ConnectedDeviceDefinition(DeviceId) { ProductId = ProductId, VendorId = VendorId, DeviceType = DeviceType.Usb };
}
}
}
diff --git a/src/Device.Net.UnitTests/MockUsbFactory.cs b/src/Device.Net.UnitTests/MockUsbFactory.cs
index ffec9a99..9286f12a 100644
--- a/src/Device.Net.UnitTests/MockUsbFactory.cs
+++ b/src/Device.Net.UnitTests/MockUsbFactory.cs
@@ -2,11 +2,10 @@
namespace Device.Net.UnitTests
{
- public class MockUsbFactory : MockFactoryBase, IDeviceFactory
+ public class MockUsbFactory : MockFactoryBase
{
- public MockUsbFactory()
+ public MockUsbFactory(ILogger logger, ITracer tracer) : base(logger, tracer)
{
- Logger = new DebugLogger { LogToConsole = true };
}
public override string DeviceId => MockUsbDevice.MockedDeviceId;
@@ -21,22 +20,24 @@ public MockUsbFactory()
public override uint VendorId => MockUsbDevice.VendorId;
- public static void Register(ILogger logger)
+ public const string FoundMessage = "Found device {0}";
+
+ public static void Register(ILogger logger, ITracer tracer)
{
- DeviceManager.Current.DeviceFactories.Add(new MockUsbFactory() { Logger = logger });
+ DeviceManager.Current.DeviceFactories.Add(new MockUsbFactory(logger, tracer));
}
public override IDevice GetDevice(ConnectedDeviceDefinition deviceDefinition)
{
- if (deviceDefinition != null)
- {
- if (deviceDefinition.DeviceId == DeviceId)
- {
- if (!deviceDefinition.DeviceType.HasValue || deviceDefinition.DeviceType == DeviceType.Usb) return new MockUsbDevice() ;
- }
- }
-
- throw new Exception("Couldn't get a device");
+ if (deviceDefinition == null) throw new Exception("Couldn't get a device");
+
+ if (deviceDefinition.DeviceId != DeviceId) throw new Exception("Couldn't get a device");
+
+ if (deviceDefinition.DeviceType.HasValue && deviceDefinition.DeviceType != DeviceType.Usb) throw new Exception("Couldn't get a device");
+
+ Logger?.Log(string.Format(FoundMessage, DeviceId), nameof(MockUsbFactory), null, LogLevel.Information);
+
+ return new MockUsbDevice(Logger, Tracer);
}
}
}
diff --git a/src/Device.Net.UnitTests/UnitTests.cs b/src/Device.Net.UnitTests/UnitTests.cs
index bf29560a..7fc2b249 100644
--- a/src/Device.Net.UnitTests/UnitTests.cs
+++ b/src/Device.Net.UnitTests/UnitTests.cs
@@ -1,3 +1,4 @@
+using Device.Net.Exceptions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
@@ -10,12 +11,15 @@ namespace Device.Net.UnitTests
[TestClass]
public class UnitTests
{
+ private static readonly MockLogger logger = new MockLogger();
+ private static readonly MockTracer tracer = new MockTracer();
+
#region Tests
[TestInitialize]
public void Startup()
{
- MockHidFactory.Register(null);
- MockUsbFactory.Register(null);
+ MockHidFactory.Register(logger, tracer);
+ MockUsbFactory.Register(logger, tracer);
}
[TestMethod]
@@ -33,6 +37,25 @@ public async Task TestWithMatchedFilterAsync(bool isHidConnected, bool isUsbConn
MockHidFactory.IsConnectedStatic = isHidConnected;
MockUsbFactory.IsConnectedStatic = isUsbConnected;
var connectedDeviceDefinitions = (await DeviceManager.Current.GetConnectedDeviceDefinitionsAsync(new FilterDeviceDefinition { ProductId = pid, VendorId = vid })).ToList();
+
+ if (connectedDeviceDefinitions.Count > 0)
+ {
+ foreach (var connectedDeviceDefinition in connectedDeviceDefinitions)
+ {
+ var device = DeviceManager.Current.GetDevice(connectedDeviceDefinition);
+
+ if (device != null && connectedDeviceDefinition.DeviceType == DeviceType.Hid)
+ {
+ Assert.IsTrue(logger.LogText.Contains(string.Format(MockHidFactory.FoundMessage, connectedDeviceDefinition.DeviceId)));
+ }
+
+ if (device != null && connectedDeviceDefinition.DeviceType == DeviceType.Usb)
+ {
+ Assert.IsTrue(logger.LogText.Contains(string.Format(MockUsbFactory.FoundMessage, connectedDeviceDefinition.DeviceId)));
+ }
+ }
+ }
+
Assert.IsNotNull(connectedDeviceDefinitions);
Assert.AreEqual(expectedCount, connectedDeviceDefinitions.Count);
}
@@ -40,20 +63,25 @@ public async Task TestWithMatchedFilterAsync(bool isHidConnected, bool isUsbConn
[TestMethod]
[DataRow(true, true, MockHidDevice.VendorId, MockHidDevice.ProductId)]
[DataRow(true, false, MockHidDevice.VendorId, MockHidDevice.ProductId)]
- //[DataRow(true, true, MockUsbDevice.VendorId, MockUsbDevice.ProductId)]
- //[DataRow(false, true, MockUsbDevice.VendorId, MockUsbDevice.ProductId)]
public async Task TestWriteAndReadThreadSafety(bool isHidConnected, bool isUsbConnected, uint vid, uint pid)
{
+ var readtraceCount = tracer.ReadCount;
+ var writetraceCount = tracer.WriteCount;
+
MockHidFactory.IsConnectedStatic = isHidConnected;
MockUsbFactory.IsConnectedStatic = isUsbConnected;
var connectedDeviceDefinition = (await DeviceManager.Current.GetConnectedDeviceDefinitionsAsync(new FilterDeviceDefinition { ProductId = pid, VendorId = vid })).ToList().First();
- var mockHidDevice = new MockHidDevice() { DeviceId = connectedDeviceDefinition.DeviceId };
+
+
+ var mockHidDevice = new MockHidDevice(logger, tracer) { DeviceId = connectedDeviceDefinition.DeviceId };
var writeAndReadTasks = new List>();
//TODO: Does this properly test thread safety?
- for (byte i = 0; i < 10; i++)
+ const int count = 10;
+
+ for (byte i = 0; i < count; i++)
{
writeAndReadTasks.Add(mockHidDevice.WriteAndReadAsync(new byte[64] { i, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }));
}
@@ -65,6 +93,11 @@ public async Task TestWriteAndReadThreadSafety(bool isHidConnected, bool isUsbCo
var result = results[i];
Assert.IsTrue(result[0] == i);
}
+
+ Assert.AreEqual(readtraceCount + count, tracer.ReadCount);
+ Assert.AreEqual(writetraceCount + count, tracer.WriteCount);
+
+ Assert.IsTrue(logger.LogText.Contains(Messages.SuccessMessageWriteAndReadCalled));
}
[TestMethod]
@@ -120,7 +153,7 @@ public async Task TestDeviceFactoriesNotRegisteredException()
try
{
- var connectedDevices = await DeviceManager.Current.GetConnectedDeviceDefinitionsAsync(null);
+ await DeviceManager.Current.GetConnectedDeviceDefinitionsAsync(null);
}
catch (DeviceFactoriesNotRegisteredException)
{
diff --git a/src/Device.Net/BulkIOService.cs b/src/Device.Net/BulkIOService.cs
new file mode 100644
index 00000000..d97b86f8
--- /dev/null
+++ b/src/Device.Net/BulkIOService.cs
@@ -0,0 +1,99 @@
+using Device.Net.Exceptions;
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Device.Net
+{
+ ///
+ /// Wraps a device and allows it to be used like a stream
+ ///
+ public class BulkIOService
+ {
+ #region Public Properties
+ public IDevice Device { get; }
+ public int ReadBufferSize { get; }
+ #endregion
+
+ #region Constructor
+ public BulkIOService(IDevice device, int readBufferSize)
+ {
+ Device = device;
+ ReadBufferSize = readBufferSize;
+ }
+ #endregion
+
+ #region Public Methods
+ public async Task ReadAsync(byte[] buff, int offset, int len)
+ {
+ if (buff == null) throw new ArgumentNullException(nameof(buff));
+
+ if (buff.Length - offset < len)
+ {
+ throw new ValidationException("Index out of bounds");
+ }
+
+ var totalRead = 0;
+
+ while (totalRead < len)
+ {
+ // Getting some data.
+ var data = await Device.ReadAsync();
+
+ if (data.Length > len - totalRead)
+ {
+ // Out of bounds.
+ // Cut the overflowing result.
+ data = data.Take(len - totalRead).ToArray();
+ }
+
+ // Copying buffer.
+ for (var i = 0; i < data.Length; ++i)
+ {
+ buff[totalRead + offset] = data[i];
+ ++totalRead;
+ }
+
+ if (data.Length < ReadBufferSize)
+ {
+ // Last buffer.
+ break;
+ }
+ }
+
+ return totalRead;
+ }
+
+ public async Task WriteAsync(byte[] data, int offset, int len)
+ {
+ if (data == null) throw new ArgumentNullException(nameof(data));
+
+ // Some checking.
+ if (data.Length - offset < len)
+ {
+ throw new ValidationException("Index out of bounds");
+ }
+
+ // Determining buffer size.
+ byte[] writeBuff;
+
+ if (offset == 0 && len == data.Length)
+ {
+ writeBuff = data;
+ }
+ else
+ {
+ writeBuff = new byte[len];
+
+ // Copying buffer.
+ for (var i = 0; i < len; ++i)
+ {
+ writeBuff[i] = data[offset + i];
+ }
+ }
+
+ await Device.WriteAsync(writeBuff);
+ }
+ #endregion
+ }
+}
diff --git a/src/Device.Net/CodeRules.ruleset b/src/Device.Net/CodeRules.ruleset
index 348f6ffc..4a74e7af 100644
--- a/src/Device.Net/CodeRules.ruleset
+++ b/src/Device.Net/CodeRules.ruleset
@@ -20,6 +20,7 @@
+
@@ -33,7 +34,7 @@
-
+
@@ -60,14 +61,16 @@
+
+
-
+
@@ -75,6 +78,7 @@
+
@@ -102,6 +106,7 @@
+
@@ -130,6 +135,7 @@
+
@@ -191,6 +197,7 @@
+
@@ -223,6 +230,7 @@
+
@@ -858,7 +866,7 @@
-
+
@@ -1156,7 +1164,6 @@
-
@@ -1167,7 +1174,6 @@
-
@@ -1184,7 +1190,6 @@
-
@@ -1234,7 +1239,6 @@
-
@@ -1275,7 +1279,7 @@
-
+
diff --git a/src/Device.Net/DebugTracer.cs b/src/Device.Net/DebugTracer.cs
index 0f8f242d..82604ba6 100644
--- a/src/Device.Net/DebugTracer.cs
+++ b/src/Device.Net/DebugTracer.cs
@@ -6,7 +6,9 @@ public class DebugTracer : ITracer
{
public void Trace(bool isWrite, byte[] data)
{
- Debug.WriteLine($"({string.Join(",", data)}) - {(isWrite ? "Write" : "Read")} ({data.Length})");
+ if (data == null) return;
+
+ Debug.WriteLine($"{(isWrite ? "Write" : "Read")}: ({string.Join(",", data)}) ({data.Length})");
}
}
}
diff --git a/src/Device.Net/Device.Net.csproj b/src/Device.Net/Device.Net.csproj
index 3251c1d6..0c9f2633 100644
--- a/src/Device.Net/Device.Net.csproj
+++ b/src/Device.Net/Device.Net.csproj
@@ -15,7 +15,7 @@
https://github.com/MelbourneDeveloper/Device.Net
Hid USB Android UWP Windows C# MacOS Linux
NU5125
- true
+ false
CodeRules.ruleset
@@ -39,7 +39,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers
diff --git a/src/Device.Net/DeviceBase.cs b/src/Device.Net/DeviceBase.cs
index 7876bf6d..681cfa23 100644
--- a/src/Device.Net/DeviceBase.cs
+++ b/src/Device.Net/DeviceBase.cs
@@ -8,8 +8,8 @@ namespace Device.Net
public abstract class DeviceBase : IDisposable
{
#region Fields
- private SemaphoreSlim _WriteAndReadLock = new SemaphoreSlim(1, 1);
- private bool disposed = false;
+ private readonly SemaphoreSlim _WriteAndReadLock = new SemaphoreSlim(1, 1);
+ private bool disposed;
public const string DeviceDisposedErrorMessage = "This device has already been disposed";
private string _LogRegion;
#endregion
@@ -21,10 +21,18 @@ public abstract class DeviceBase : IDisposable
#endregion
#region Public Properties
- public ITracer Tracer { get; set; }
public ConnectedDeviceDefinitionBase ConnectedDeviceDefinition { get; set; }
public string DeviceId { get; set; }
- public ILogger Logger { get; set; }
+ public ILogger Logger { get; }
+ public ITracer Tracer { get; }
+ #endregion
+
+ #region Constructor
+ protected DeviceBase(ILogger logger, ITracer tracer)
+ {
+ Tracer = tracer;
+ Logger = logger;
+ }
#endregion
#region Private Methods
@@ -75,12 +83,12 @@ public async Task WriteAndReadAsync(byte[] writeBuffer)
{
await WriteAsync(writeBuffer);
var retVal = await ReadAsync();
- Log($"Successfully called {nameof(WriteAndReadAsync)}");
+ Log(Messages.SuccessMessageWriteAndReadCalled);
return retVal;
}
catch (Exception ex)
{
- Log("Read/Write Error", ex);
+ Log(Messages.ErrorMessageReadWrite, ex);
throw;
}
finally
@@ -94,6 +102,8 @@ public async Task WriteAndReadAsync(byte[] writeBuffer)
///
public static byte[] RemoveFirstByte(byte[] bytes)
{
+ if (bytes == null) throw new ArgumentNullException(nameof(bytes));
+
var length = bytes.Length - 1;
var retVal = new byte[length];
diff --git a/src/Device.Net/DeviceFactoriesNotRegisteredException.cs b/src/Device.Net/DeviceFactoriesNotRegisteredException.cs
deleted file mode 100644
index d89e683b..00000000
--- a/src/Device.Net/DeviceFactoriesNotRegisteredException.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System;
-
-namespace Device.Net
-{
-#pragma warning disable CA2229
-#pragma warning disable CA1032
- public class DeviceFactoriesNotRegisteredException : Exception
-#pragma warning restore CA1032
-#pragma warning restore CA2229
- {
- public DeviceFactoriesNotRegisteredException() : base("No device factories have been registered")
- {
- }
- }
-}
\ No newline at end of file
diff --git a/src/Device.Net/DeviceListener.cs b/src/Device.Net/DeviceListener.cs
index 30c0eb3d..fe2e026a 100644
--- a/src/Device.Net/DeviceListener.cs
+++ b/src/Device.Net/DeviceListener.cs
@@ -1,4 +1,5 @@
-using System;
+using Device.Net.Exceptions;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
@@ -72,7 +73,7 @@ public void Start()
{
if (_PollTimer == null)
{
- throw new Exception("Polling is not enabled. Please specify pollMilliseconds in the constructor");
+ throw new ValidationException(Messages.ErrorMessagePollingNotEnabled);
}
if (DeviceManager.Current.DeviceFactories.Count == 0) throw new DeviceFactoriesNotRegisteredException();
@@ -124,7 +125,7 @@ public async Task CheckForDevicesAsync()
//Let listeners know a registered device was initialized
DeviceInitialized?.Invoke(this, new DeviceEventArgs(device));
- Log("Device connected", null);
+ Log(Messages.InformationMessageDeviceConnected, null);
}
}
@@ -149,7 +150,7 @@ public async Task CheckForDevicesAsync()
removeDefs.Add(filteredDeviceDefinitionKey);
- Log("Disconnected", null);
+ Log(Messages.InformationMessageDeviceListenerDisconnected, null);
}
}
}
@@ -159,12 +160,12 @@ public async Task CheckForDevicesAsync()
_CreatedDevicesByDefinition.Remove(removeDef);
}
- Log("Poll complete", null);
+ Log(Messages.InformationMessageDeviceListenerPollingComplete, null);
}
catch (Exception ex)
{
- Log("Hid polling error", ex);
+ Log(Messages.ErrorMessagePollingError, ex);
//TODO: What else to do here?
}
@@ -186,6 +187,8 @@ public void Dispose()
Stop();
+ _PollTimer?.Dispose();
+
foreach (var key in _CreatedDevicesByDefinition.Keys)
{
_CreatedDevicesByDefinition[key].Dispose();
diff --git a/src/Device.Net/DeviceManager.cs b/src/Device.Net/DeviceManager.cs
index f64d7c99..736ebfc2 100644
--- a/src/Device.Net/DeviceManager.cs
+++ b/src/Device.Net/DeviceManager.cs
@@ -1,4 +1,6 @@
-using System.Collections.Generic;
+using Device.Net.Exceptions;
+using System;
+using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
@@ -40,17 +42,21 @@ public async Task> GetConnectedDeviceDefi
//TODO: Duplicate code here...
public IDevice GetDevice(ConnectedDeviceDefinition connectedDeviceDefinition)
{
+ if (connectedDeviceDefinition == null) throw new ArgumentNullException(nameof(connectedDeviceDefinition));
+
foreach (var deviceFactory in DeviceFactories)
{
if (connectedDeviceDefinition.DeviceType.HasValue && (deviceFactory.DeviceType != connectedDeviceDefinition.DeviceType)) continue;
return deviceFactory.GetDevice(connectedDeviceDefinition);
}
- throw new System.Exception("Couldn't get a device");
+ throw new DeviceException(Messages.ErrorMessageCouldntGetDevice);
}
public async Task> GetDevicesAsync(IList deviceDefinitions)
{
+ if (deviceDefinitions == null) throw new ArgumentNullException(nameof(deviceDefinitions), $"{nameof(GetConnectedDeviceDefinitionsAsync)} can be used to enumerate all devices without specifying definitions.");
+
var retVal = new List();
foreach (var deviceFactory in DeviceFactories)
@@ -81,6 +87,8 @@ public async Task> GetDevicesAsync(IList d
#region Public Static Methods
public static bool IsDefinitionMatch(FilterDeviceDefinition filterDevice, ConnectedDeviceDefinition actualDevice)
{
+ if (actualDevice == null) throw new ArgumentNullException(nameof(actualDevice));
+
if (filterDevice == null) return true;
var vendorIdPasses = !filterDevice.VendorId.HasValue || filterDevice.VendorId == actualDevice.VendorId;
diff --git a/src/Device.Net/Exceptions/ApiException.cs b/src/Device.Net/Exceptions/ApiException.cs
new file mode 100644
index 00000000..d249eecf
--- /dev/null
+++ b/src/Device.Net/Exceptions/ApiException.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace Device.Net.Exceptions
+{
+ public class ApiException : Exception
+ {
+ public ApiException()
+ {
+ }
+
+ public ApiException(string message) : base(message)
+ {
+ }
+
+ public ApiException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+
+ protected ApiException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Device.Net/Exceptions/AsyncException.cs b/src/Device.Net/Exceptions/AsyncException.cs
new file mode 100644
index 00000000..1b428001
--- /dev/null
+++ b/src/Device.Net/Exceptions/AsyncException.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace Device.Net.Exceptions
+{
+ public class AsyncException : Exception
+ {
+ public AsyncException(string message) : base(message)
+ {
+ }
+
+ public AsyncException()
+ {
+ }
+
+ public AsyncException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Device.Net/DeviceException.cs b/src/Device.Net/Exceptions/DeviceException.cs
similarity index 91%
rename from src/Device.Net/DeviceException.cs
rename to src/Device.Net/Exceptions/DeviceException.cs
index 2e77e5fe..89cb1cbb 100644
--- a/src/Device.Net/DeviceException.cs
+++ b/src/Device.Net/Exceptions/DeviceException.cs
@@ -1,6 +1,6 @@
using System;
-namespace Device.Net
+namespace Device.Net.Exceptions
{
public class DeviceException : Exception
{
diff --git a/src/Device.Net/Exceptions/DeviceFactoriesNotRegisteredException.cs b/src/Device.Net/Exceptions/DeviceFactoriesNotRegisteredException.cs
new file mode 100644
index 00000000..9d0743af
--- /dev/null
+++ b/src/Device.Net/Exceptions/DeviceFactoriesNotRegisteredException.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace Device.Net.Exceptions
+{
+ public class DeviceFactoriesNotRegisteredException : Exception
+ {
+ public DeviceFactoriesNotRegisteredException() : base(Messages.ErrorMessageNoDeviceFactoriesRegistered)
+ {
+ }
+
+ public DeviceFactoriesNotRegisteredException(string message) : base(message)
+ {
+ }
+
+ public DeviceFactoriesNotRegisteredException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Device.Net/NotInitializedException.cs b/src/Device.Net/Exceptions/NotInitializedException.cs
similarity index 94%
rename from src/Device.Net/NotInitializedException.cs
rename to src/Device.Net/Exceptions/NotInitializedException.cs
index d2e244f1..ca023c03 100644
--- a/src/Device.Net/NotInitializedException.cs
+++ b/src/Device.Net/Exceptions/NotInitializedException.cs
@@ -1,7 +1,7 @@
using System;
using System.Runtime.Serialization;
-namespace Device.Net
+namespace Device.Net.Windows
{
public class NotInitializedException : Exception
{
diff --git a/src/Device.Net/Exceptions/ValidationException.cs b/src/Device.Net/Exceptions/ValidationException.cs
new file mode 100644
index 00000000..727ff61b
--- /dev/null
+++ b/src/Device.Net/Exceptions/ValidationException.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace Device.Net.Exceptions
+{
+ public class ValidationException : Exception
+ {
+ public ValidationException()
+ {
+ }
+
+ public ValidationException(string message) : base(message)
+ {
+ }
+
+ public ValidationException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+
+ protected ValidationException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Device.Net/Messages.cs b/src/Device.Net/Messages.cs
new file mode 100644
index 00000000..067ab851
--- /dev/null
+++ b/src/Device.Net/Messages.cs
@@ -0,0 +1,40 @@
+namespace Device.Net
+{
+ public static class Messages
+ {
+ #region Device Initialization
+ public const string ErrorMessageNotInitialized = "The device has not been initialized.";
+ public const string ErrorMessageCouldntIntializeDevice = "Couldn't initialize device";
+ public const string ErrorMessageCantOpenWrite = "Could not open connection for writing";
+ public const string ErrorMessageCantOpenRead = "Could not open connection for reading";
+ #endregion
+
+ #region Misc
+ public const string ErrorMessageReentry = "Reentry. This method is not thread safe";
+ public static string SuccessMessageWriteAndReadCalled => $"Successfully called {nameof(DeviceBase.WriteAndReadAsync)}";
+ #endregion
+
+ #region IO
+ public static string GetErrorMessageInvalidWriteLength(int length, uint count)
+ {
+ return $"Write failure. {length} bytes were sent to the device but it claims that {count} were sent.";
+ }
+
+ public const string ErrorMessageReadWrite = "Read/Write Error";
+ #endregion
+
+ #region Polling
+ public const string InformationMessageDeviceListenerPollingComplete = "Poll complete";
+ public const string InformationMessageDeviceListenerDisconnected = "Disconnected";
+ public const string ErrorMessagePollingError = "Hid polling error";
+ public const string InformationMessageDeviceConnected = "Device connected";
+ public const string ErrorMessagePollingNotEnabled = "Polling is not enabled. Please specify pollMilliseconds in the constructor";
+ #endregion
+
+ #region Factories
+ public const string ErrorMessageNoDeviceFactoriesRegistered = "No device factories have been registered";
+ public const string ErrorMessageCouldntGetDevice = "Couldn't get a device";
+ #endregion
+
+ }
+}
diff --git a/src/Device.Net/Windows/APICalls.cs b/src/Device.Net/Windows/APICalls.cs
index 92bbf3ca..904bfb87 100644
--- a/src/Device.Net/Windows/APICalls.cs
+++ b/src/Device.Net/Windows/APICalls.cs
@@ -1,9 +1,8 @@
-using Device.Net.Windows;
-using System;
-using Microsoft.Win32.SafeHandles;
+using System;
using System.Runtime.InteropServices;
+using Microsoft.Win32.SafeHandles;
-namespace Device.Net
+namespace Device.Net.Windows
{
public static class APICalls
{
diff --git a/src/Device.Net/Windows/WindowsDeviceBase.cs b/src/Device.Net/Windows/WindowsDeviceBase.cs
index 3947b7f5..f021acb5 100644
--- a/src/Device.Net/Windows/WindowsDeviceBase.cs
+++ b/src/Device.Net/Windows/WindowsDeviceBase.cs
@@ -1,4 +1,4 @@
-using System;
+using Device.Net.Exceptions;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
@@ -14,7 +14,7 @@ public abstract class WindowsDeviceBase : DeviceBase
#endregion
#region Constructor
- protected WindowsDeviceBase(string deviceId)
+ protected WindowsDeviceBase(string deviceId, ILogger logger, ITracer tracer) : base(logger, tracer)
{
DeviceId = deviceId;
}
@@ -33,7 +33,7 @@ public static void HandleError(bool isSuccess, string message)
//TODO: Loggin
if (errorCode == 0) return;
- throw new Exception($"{message}. Error code: {errorCode}");
+ throw new ApiException($"{message}. Error code: {errorCode}");
}
#endregion
}
diff --git a/src/Device.Net/Windows/WindowsDeviceFactoryBase.cs b/src/Device.Net/Windows/WindowsDeviceFactoryBase.cs
index 93fcde8c..08933d38 100644
--- a/src/Device.Net/Windows/WindowsDeviceFactoryBase.cs
+++ b/src/Device.Net/Windows/WindowsDeviceFactoryBase.cs
@@ -14,8 +14,8 @@ namespace Device.Net.Windows
public abstract class WindowsDeviceFactoryBase
{
#region Public Properties
- public ILogger Logger { get; set; }
- public ITracer Tracer { get; set; }
+ public ILogger Logger { get; }
+ public ITracer Tracer { get; }
#endregion
#region Public Abstract Properties
@@ -27,6 +27,14 @@ public abstract class WindowsDeviceFactoryBase
protected abstract Guid GetClassGuid();
#endregion
+ #region Constructor
+ protected WindowsDeviceFactoryBase(ILogger logger, ITracer tracer)
+ {
+ Logger = logger;
+ Tracer = tracer;
+ }
+ #endregion
+
#region Public Methods
public async Task> GetConnectedDeviceDefinitionsAsync(FilterDeviceDefinition filterDeviceDefinition)
{
@@ -147,6 +155,8 @@ protected void Log(string message, string region, Exception ex, LogLevel logLeve
#region Private Static Methods
private static uint GetNumberFromDeviceId(string deviceId, string searchString)
{
+ if (deviceId == null) throw new ArgumentNullException(nameof(deviceId));
+
var indexOfSearchString = deviceId.IndexOf(searchString, StringComparison.OrdinalIgnoreCase);
string hexString = null;
if (indexOfSearchString > -1)
@@ -168,10 +178,8 @@ public static ConnectedDeviceDefinition GetDeviceDefinitionFromWindowsDeviceId(s
vid = GetNumberFromDeviceId(deviceId, "vid_");
pid = GetNumberFromDeviceId(deviceId, "pid_");
}
- catch (Exception)
+ catch
{
- //TODO: Logging
- //We really need the Vid/Pid here for polling etc. so not sure if swallowing errors it the way to go
}
return new ConnectedDeviceDefinition(deviceId) { DeviceType = deviceType, VendorId = vid, ProductId = pid };
diff --git a/src/Device.Net/Windows/WindowsException.cs b/src/Device.Net/Windows/WindowsException.cs
deleted file mode 100644
index 458c209c..00000000
--- a/src/Device.Net/Windows/WindowsException.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System;
-
-namespace Device.Net.Windows
-{
- public class WindowsException : Exception
- {
- public WindowsException(string message) : base(message)
- {
-
- }
-
- public WindowsException()
- {
- }
-
- public WindowsException(string message, Exception innerException) : base(message, innerException)
- {
- }
- }
-}
diff --git a/src/Hid.Net.UWP/Hid.Net.UWP.csproj b/src/Hid.Net.UWP/Hid.Net.UWP.csproj
index 32049279..85851fe3 100644
--- a/src/Hid.Net.UWP/Hid.Net.UWP.csproj
+++ b/src/Hid.Net.UWP/Hid.Net.UWP.csproj
@@ -17,9 +17,9 @@
512
{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
../Device.Net/CodeRules.ruleset
- true
- 7.3
- PackageReference
+ false
+ 7.3
+ PackageReference
AnyCPU
@@ -38,16 +38,16 @@
TRACE;NETFX_CORE;WINDOWS_UWP
prompt
true
- ../Device.Net/Device.Net.pfx
+ ../Device.Net/Device.Net.pfx
-
+
- 2.6.3
+ 2.9.3
runtime; build; native; contentfiles; analyzers
all
diff --git a/src/Hid.Net.UWP/Properties/AssemblyInfo.cs b/src/Hid.Net.UWP/Properties/AssemblyInfo.cs
index 08be974c..08b8c98a 100644
--- a/src/Hid.Net.UWP/Properties/AssemblyInfo.cs
+++ b/src/Hid.Net.UWP/Properties/AssemblyInfo.cs
@@ -9,7 +9,7 @@
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Hid.Net.UWP")]
-[assembly: AssemblyCopyright("Copyright © Christian Findlay 2018")]
+[assembly: AssemblyCopyright("Copyright © Christian Findlay 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
diff --git a/src/Hid.Net.UWP/UWPHidDevice.cs b/src/Hid.Net.UWP/UWPHidDevice.cs
index 21d67df1..135ad776 100644
--- a/src/Hid.Net.UWP/UWPHidDevice.cs
+++ b/src/Hid.Net.UWP/UWPHidDevice.cs
@@ -1,5 +1,8 @@
-using Device.Net.UWP;
+using Device.Net;
+using Device.Net.Exceptions;
+using Device.Net.UWP;
using System;
+using System.IO;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Devices.HumanInterfaceDevice;
@@ -34,11 +37,15 @@ private void _HidDevice_InputReportReceived(HidDevice sender, HidInputReportRece
#endregion
#region Constructors
- public UWPHidDevice()
+ public UWPHidDevice(ILogger logger, ITracer tracer) : this(null, logger, tracer)
{
}
- public UWPHidDevice(string deviceId) : base(deviceId)
+ public UWPHidDevice(string deviceId) : this(deviceId, null, null)
+ {
+ }
+
+ public UWPHidDevice(string deviceId, ILogger logger, ITracer tracer) : base(deviceId, logger, tracer)
{
}
#endregion
@@ -48,7 +55,7 @@ public override async Task InitializeAsync()
{
//TODO: Put a lock here to stop reentrancy of multiple calls
- if (Disposed) throw new Exception(DeviceDisposedErrorMessage);
+ if (Disposed) throw new ValidationException(DeviceDisposedErrorMessage);
Log("Initializing Hid device", null);
@@ -60,7 +67,7 @@ public override async Task InitializeAsync()
}
else
{
- throw new Exception($"The device {DeviceId} failed to initialize");
+ throw new DeviceException($"The device {DeviceId} failed to initialize");
}
}
@@ -92,6 +99,8 @@ public override Task WriteAsync(byte[] data)
public async Task WriteReportAsync(byte[] data, byte? reportId)
{
+ if (data == null) throw new ArgumentNullException(nameof(data));
+
byte[] bytes;
if (DataHasExtraByte)
{
@@ -111,19 +120,30 @@ public async Task WriteReportAsync(byte[] data, byte? reportId)
try
{
var operation = ConnectedDevice.SendOutputReportAsync(outReport);
- await operation.AsTask();
- Tracer?.Trace(false, bytes);
+ var count = await operation.AsTask();
+ if (count == bytes.Length)
+ {
+ Tracer?.Trace(true, bytes);
+ }
+ else
+ {
+ var message = Messages.GetErrorMessageInvalidWriteLength(bytes.Length, count);
+ Logger?.Log(message, GetType().Name, null, LogLevel.Error);
+ throw new IOException(message);
+ }
}
catch (ArgumentException ex)
{
//TODO: Check the string is nasty. Validation on the size of the array being sent should be done earlier anyway
if (string.Equals(ex.Message, "Value does not fall within the expected range.", StringComparison.Ordinal))
{
- throw new Exception("It seems that the data being sent to the device does not match the accepted size. Have you checked DataHasExtraByte?", ex);
+ throw new IOException("It seems that the data being sent to the device does not match the accepted size. Have you checked DataHasExtraByte?", ex);
}
throw;
}
}
+
+
#endregion
#region Public Overrides
@@ -143,7 +163,9 @@ public async Task ReadReportAsync()
public override async Task ReadAsync()
{
- return (await ReadReportAsync()).Data;
+ var data = (await ReadReportAsync()).Data;
+ Tracer?.Trace(false, data);
+ return data;
}
#endregion
diff --git a/src/Hid.Net.UWP/UWPHidDeviceFactory.cs b/src/Hid.Net.UWP/UWPHidDeviceFactory.cs
index c4ac8c29..8c05bf2b 100644
--- a/src/Hid.Net.UWP/UWPHidDeviceFactory.cs
+++ b/src/Hid.Net.UWP/UWPHidDeviceFactory.cs
@@ -11,7 +11,7 @@ public sealed class UWPHidDeviceFactory : UWPDeviceFactoryBase, IDeviceFactory,
{
#region Fields
private readonly SemaphoreSlim _TestConnectionSemaphore = new SemaphoreSlim(1, 1);
- private Dictionary _ConnectionTestedDeviceIds = new Dictionary();
+ private readonly Dictionary _ConnectionTestedDeviceIds = new Dictionary();
private bool disposed;
#endregion
@@ -64,10 +64,19 @@ public override async Task TestConnection(string deviceId)
}
#endregion
+ #region Constructor
+ public UWPHidDeviceFactory(ILogger logger, ITracer tracer) : base(logger, tracer)
+ {
+
+ }
+ #endregion
+
#region Public Methods
public IDevice GetDevice(ConnectedDeviceDefinition deviceDefinition)
{
- return deviceDefinition.DeviceType == DeviceType.Usb ? null : new UWPHidDevice(deviceDefinition.DeviceId) { Logger = Logger };
+ if (deviceDefinition == null) throw new ArgumentNullException(nameof(deviceDefinition));
+
+ return deviceDefinition.DeviceType == DeviceType.Usb ? null : new UWPHidDevice(deviceDefinition.DeviceId, Logger, Tracer);
}
public void Dispose()
@@ -82,19 +91,17 @@ public void Dispose()
#endregion
#region Public Static Methods
- public static void Register()
- {
- Register(null);
- }
-
- public static void Register(ILogger logger)
+ ///
+ /// Register the factory for enumerating Hid devices on UWP.
+ ///
+ public static void Register(ILogger logger, ITracer tracer)
{
foreach (var deviceFactory in DeviceManager.Current.DeviceFactories)
{
if (deviceFactory is UWPHidDeviceFactory) return;
}
- DeviceManager.Current.DeviceFactories.Add(new UWPHidDeviceFactory() { Logger = logger });
+ DeviceManager.Current.DeviceFactories.Add(new UWPHidDeviceFactory(logger, tracer));
}
#endregion
diff --git a/src/Hid.Net/Hid.Net.csproj b/src/Hid.Net/Hid.Net.csproj
index 36f34ff9..1df08c2d 100644
--- a/src/Hid.Net/Hid.Net.csproj
+++ b/src/Hid.Net/Hid.Net.csproj
@@ -20,7 +20,7 @@ Supports .NET, Android, and UWP out of the box. Other platforms can be addedChristian Findlay
https://github.com/MelbourneDeveloper/Device.Net
Hid.Net
- true
+ false
../Device.Net/CodeRules.ruleset
1701;1702;NU5125
@@ -50,7 +50,7 @@ Supports .NET, Android, and UWP out of the box. Other platforms can be added
-
+
all
runtime; build; native; contentfiles; analyzers
diff --git a/src/Hid.Net/Windows/HidAPICalls.cs b/src/Hid.Net/Windows/HidAPICalls.cs
index 52eba999..6e353e09 100644
--- a/src/Hid.Net/Windows/HidAPICalls.cs
+++ b/src/Hid.Net/Windows/HidAPICalls.cs
@@ -1,4 +1,5 @@
-using Device.Net.Windows;
+using Device.Net.Exceptions;
+using Device.Net.Windows;
using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.InteropServices;
@@ -72,7 +73,7 @@ public static HidCollectionCapabilities GetHidCapabilities(SafeFileHandle readSa
var result = HidP_GetCaps(pointerToPreParsedData, out var hidCollectionCapabilities);
if (result != HIDP_STATUS_SUCCESS)
{
- throw new Exception($"Could not get Hid capabilities. Return code: {result}");
+ throw new ApiException($"Could not get Hid capabilities. Return code: {result}");
}
isSuccess = HidD_FreePreparsedData(ref pointerToPreParsedData);
diff --git a/src/Hid.Net/Windows/WindowsHIDDevice.cs b/src/Hid.Net/Windows/WindowsHIDDevice.cs
index 4c4c57ca..22930396 100644
--- a/src/Hid.Net/Windows/WindowsHIDDevice.cs
+++ b/src/Hid.Net/Windows/WindowsHIDDevice.cs
@@ -1,4 +1,5 @@
using Device.Net;
+using Device.Net.Exceptions;
using Device.Net.Windows;
using Microsoft.Win32.SafeHandles;
using System;
@@ -16,7 +17,7 @@ public sealed class WindowsHidDevice : WindowsDeviceBase, IHidDevice
private SafeFileHandle _ReadSafeFileHandle;
private SafeFileHandle _WriteSafeFileHandle;
private bool _IsClosing;
- private bool disposed = false;
+ private bool disposed;
private readonly ushort? _WriteBufferSize;
private readonly ushort? _ReadBufferSize;
@@ -41,11 +42,15 @@ public sealed class WindowsHidDevice : WindowsDeviceBase, IHidDevice
#endregion
#region Constructor
- public WindowsHidDevice(string deviceId) : this(deviceId, null, null)
+ public WindowsHidDevice(string deviceId) : this(deviceId, null, null, null, null)
{
}
- public WindowsHidDevice(string deviceId, ushort? writeBufferSize, ushort? readBufferSize) : base(deviceId)
+ public WindowsHidDevice(string deviceId, ILogger logger, ITracer tracer) : this(deviceId, null, null, logger, tracer)
+ {
+ }
+
+ public WindowsHidDevice(string deviceId, ushort? writeBufferSize, ushort? readBufferSize, ILogger logger, ITracer tracer) : base(deviceId, logger, tracer)
{
_WriteBufferSize = writeBufferSize;
_ReadBufferSize = readBufferSize;
@@ -61,7 +66,7 @@ private bool Initialize()
if (string.IsNullOrEmpty(DeviceId))
{
- throw new WindowsHidException($"{nameof(DeviceId)} must be specified before {nameof(Initialize)} can be called.");
+ throw new ValidationException($"{nameof(DeviceId)} must be specified before {nameof(Initialize)} can be called.");
}
_ReadSafeFileHandle = APICalls.CreateFile(DeviceId, APICalls.GenericRead | APICalls.GenericWrite, APICalls.FileShareRead | APICalls.FileShareWrite, IntPtr.Zero, APICalls.OpenExisting, 0, IntPtr.Zero);
@@ -69,12 +74,12 @@ private bool Initialize()
if (_ReadSafeFileHandle.IsInvalid)
{
- throw new Exception("Could not open connection for reading");
+ throw new ApiException(Messages.ErrorMessageCantOpenRead);
}
if (_WriteSafeFileHandle.IsInvalid)
{
- throw new Exception("Could not open connection for writing");
+ throw new ApiException(Messages.ErrorMessageCantOpenWrite);
}
ConnectedDeviceDefinition = WindowsHidDeviceFactory.GetDeviceDefinition(DeviceId, _ReadSafeFileHandle);
@@ -84,12 +89,12 @@ private bool Initialize()
if (readBufferSize == 0)
{
- throw new WindowsHidException($"{nameof(ReadBufferSize)} must be specified. HidD_GetAttributes may have failed or returned an InputReportByteLength of 0. Please specify this argument in the constructor");
+ throw new ValidationException($"{nameof(ReadBufferSize)} must be specified. HidD_GetAttributes may have failed or returned an InputReportByteLength of 0. Please specify this argument in the constructor");
}
if (writeBufferSize == 0)
{
- throw new WindowsHidException($"{nameof(WriteBufferSize)} must be specified. HidD_GetAttributes may have failed or returned an OutputReportByteLength of 0. Please specify this argument in the constructor. Note: Hid devices are always opened in write mode. If you need to open in read mode, please log an issue here: https://github.com/MelbourneDeveloper/Device.Net/issues");
+ throw new ValidationException($"{nameof(WriteBufferSize)} must be specified. HidD_GetAttributes may have failed or returned an OutputReportByteLength of 0. Please specify this argument in the constructor. Note: Hid devices are always opened in write mode. If you need to open in read mode, please log an issue here: https://github.com/MelbourneDeveloper/Device.Net/issues");
}
_ReadFileStream = new FileStream(_ReadSafeFileHandle, FileAccess.ReadWrite, readBufferSize, false);
@@ -155,14 +160,16 @@ public override void Dispose()
public override async Task InitializeAsync()
{
- if (disposed) throw new Exception(DeviceDisposedErrorMessage);
+ if (disposed) throw new ValidationException(DeviceDisposedErrorMessage);
await Task.Run(() => Initialize());
}
public override async Task ReadAsync()
{
- return (await ReadReportAsync()).Data;
+ var data = (await ReadReportAsync()).Data;
+ Tracer?.Trace(false, data);
+ return data;
}
public async Task ReadReportAsync()
@@ -171,7 +178,7 @@ public async Task ReadReportAsync()
if (_ReadFileStream == null)
{
- throw new Exception("The device has not been initialized");
+ throw new NotInitializedException("The device has not been initialized");
}
var bytes = new byte[ReadBufferSize];
@@ -190,8 +197,6 @@ public async Task ReadReportAsync()
var retVal = ReadBufferHasReportId ? RemoveFirstByte(bytes) : bytes;
- Tracer?.Trace(false, retVal);
-
return new ReadReport(reportId, retVal);
}
@@ -202,14 +207,16 @@ public override Task WriteAsync(byte[] data)
public async Task WriteReportAsync(byte[] data, byte? reportId)
{
+ if (data == null) throw new ArgumentNullException(nameof(data));
+
if (_WriteFileStream == null)
{
- throw new Exception("The device has not been initialized");
+ throw new NotInitializedException("The device has not been initialized");
}
if (data.Length > WriteBufferSize)
{
- throw new Exception($"Data is longer than {WriteBufferSize - 1} bytes which is the device's OutputReportByteLength.");
+ throw new ValidationException($"Data is longer than {WriteBufferSize - 1} bytes which is the device's OutputReportByteLength.");
}
byte[] bytes;
@@ -234,14 +241,13 @@ public async Task WriteReportAsync(byte[] data, byte? reportId)
try
{
await _WriteFileStream.WriteAsync(bytes, 0, bytes.Length);
+ Tracer?.Trace(true, bytes);
}
catch (Exception ex)
{
Log(Helpers.WriteErrorMessage, ex);
throw new IOException(Helpers.WriteErrorMessage, ex);
}
-
- Tracer?.Trace(true, bytes);
}
else
{
diff --git a/src/Hid.Net/Windows/WindowsHidDeviceFactory.cs b/src/Hid.Net/Windows/WindowsHidDeviceFactory.cs
index b856148c..26511b46 100644
--- a/src/Hid.Net/Windows/WindowsHidDeviceFactory.cs
+++ b/src/Hid.Net/Windows/WindowsHidDeviceFactory.cs
@@ -36,10 +36,19 @@ protected override Guid GetClassGuid()
#endregion
+ #region Constructor
+ public WindowsHidDeviceFactory(ILogger logger, ITracer tracer) : base(logger, tracer)
+ {
+
+ }
+ #endregion
+
#region Public Methods
public IDevice GetDevice(ConnectedDeviceDefinition deviceDefinition)
{
- return deviceDefinition.DeviceType != DeviceType ? null : new WindowsHidDevice(deviceDefinition.DeviceId) { Logger = Logger };
+ if (deviceDefinition == null) throw new ArgumentNullException(nameof(deviceDefinition));
+
+ return deviceDefinition.DeviceType != DeviceType ? null : new WindowsHidDevice(deviceDefinition.DeviceId, Logger, Tracer);
}
#endregion
@@ -70,14 +79,12 @@ public static ConnectedDeviceDefinition GetDeviceDefinition(string deviceId, Saf
#endregion
#region Public Static Methods
- public static void Register()
- {
- Register(null);
- }
-
- public static void Register(ILogger logger)
+ ///
+ /// Register the factory for enumerating Hid devices on UWP.
+ ///
+ public static void Register(ILogger logger, ITracer tracer)
{
- DeviceManager.Current.DeviceFactories.Add(new WindowsHidDeviceFactory() { Logger = logger });
+ DeviceManager.Current.DeviceFactories.Add(new WindowsHidDeviceFactory(logger, tracer));
}
#endregion
}
diff --git a/src/Hid.Net/Windows/WindowsHidException.cs b/src/Hid.Net/Windows/WindowsHidException.cs
deleted file mode 100644
index 44eff5a7..00000000
--- a/src/Hid.Net/Windows/WindowsHidException.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System;
-
-namespace Hid.Net.Windows
-{
- public class WindowsHidException : Exception
- {
- public WindowsHidException(string message) : base(message)
- {
-
- }
-
- public WindowsHidException()
- {
- }
-
- public WindowsHidException(string message, Exception innerException) : base(message, innerException)
- {
- }
- }
-}
diff --git a/src/Usb.Net.Android/AndroidUsbDevice.cs b/src/Usb.Net.Android/AndroidUsbDevice.cs
index 511d2673..bc2db736 100644
--- a/src/Usb.Net.Android/AndroidUsbDevice.cs
+++ b/src/Usb.Net.Android/AndroidUsbDevice.cs
@@ -1,11 +1,10 @@
-using Usb.Net;
-using Usb.Net.Android;
+using Device.Net;
-namespace Device.Net
+namespace Usb.Net.Android
{
- public class AndroidUsbDevice : UsbDevice, IUsbDevice
+ public class AndroidUsbDevice : UsbDevice
{
- public AndroidUsbDevice(AndroidUsbDeviceHandler androidUsbDeviceHandler) : base(androidUsbDeviceHandler)
+ public AndroidUsbDevice(AndroidUsbDeviceHandler androidUsbDeviceHandler, ILogger logger, ITracer tracer) : base(androidUsbDeviceHandler, logger, tracer)
{
}
}
diff --git a/src/Usb.Net.Android/AndroidUsbDeviceFactory.cs b/src/Usb.Net.Android/AndroidUsbDeviceFactory.cs
index f6b8444d..aef5a7f3 100644
--- a/src/Usb.Net.Android/AndroidUsbDeviceFactory.cs
+++ b/src/Usb.Net.Android/AndroidUsbDeviceFactory.cs
@@ -1,12 +1,12 @@
-using Android.Content;
-using Android.Hardware.Usb;
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
-using Usb.Net.Android;
+using Android.Content;
+using Android.Hardware.Usb;
+using Device.Net;
-namespace Device.Net
+namespace Usb.Net.Android
{
///
/// TODO: Merge this factory class with other factory classes
@@ -16,8 +16,8 @@ public class AndroidUsbDeviceFactory : IDeviceFactory
#region Public Properties
public UsbManager UsbManager { get; }
public Context Context { get; }
- public ILogger Logger { get; set; }
- public ITracer Tracer { get; set; }
+ public ILogger Logger { get; }
+ public ITracer Tracer { get; }
public ushort? ReadBufferSize { get; set; }
public ushort? WriteBufferSize { get; set; }
#endregion
@@ -27,10 +27,12 @@ public class AndroidUsbDeviceFactory : IDeviceFactory
#endregion
#region Constructor
- public AndroidUsbDeviceFactory(UsbManager usbManager, Context context)
+ public AndroidUsbDeviceFactory(UsbManager usbManager, Context context, ILogger logger, ITracer tracer)
{
UsbManager = usbManager;
Context = context;
+ Logger = logger;
+ Tracer = tracer;
}
#endregion
@@ -63,12 +65,12 @@ public IDevice GetDevice(ConnectedDeviceDefinition deviceDefinition)
throw new Exception($"The device Id '{deviceDefinition.DeviceId}' is not a valid integer");
}
- return new AndroidUsbDevice(new AndroidUsbDeviceHandler(UsbManager, Context, deviceId, Logger, Tracer, ReadBufferSize, WriteBufferSize));
+ return new AndroidUsbDevice(new AndroidUsbDeviceHandler(UsbManager, Context, deviceId, Logger, Tracer, ReadBufferSize, WriteBufferSize), Logger, Tracer);
}
#endregion
#region Public Static Methods
- public static ConnectedDeviceDefinition GetAndroidDeviceDefinition(UsbDevice usbDevice)
+ public static ConnectedDeviceDefinition GetAndroidDeviceDefinition(global::Android.Hardware.Usb.UsbDevice usbDevice)
{
var deviceId = usbDevice.DeviceId.ToString(Helpers.ParsingCulture);
@@ -83,14 +85,12 @@ public static ConnectedDeviceDefinition GetAndroidDeviceDefinition(UsbDevice usb
};
}
- public static void Register(UsbManager usbManager, Context context)
- {
- Register(usbManager, context, null);
- }
-
- public static void Register(UsbManager usbManager, Context context, ILogger logger)
+ ///
+ /// Register the factory for enumerating USB devices on Android.
+ ///
+ public static void Register(UsbManager usbManager, Context context, ILogger logger, ITracer tracer)
{
- DeviceManager.Current.DeviceFactories.Add(new AndroidUsbDeviceFactory(usbManager, context) { Logger = logger });
+ DeviceManager.Current.DeviceFactories.Add(new AndroidUsbDeviceFactory(usbManager, context, logger, tracer));
}
#endregion
}
diff --git a/src/Usb.Net.Android/AndroidUsbDeviceHandler.cs b/src/Usb.Net.Android/AndroidUsbDeviceHandler.cs
index c6192898..b12eb134 100644
--- a/src/Usb.Net.Android/AndroidUsbDeviceHandler.cs
+++ b/src/Usb.Net.Android/AndroidUsbDeviceHandler.cs
@@ -15,7 +15,7 @@ public class AndroidUsbDeviceHandler : UsbDeviceHandlerBase, IUsbDeviceHandler
#region Fields
private UsbDeviceConnection _UsbDeviceConnection;
private usbDevice _UsbDevice;
- private SemaphoreSlim _InitializingSemaphoreSlim = new SemaphoreSlim(1, 1);
+ private readonly SemaphoreSlim _InitializingSemaphoreSlim = new SemaphoreSlim(1, 1);
private bool _IsClosing;
private bool disposed;
#endregion
@@ -35,16 +35,15 @@ public class AndroidUsbDeviceHandler : UsbDeviceHandlerBase, IUsbDeviceHandler
#region Constructor
public AndroidUsbDeviceHandler(UsbManager usbManager, Context androidContext, int deviceNumberId, ILogger logger, ITracer tracer, ushort? readBufferLength, ushort? writeBufferLength) : base(logger, tracer, readBufferLength, writeBufferLength)
{
- DeviceNumberId = deviceNumberId;
- UsbManager = usbManager;
- AndroidContext = androidContext;
+ UsbManager = usbManager ?? throw new ArgumentNullException(nameof(usbManager));
+ AndroidContext = androidContext ?? throw new ArgumentNullException(nameof(androidContext));
DeviceNumberId = deviceNumberId;
}
#endregion
#region Public Methods
- public void Dispose()
+ public override void Dispose()
{
if (disposed) return;
disposed = true;
@@ -53,6 +52,8 @@ public void Dispose()
_InitializingSemaphoreSlim.Dispose();
+ base.Dispose();
+
GC.SuppressFinalize(this);
}
@@ -81,13 +82,11 @@ public void Close()
_IsClosing = false;
}
- //TODO: Make async properly
public Task ReadAsync()
{
return ReadUsbInterface.ReadAsync(ReadBufferSize);
}
- //TODO: Perhaps we should implement Batch Begin/Complete so that the UsbRequest is not created again and again. This will be expensive
public Task WriteAsync(byte[] data)
{
return WriteUsbInterface.WriteAsync(data);
@@ -154,7 +153,7 @@ public async Task InitializeAsync()
//TODO: This is the default interface but other interfaces might be needed so this needs to be changed.
var usbInterface = _UsbDevice.GetInterface(x);
- var androidUsbInterface = new AndroidUsbInterface(usbInterface, _UsbDeviceConnection, Logger, Tracer, _ReadBufferSize, _WriteBufferSize);
+ var androidUsbInterface = new AndroidUsbInterface(usbInterface, _UsbDeviceConnection, Logger, Tracer);
UsbInterfaces.Add(androidUsbInterface);
for (var y = 0; y < usbInterface.EndpointCount; y++)
@@ -240,6 +239,9 @@ public Task GetConnectedDeviceDefinitionAsync()
#endregion
#region Finalizer
+ ///
+ /// What's this then?
+ ///
~AndroidUsbDeviceHandler()
{
Dispose();
diff --git a/src/Usb.Net.Android/AndroidUsbInterface.cs b/src/Usb.Net.Android/AndroidUsbInterface.cs
index 3bd48289..5701dfdb 100644
--- a/src/Usb.Net.Android/AndroidUsbInterface.cs
+++ b/src/Usb.Net.Android/AndroidUsbInterface.cs
@@ -9,20 +9,21 @@ namespace Usb.Net.Android
{
internal class AndroidUsbInterface : UsbInterfaceBase, IUsbInterface
{
+ #region Fields
+ private bool disposed;
private readonly UsbInterface _UsbInterface;
private readonly UsbDeviceConnection _UsbDeviceConnection;
+ #endregion
- public AndroidUsbInterface(UsbInterface usbInterface, UsbDeviceConnection usbDeviceConnection, ILogger logger, ITracer tracer, ushort? readBufferSize, ushort? writeBufferSize) : base(logger, tracer,readBufferSize, writeBufferSize )
+ #region Constructor
+ public AndroidUsbInterface(UsbInterface usbInterface, UsbDeviceConnection usbDeviceConnection, ILogger logger, ITracer tracer) : base(logger, tracer )
{
- _UsbInterface = usbInterface;
- _UsbDeviceConnection = usbDeviceConnection;
- }
-
- public void Dispose()
- {
- throw new NotImplementedException();
+ _UsbInterface = usbInterface ?? throw new ArgumentNullException(nameof(usbInterface));
+ _UsbDeviceConnection = usbDeviceConnection ?? throw new ArgumentNullException(nameof(usbDeviceConnection));
}
+ #endregion
+ #region Public Methods
public async Task ReadAsync(uint bufferLength)
{
return await Task.Run(async () =>
@@ -72,7 +73,9 @@ public async Task WriteAsync(byte[] data)
{
try
{
- var request = new UsbRequest();
+ //TODO: Perhaps we should implement Batch Begin/Complete so that the UsbRequest is not created again and again. This will be expensive
+
+ var request = new UsbRequest();
var endpoint = ((AndroidUsbEndpoint)WriteEndpoint).UsbEndpoint;
request.Initialize(_UsbDeviceConnection, endpoint);
var byteBuffer = ByteBuffer.Wrap(data);
@@ -91,5 +94,15 @@ public async Task WriteAsync(byte[] data)
}
});
}
+
+ public void Dispose()
+ {
+ if (disposed) return;
+ disposed = true;
+
+ _UsbInterface.Dispose();
+ _UsbDeviceConnection.Dispose();
+ }
+ #endregion
}
}
\ No newline at end of file
diff --git a/src/Usb.Net.Android/Usb.Net.Android.csproj b/src/Usb.Net.Android/Usb.Net.Android.csproj
index b8faa00d..5ee295c0 100644
--- a/src/Usb.Net.Android/Usb.Net.Android.csproj
+++ b/src/Usb.Net.Android/Usb.Net.Android.csproj
@@ -1,10 +1,11 @@
-
+
+
+
+
+
-
-
-
Debug
AnyCPU
@@ -32,7 +33,7 @@
DEBUG;TRACE
prompt
4
- true
+ false
pdbonly
@@ -77,13 +78,7 @@
-
-
-
-
-
-
-
+
@@ -92,11 +87,12 @@
This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
-
+
+
+
+
+