Подтвердить что ты не робот

Работа с устройствами USB в .NET.

Используя .Net(С#), как вы можете работать с USB-устройствами?

Как вы можете обнаружить события USB (соединения/разъединения) и как вы общаетесь с устройствами (чтение/запись).

Есть ли для этого встроенное .NET решение?

4b9b3361

Ответ 1

Для этого нет встроенного (например, системных библиотек). Это причина, по которой SharpUSBLib существует, как упоминалось moobaa.

Если вы хотите перевернуть свой собственный обработчик для USB-устройств, вы можете проверить класс SerialPort System.IO.Ports.

Ответ 2

Я пробовал использовать SharpUSBLib, и он прикрутил мой компьютер (требуется восстановление системы). Случилось также с коллегой по тому же проекту.

Я нашел альтернативу в LibUSBDotNet: http://sourceforge.net/projects/libusbdotnet Havn't использовал его много, но кажется хорошим и недавно обновленным (в отличие от Sharp).

EDIT: По состоянию на середину февраля 2017 года LibUSBDotNet обновлялась около 2 недель назад. Тем временем SharpUSBLib не обновлялся с 2004 года.

Ответ 4

Я использовал следующий код для определения того, когда 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-объекта во время выполнения при закрытии.

Ответ 5

Я бы рекомендовал LibUSBDotNet библиотеку, которую я использовал в течение 2 лет. Если вам нужно работать с USB-устройством (отправлять запросы, обрабатывать ответы), эта библиотека была лучшим решением, которое я мог найти.

Плюсы:

  • Все методы, которые вам нужны для работы в синхронном или асинхронном режиме.
  • Исходный код
  • Достаточно образцов, чтобы начать использовать его сразу.

Минусы:

  • Плохая документация (общая проблема для проектов с открытым исходным кодом). В принципе, вы можете найти просто общее описание методов в файле справки CHM и его. Но я все еще нахожу предоставленные образцы и исходного кода достаточно для кодирования. Просто иногда я вижу странное поведение и хочу знать, почему он был реализован таким образом и не может получить даже намека...
  • Похоже, что не поддерживается. Последняя версия была выпущена в октябре 2010 года. И иногда бывает трудно получить ответы.

Ответ 7

Существует общий набор инструментов WinDriver для записи драйверов USB в пользовательском режиме, которые также поддерживают #.NET

Ответ 8

Если на вашем ПК установлено программное обеспечение National Instruments, вы можете создать драйвер USB с помощью "мастера драйверов NI-VISA".

Шаги по созданию драйвера USB: http://www.ni.com/tutorial/4478/en/

После создания драйвера вы сможете записывать и читать байты на любое USB-устройство.

Убедитесь, что драйвер находится в окне Диспетчера устройств:

enter image description here

Код С#:

    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();

Надеюсь, это поможет кому-то.

Ответ 9

Большинство наборов микросхем USB поставляются с драйверами. Silicon Labs имеет один.

Ответ 10

У меня есть интерфейс к Teensy, работающий достаточно хорошо, используя в этой статье

Ответ 11

Я попробовал несколько из этих предложений без везения. В итоге я написал рабочее решение с использованием Java и библиотеки hid4java. Как консольное приложение, я могу выполнить его из С#, используя Process.Start(), передавая параметры, а также считывая ответы. Это обеспечивает базовый ввод-вывод HID, но без событий подключения/отключения. Для этого мне нужно будет переписать его для запуска в качестве демона/службы и использовать именованные каналы или другой транспортный сервер/клиент. На данный момент этого достаточно, чтобы выполнить эту работу, так как библиотека hi4java "просто работает".

Ответ 12

USB-устройства обычно подразделяются на две категории: Hid и USB. Устройство USB может быть, а может и не быть устройством Hid, и наоборот. Спрятать обычно немного проще, чем прямой USB. Разные платформы имеют разные API для работы с USB и Hid.

Вот документация для UWP:

USB: https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/how-to-connect-to-a-usb-device--uwp-app-

Спрятано: 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
}