melbournedeveloper / device.net Goto Github PK
View Code? Open in Web Editor NEWA C# cross platform connected device framework
License: MIT License
A C# cross platform connected device framework
License: MIT License
This library currently supports direct USB access on Android and UWP. It can also connect to a USB device on Windows if that USB device has a Hid interface. However, in order to communicate with a USB device without Hid, a 3rd party library like LibUsbDotNet must be used.
I'm struggling to find a USB sample for windows that uses the winusb.dll C library. I have documented the problem here. Please comment if you have any tips:
https://stackoverflow.com/questions/53689682/windows-api-usb-io-winusb-dll
I downloaded the sample. but I can't run it on my visual studio. I get error message-
The "ResolveLibraryProjectImports" task failed unexpectedly.System.IO.FileNotFoundException: Could not load assembly 'Device.Net, Version=0.0.0.0, Culture=neutral, PublicKeyToken='. Perhaps it doesn't exist in the Mono for Android profile?File name: 'Device.Net.dll' at Java.Interop.Tools.Cecil.DirectoryAssemblyResolver.Resolve(AssemblyNameReference reference, ReaderParameters parameters) at Java.Interop.Tools.Cecil.DirectoryAssemblyResolver.Resolve(String fullName) at Xamarin.Android.Tasks.ResolveLibraryProjectImports.Extract(DirectoryAssemblyResolver res, ICollection1 jars, ICollection
1 resolvedResourceDirectories, ICollection1 resolvedAssetDirectories, ICollection
1 resolvedEnvironments) at Xamarin.Android.Tasks.ResolveLibraryProjectImports.Execute() at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute() at Microsoft.Build.BackEnd.TaskBuilder.d__26.MoveNext()
I tried a lot of "google" solutions. including rebuild and so on. with no success.
do you have any idea how to run the project?
When the device listener is constructed, it automatically starts polling. This is bad because the user may want to delay the start of the polling. But, also, the event handlers are hooked up after the polling is started. It's probably not possible that an event would fire before the event handlers are first hooked up, but it's at least theoretically possible.
Put a layer over polling for all platforms
-The factories should hang on to a reference of the devices that they have created
-Logic for checking if the device is connected should be disconnected from the device itself (i.e. Android's CheckForDevice)
-The factories should handle disconnection and connection
-When the factory scans for devices is, if an existing device is still connected, this device should be retrieved so as to not create a new one. The question is, what to do if the handle is no longer valid... Connect and disconnect?
On platforms like Windows, polling will occur with a timer. When the timer is called, the factory should check to see if the device is still connected. If not, the device should be disposed which should call the Disconnected event.
On Android, there is no need for a timer because there is an event for when a device is connected or disconnected. This might be possible on Windows and UWP in the long run...
Take this basic example:
using Device.Net;
using Hid.Net.Windows;
using System;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
Test.Find();
Console.ReadLine();
}
}
class Test
{
public static async void Find()
{
WindowsHidDeviceFactory.Register();
var devices = await DeviceManager.Current.GetConnectedDeviceDefinitionsAsync(new FilterDeviceDefinition { VendorId = 0x04D9, ProductId = 0x0130 });
Console.WriteLine("this is never printed to console");
foreach (var device in devices)
{
Console.WriteLine(device.DeviceId);
}
}
}
}
The application hangs before Console.WriteLine("this is never printed to console");
is reached.
Windows 10 x64 with netcore 2.2
It's loading thousands of devices
This problem doesn't seem to happen in the UWP version. The UWP version seems to close the interface handles, but when I attempt to call CloseHandle with the WinUSB handle, I get an error. I suspect this is why a device cannot be opened twice in a row. I suspect that this issue is the same thing: trezor/trezor-mcu#444
Here is a full Stack Overflow discussion:
https://stackoverflow.com/questions/54189056/c-sharp-winusb-cant-call-closehandle-on-interface
This call needs to be rerouted for Mono devices
Calls to GetHidAttributes and so on fail for some devices . This means that there will be an error and no devices will be returned.
This issue is fixed in commit 338132d but has not been rolled out to a NuGet package. It should be included in release 2.3
In WIndowsHIDDevice.cs,Line 180,bytes[0] should be set to the reportID from HID device Out definition.Otherwise,write to device will cause exception"IO operation will not work. Most likely the file will become too long or the handle was not opened to support synchronous IO operations."
Don't hard code these to 64
UWP has an inbuilt device listener. See if this can be harnessed in order to avoid polling
This means sealing off all Pinvokes and only implementing a class that would be safe to expose outside the library.
Don't use the hard coded Hid Guid. Call the method to get the Hid Guid on the machine before enumerating Hid devices.
I have tested my program on my PC and it works fine(except read,Idon't know why my input report won't be picked up via WriteAndReadAsync()),but at least it won't throw an exception.
On my laptop,it will throw a lot of exceptions,after starting the listener.
//exception below
An exception of type 'System.Exception' occurred in test.exe but was not handled in user code
Could not get device interface detail. Error code: 122
//==============
and call stack lead me to WindowsDeviceFactoryBase.cs,line:76
It seems my laptop has some wired hid devices made the SetupDiGetDeviceInterfaceDetail() failed,because the program can‘t listen to the device and initialize device.
Maybe listener should try not to get all hid devices on the computer?I don't know.
Go through TODOs and handle the situations
These need to be specified on UWP or the search will fail. Need to build the query dynamically.
Devices are currently getting initialized, disposed, and then reinitialized. I don't suppose that this is causing any issues right now, but it's not a good look for profilers and so on. Once an object is disposed, it's supposed to get finalized. So, Dispose should be broken in to two methods: Close, and Dispose. Close should be called when the device is unplugged or we temporarily don't want to use the device. Dispose should only be called when the DeviceListener is completely done with the device or the app is shutting down.
This happens in a couple of different libraries including Device.Net.LibUsb
Hello. currently https://www.nuget.org/packages/Device.Net.LibUsb/ misses the 2.6 version, thus it will fail with runtime exceptions, if the version 2.6 of device.net is installed.
The error is always:
TypeLoadException: Method 'Close' in type 'Device.Net.LibUsb.LibUsbDevice' from assembly 'Device.Net.LibUsb, Version=2.5.1.0, Culture=neutral, PublicKeyToken=918542c6e3a3318a' does not have an implementation.
Linux and MacOS are now supported. See this wiki entry. However, this has been done via LibUsbDotNet. I'd like to build libraries that are not dependent on LibUsbDotNet, and possibly not dependent on LibUsb. Contributions on this are very welcome.
The UsbDevice
is a base class that doesn't depends on IUsbInterfaceManager
to inject the platform specifics in. The IUsbInterface
class is where the platform specifics need to be implemented:
public interface IUsbInterface : IDisposable
{
IUsbInterfaceEndpoint ReadEndpoint { get; set; }
IList<IUsbInterfaceEndpoint> UsbInterfaceEndpoints { get; }
IUsbInterfaceEndpoint WriteEndpoint { get; set; }
IUsbInterfaceEndpoint InterruptWriteEndpoint { get; set; }
IUsbInterfaceEndpoint InterruptReadEndpoint { get; set; }
//TODO: Remove these. They should come from the endpoint... or be specified there
ushort ReadBufferSize { get; }
ushort WriteBufferSize { get; }
Task WriteAsync(byte[] data, CancellationToken cancellationToken = default);
Task<ReadResult> ReadAsync(uint bufferLength, CancellationToken cancellationToken = default);
byte InterfaceNumber { get; }
Task ClaimInterface();
/// <summary>
/// This is for internal use and should need to be called. This will probably be removed in future versions.
/// TODO
/// </summary>
void RegisterDefaultEndpoints();
}
The WindowsUsbInterface
is an example of such an interface.
Bare in mind that these interfaces are quite cluttered and need some work, so refactoring is always an option.
The AndroidUsbDevice class is a mess. There is logic there that is mixed up between scanning for devices, receiving events, and polling.
-Implement the factory pattern in other platforms
-Remove any CheckForDevice methods and deal with this in some other way
-This issue is dependent on #3 because polling is necessary on Android
Any given USB device can have multiple different interfaces, and pipes within those interfaces. There should be a way to select which interface is used before InitializeAsync is called.
I am attempting to enumerate an HID device in a UWP app on Win 10 IOT platform. The device is a touchscreen monitor and utilizes the Consumer Usage Page collection. (https://www.chalk-elec.com/?p=2060)
I have added the device capabilities to the Package.appxmanifest, but have been unsuccessfull at enumerating the device, as the output of DeviceManager.Current.GetDevicesAsync method always returns null with no error.
The Official UWP HID API documents the blocking of device usages under the the Consumer Usage Page collection. Does this limitation still apply to this library?
Some methods - particular in the factories are not suffixed with Async
GetConnectedDeviceDefinitions
DeviceManager.Current.GetDevices();
While more of the Dispose pattern has been implemented with Finalizers, the Finalizers don't seem to be getting called for at least some devices. This means that the classes may not be getting garbage collected.
Done:
Classes don't dispose resources on finalize if the dispose method is not called. Need to implement something similar to the dispose pattern correctly.
Make compatible with lower versions of .NET
In some cases they don't get disposed when the listener is dispoed. This means that they don't get finalized. Also, test to make sure that with disposal, they do get finalized.
It is possible to scan through COM ports and listen for data. While I haven't got a need for this, one use case is for GPS devices. Would anyone find this useful? Anyone willing to help? I have code for it already, but I'd just need for it to be integrated in to Device.Net in a useful way.
Allow for a tracer to be passed in to the devices
Currently, Device.Net is designed around the Request/Response model (see here). You are supposed to send some data to the device, and then wait for the device to return some data with WriteAndReadAsync().
However, many devices such as joysticks and so on do not work this way. The input originates from the device itself and could send data to the computer at any point in time. So, there needs to be an event that is registered when data is received. The UWP providers actually work in this way. They receive events when the device sends the computer data. This should be harnessed to achieve the desired functionality.
Perhaps there needs to be two modes for devices: Request/Response, and Ad Hoc...
Multiple locks in this class that aren't properly thread safe. They should also be semaphores.
A library for communication with Linux devices
Allow logger to be passed in with dependency injection
Implement IDevice and IDeviceFactory for LibUsb
This can then be used on MacOS and eventually Linux.
I noticed there are 3 type devices defined in WindowsDeviceConstants.cs
public static Guid GUID_DEVINTERFACE_HID = new Guid("4D1E55B2-F16F-11CF-88CB-001111000030");
public static Guid GUID_DEVINTERFACE_USB_DEVICE = new Guid("A5DCBF10-6530-11D2-901F-00C04FB951ED");
public static Guid WinUSBGuid = new Guid("dee824ef-729b-4a0e-9c14-b7117d33a817");
So, what's the difference between DEVINTERFACE_USB_DEVICE and WinUSB?
Hi. May be will be good if you add CancellationTokenSource or just timeout for read\write operation. Something like this:
//One sec timeout by default
public int Timeout { get; set; } = 1000;
...
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(Timeout);
await _ReadFileStream.ReadAsync(bytes, 0, bytes.Length, cancellationTokenSource.Token);
If a Hid device can't get a serial number, it will not be picked up. This is bug because you can still connect to the device. Serial number is not necessary.
Fix: Don't throw an exception if we can't get serial number.
The messaging is ad hoc across platforms and device types. The messages should be defined in a single location.
Implement a Windows Error code handler in Windows libraries so that we get a textual, meaningful error from the error codes.
It needs to Dispose of connected devices
See #24 but for Android.
This should be possible with Broadcast receivers, but the question is whether or not these trigger activities in external apps...
When the device is initialized, as much of the DeviceDefinition should be filled in as possible.
Need a script (powershell, batch, MSBuild?) to put all the DLLs in the right places.
Implement as many as is reasonable for now.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.