Используя .Net(С#), как вы можете работать с USB-устройствами?
Как вы можете обнаружить события USB (соединения/разъединения) и как вы общаетесь с устройствами (чтение/запись).
Есть ли для этого встроенное .NET решение?
Используя .Net(С#), как вы можете работать с USB-устройствами?
Как вы можете обнаружить события USB (соединения/разъединения) и как вы общаетесь с устройствами (чтение/запись).
Есть ли для этого встроенное .NET решение?
Для этого нет встроенного (например, системных библиотек). Это причина, по которой SharpUSBLib существует, как упоминалось moobaa.
Если вы хотите перевернуть свой собственный обработчик для USB-устройств, вы можете проверить класс SerialPort System.IO.Ports.
Я пробовал использовать SharpUSBLib, и он прикрутил мой компьютер (требуется восстановление системы). Случилось также с коллегой по тому же проекту.
Я нашел альтернативу в LibUSBDotNet: http://sourceforge.net/projects/libusbdotnet Havn't использовал его много, но кажется хорошим и недавно обновленным (в отличие от Sharp).
EDIT: По состоянию на середину февраля 2017 года LibUSBDotNet обновлялась около 2 недель назад. Тем временем SharpUSBLib не обновлялся с 2004 года.
Я использовал следующий код для определения того, когда USB-устройства были подключены и отсоединены от моего компьютера:
class USBControl : IDisposable
{
// used for monitoring plugging and unplugging of USB devices.
private ManagementEventWatcher watcherAttach;
private ManagementEventWatcher watcherRemove;
public USBControl()
{
// Add USB plugged event watching
watcherAttach = new ManagementEventWatcher();
//var queryAttach = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2");
watcherAttach.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
watcherAttach.Query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2");
watcherAttach.Start();
// Add USB unplugged event watching
watcherRemove = new ManagementEventWatcher();
//var queryRemove = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 3");
watcherRemove.EventArrived += new EventArrivedEventHandler(watcher_EventRemoved);
watcherRemove.Query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 3");
watcherRemove.Start();
}
/// <summary>
/// Used to dispose of the USB device watchers when the USBControl class is disposed of.
/// </summary>
public void Dispose()
{
watcherAttach.Stop();
watcherRemove.Stop();
//Thread.Sleep(1000);
watcherAttach.Dispose();
watcherRemove.Dispose();
//Thread.Sleep(1000);
}
void watcher_EventArrived(object sender, EventArrivedEventArgs e)
{
Debug.WriteLine("watcher_EventArrived");
}
void watcher_EventRemoved(object sender, EventArrivedEventArgs e)
{
Debug.WriteLine("watcher_EventRemoved");
}
~USBControl()
{
this.Dispose();
}
}
Вы должны убедиться, что вы вызываете метод Dispose() при закрытии приложения. В противном случае вы будете получать ошибку COM-объекта во время выполнения при закрытии.
Я бы рекомендовал LibUSBDotNet библиотеку, которую я использовал в течение 2 лет. Если вам нужно работать с USB-устройством (отправлять запросы, обрабатывать ответы), эта библиотека была лучшим решением, которое я мог найти.
Плюсы:
Минусы:
Здесь есть учебное пособие по сбору библиотеки SharpUSBLib и HID с С#:
http://www.developerfusion.com/article/84338/making-usb-c-friendly/
Существует общий набор инструментов WinDriver для записи драйверов USB в пользовательском режиме, которые также поддерживают #.NET
Если на вашем ПК установлено программное обеспечение National Instruments, вы можете создать драйвер USB с помощью "мастера драйверов NI-VISA".
Шаги по созданию драйвера USB: http://www.ni.com/tutorial/4478/en/
После создания драйвера вы сможете записывать и читать байты на любое USB-устройство.
Убедитесь, что драйвер находится в окне Диспетчера устройств:
Код С#:
using NationalInstruments.VisaNS;
#region UsbRaw
/// <summary>
/// Class to communicate with USB Devices using the UsbRaw Class of National Instruments
/// </summary>
public class UsbRaw
{
private NationalInstruments.VisaNS.UsbRaw usbRaw;
private List<byte> DataReceived = new List<byte>();
/// <summary>
/// Initialize the USB Device to interact with
/// </summary>
/// <param name="ResourseName">In this format: "USB0::0x1448::0x8CA0::NI-VISA-30004::RAW". Use the NI-VISA Driver Wizard from Start»All Programs»National Instruments»VISA»Driver Wizard to create the USB Driver for the device you need to talk to.</param>
public UsbRaw(string ResourseName)
{
usbRaw = new NationalInstruments.VisaNS.UsbRaw(ResourseName, AccessModes.NoLock, 10000, false);
usbRaw.UsbInterrupt += new UsbRawInterruptEventHandler(OnUSBInterrupt);
usbRaw.EnableEvent(UsbRawEventType.UsbInterrupt, EventMechanism.Handler);
}
/// <summary>
/// Clears a USB Device from any previous commands
/// </summary>
public void Clear()
{
usbRaw.Clear();
}
/// <summary>
/// Writes Bytes to the USB Device
/// </summary>
/// <param name="EndPoint">USB Bulk Out Pipe attribute to send the data to. For example: If you see on the Bus Hound sniffer tool that data is coming out from something like 28.4 (Device column), this means that the USB is using Endpoint 4 (Number after the dot)</param>
/// <param name="BytesToSend">Data to send to the USB device</param>
public void Write(short EndPoint, byte[] BytesToSend)
{
usbRaw.BulkOutPipe = EndPoint;
usbRaw.Write(BytesToSend); // Write to USB
}
/// <summary>
/// Reads bytes from a USB Device
/// </summary>
/// <returns>Bytes Read</returns>
public byte[] Read()
{
usbRaw.ReadByteArray(); // This fires the UsbRawInterruptEventHandler
byte[] rxBytes = DataReceived.ToArray(); // Collects the data received
return rxBytes;
}
/// <summary>
/// This is used to get the data received by the USB device
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnUSBInterrupt(object sender, UsbRawInterruptEventArgs e)
{
try
{
DataReceived.Clear(); // Clear previous data received
DataReceived.AddRange(e.DataBuffer);
}
catch (Exception exp)
{
string errorMsg = "Error: " + exp.Message;
DataReceived.AddRange(ASCIIEncoding.ASCII.GetBytes(errorMsg));
}
}
/// <summary>
/// Use this function to clean up the UsbRaw class
/// </summary>
public void Dispose()
{
usbRaw.DisableEvent(UsbRawEventType.UsbInterrupt, EventMechanism.Handler);
if (usbRaw != null)
{
usbRaw.Dispose();
}
}
}
#endregion UsbRaw
Использование:
UsbRaw usbRaw = new UsbRaw("USB0::0x1448::0x8CA0::NI-VISA-30004::RAW");
byte[] sendData = new byte[] { 0x53, 0x4c, 0x56 };
usbRaw.Write(4, sendData); // Write bytes to the USB Device
byte[] readData = usbRaw.Read(); // Read bytes from the USB Device
usbRaw.Dispose();
Надеюсь, это поможет кому-то.
Большинство наборов микросхем USB поставляются с драйверами. Silicon Labs имеет один.
У меня есть интерфейс к Teensy, работающий достаточно хорошо, используя в этой статье
Я попробовал несколько из этих предложений без везения. В итоге я написал рабочее решение с использованием Java и библиотеки hid4java. Как консольное приложение, я могу выполнить его из С#, используя Process.Start()
, передавая параметры, а также считывая ответы. Это обеспечивает базовый ввод-вывод HID, но без событий подключения/отключения. Для этого мне нужно будет переписать его для запуска в качестве демона/службы и использовать именованные каналы или другой транспортный сервер/клиент. На данный момент этого достаточно, чтобы выполнить эту работу, так как библиотека hi4java "просто работает".
USB-устройства обычно подразделяются на две категории: Hid и USB. Устройство USB может быть, а может и не быть устройством Hid, и наоборот. Спрятать обычно немного проще, чем прямой USB. Разные платформы имеют разные API для работы с USB и Hid.
Вот документация для UWP:
Спрятано: https://docs.microsoft.com/en-us/uwp/api/windows.devices.humaninterfacedevice
Вот документация для Android: https://developer.xamarin.com/api/namespace/Android.Hardware.Usb/
Вот два класса для работы с USB/Hid на уровне API Windows:
https://github.com/MelbourneDeveloper/Device.Net/blob/master/src/Hid.Net/Windows/HidAPICalls.cs
https://github.com/MelbourneDeveloper/Device.Net/blob/master/src/Usb.Net/Windows/WinUsbApiCalls.cs
В любом из этих решений вам нужно будет либо опросить устройство через определенный интервал, либо использовать один из классов прослушивания нативного устройства API. Тем не менее, эта библиотека помещает слой в Hid и USB на всех платформах, чтобы вы могли легко обнаруживать соединения и разъединения: https://github.com/MelbourneDeveloper/Device.Net/wiki/Device-Listener. Вот как вы бы это использовали:
internal class TrezorExample : IDisposable
{
#region Fields
//Define the types of devices to search for. This particular device can be connected to via USB, or Hid
private readonly List<FilterDeviceDefinition> _DeviceDefinitions = new List<FilterDeviceDefinition>
{
new FilterDeviceDefinition{ DeviceType= DeviceType.Hid, VendorId= 0x534C, ProductId=0x0001, Label="Trezor One Firmware 1.6.x", UsagePage=65280 },
new FilterDeviceDefinition{ DeviceType= DeviceType.Usb, VendorId= 0x534C, ProductId=0x0001, Label="Trezor One Firmware 1.6.x (Android Only)" },
new FilterDeviceDefinition{ DeviceType= DeviceType.Usb, VendorId= 0x1209, ProductId=0x53C1, Label="Trezor One Firmware 1.7.x" },
new FilterDeviceDefinition{ DeviceType= DeviceType.Usb, VendorId= 0x1209, ProductId=0x53C0, Label="Model T" }
};
#endregion
#region Events
public event EventHandler TrezorInitialized;
public event EventHandler TrezorDisconnected;
#endregion
#region Public Properties
public IDevice TrezorDevice { get; private set; }
public DeviceListener DeviceListener { get; private set; }
#endregion
#region Event Handlers
private void DevicePoller_DeviceInitialized(object sender, DeviceEventArgs e)
{
TrezorDevice = e.Device;
TrezorInitialized?.Invoke(this, new EventArgs());
}
private void DevicePoller_DeviceDisconnected(object sender, DeviceEventArgs e)
{
TrezorDevice = null;
TrezorDisconnected?.Invoke(this, new EventArgs());
}
#endregion
#region Public Methods
public void StartListening()
{
TrezorDevice?.Dispose();
DeviceListener = new DeviceListener(_DeviceDefinitions, 3000);
DeviceListener.DeviceDisconnected += DevicePoller_DeviceDisconnected;
DeviceListener.DeviceInitialized += DevicePoller_DeviceInitialized;
}
public async Task InitializeTrezorAsync()
{
//Get the first available device and connect to it
var devices = await DeviceManager.Current.GetDevices(_DeviceDefinitions);
TrezorDevice = devices.FirstOrDefault();
await TrezorDevice.InitializeAsync();
}
public async Task<byte[]> WriteAndReadFromDeviceAsync()
{
//Create a buffer with 3 bytes (initialize)
var writeBuffer = new byte[64];
writeBuffer[0] = 0x3f;
writeBuffer[1] = 0x23;
writeBuffer[2] = 0x23;
//Write the data to the device
return await TrezorDevice.WriteAndReadAsync(writeBuffer);
}
public void Dispose()
{
TrezorDevice?.Dispose();
}
#endregion
}