Программирование PC Библиотека HID USB Library для Visual Studio .Net (C#, Visual Basic) Sat, April 20 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

Библиотека HID USB Library для Visual Studio .Net (C#, Visual Basic) Печать
Добавил(а) microsin   

Перевод статьи, посвященной удобной библиотеке HID USB Driver / Library for .Net / C# ("HID USB Driver / Library for .Net / C#", автор Florian Leitner-Fischer).

usb-hid-and-csharp

[Почему появилась библиотека]

Нужно было найти новое решение чтобы подключить нашу аппаратуру к PC (компьютеру) через USB, потому что результаты, которые мы получили с помощью чипов FTDI, нас полностью не устраивали.

Выбранный нами контроллер USB Maxim MAX3420E был подключен к микроконтроллеру через Serial Peripheral Interface (SPI). Поставляется MAX3420E без каких-либо драйверов или библиотек, через которые Вы могли бы общаться с ним. По этой причине и появилась библиотека, описанная в статье.

После целого дня, потраченного на гугление и чтение полученной информации я решил, что самый простой и лучший метод - использовать Human Interface Device Class (HID). HID-Class является стандартным классом устройства (generic device class), так что все устройства этого класса поддерживаются Microsoft Windows из коробки, и имеются готовые DLL с функциями, которые можно использовать для доступа к устройствам USB HID.

Стартовой точкой для "драйвера| была статья, которую я нашел на Microsoft developer network (MSDN): "Is That You? Writing Better Software for Cool USB Hardware" (Это для Вас? Написание лучшего программного обеспечения для хорошей аппаратуры USB), написанную Scott Hanselman. Программное обеспечение автора основывалось на USBSharp Class [1].

К счастью, с MAX3420E был пример кода, который конфигурирует контроллер как Human Interface Device, так что мы не испытывали особых затруднений, чтобы понять, как сконфигурировать его в режиме HID.

[Human Interface Device Class, HID]

Как упоминалось выше, HID Class является стандартным классом устройства, драйвер для которого интегрирован в операционную систему, что упрощает работу с ним. Если, к примеру, в операционную систему Windows подключено новое устройство HID, то ему не требуется никакая инсталляция драйвера. Функции для получения доступа и управления устройством HID включены в Windows hid.dll, которая расположена в папке System32.

Если не знаете наверняка, что Ваше устройство - устройство HID, то взгляните на небольшое приложение "Сведения о системе". Оно является частью windows, и Вы можете запустить его командой start -> run "msinfo32.exe". Эта программа покажет в разделе Компоненты -> USB информацию о подключенных устройствах USB. Для обновления списка устройств при переподключениях выбирайте Вид -> Обновить. Кроме того, сведение о подключенных устройствах USB HID можно получить в Диспетчере Устройств, см. Панель Управления -> Администрирование -> Управление компьютером -> Устройства HID (Human Interface Devices).

msinfo32 DeviceManager

[Специфика USB: идентификация устройства USB]

Устройство USB идентифицируется по его ID вендора (Vendor ID, VID) и ID продукта (Product ID, PID). Именно по этим идентификаторам ПО хоста подключается к конкретному устройству USB (из этого следует, кстати, что нельзя одновременно подключиться к двум устройствам USB HID, если они имеют одинаковые VID и PID). Эти ID состоят из префикса ("vid_" для vendor id или "pid_" для product id) и 4 шестнадцатеричных цифр. Например, MAX3420E имеет vendor id vid_06ba и product id pid_5346. Обычно оба значения могут быть изменены в исходном коде USB-устройства (подразумевается, что Вы имеете доступ к этому коду).

[Размер пакета / скорость передачи данных на соединении]

Устройства HID обмениваются с PC данными через репорты HID (HID report). Эти репорты могут содержать от 8 до 64 байт данных. Каждую миллисекунду один репорт отправляется от PC к устройству USB и обратно. Это означает, что теоретическая максимальная скорость обмена может достигать 64000 байт/сек.

[Интерфейс библиотеки HID USB]

Библиотека написана на C# и разработана в виде DLL, что позволяет её очень просто интегрировать в новый проект. Библиотека рассчитана на устройства USB HID с размером 64 байта для конечных точек ввода и вывода (endpoints). Просто импортируйте DLL в проект, и получите удобный доступ к устройствам USB HID. Я старался сделать программный интерфейс библиотеки максимально простым, при сохранении максимально возможного функционала. В настоящий момент имеются следующие функции:

USBInterface(String vid, String pid) - метод конструктора, инициализирующий новый экземпляр (переменную) класса. У конструктора в этом случае два параметра - идентификатор вендора и идентификатор продукта USB-устройства. По этим параметрам будет происходить поиск нужного USB HID устройства.

USBInterface(String vid) - метод конструктора, инициализирующий новый экземпляр (переменную) класса. У конструктора в этом случае один параметр - идентификатор вендор. По этому параметру будет происходить поиск нужного USB HID устройства.

Connect() - этот метод устанавливает соединение до устройства USB. Вы можете быть уверенным, что подключились к нужному устройству только в том случае, если использовали конструктор USBInterface с двумя параметрами - vid и pid. Если же Вы использовали конструктор с одним параметром vid, то может произойти соединение с другим устройством с тем же самым Vendor ID (VID) - не с тем, с что ожидали, и Вы не сможете определить, к какому устройству произойдет подключение. Метод Connect возвратит false, если произошла любая ошибка.

Disconnect() - метод производит отключение от устройства.

getDeviceList() - метод возвращает список устройств с Vendor ID (VID), указанным в конструкторе. Эта функция понадобится Вам чтобы узнать, сколько подключено USB устройств (и какие они) с указанным идентификатором вендора. Возвращает список строк (String list) с системными путями до устройств.

write(Byte[]) - метод записывает массив байт в устройство USB. Если размер массива превышает 64, то массив будет поделен на несколько массивов, каждый по 64 байта. Массивы будут отправлены друг за другом, байты 0..63 будут отправлены первыми, затем будут отправлены байты 64..127, и так далее. Метод возвратит true, если все байты будут успешно записаны.

startRead() - метод используется для активизации "состояния чтения" (reading-State). Если Вы выполните эту команду, то запустится поток, который прослушивает устройство USB и ждет появления данных.

stopRead() - метод переключает библиотеку из состояния "reading-State" в состояние ожидания (idle-State). Путем выполнения этой команды поток чтения данных останавливается, и теперь данные могут быть получены.

enableUsbBufferEvent(EventHandler) - путем вызова этого метода с обработчиком события (System.EventHandler) добавляется событие прослушивания буфера USB. Таким образом будет вызван обработчик события всякий раз, когда набор данных добавлен к буферу (и также получен от USB-устройства).

[Как интегрировать библиотеку HID USB в проект Visual Basic]

Есть два способа интеграции HID USB Library в проект Visual Studio. Один из них - добавление проекта библиотеки к Вашему решению Visual Studio solution. Второй способ - добавление ссылки на USBHIDDRIVER.dll в проект, где Вы хотите использовать библиотеку HID USB. Предварительно скачайте пакет библиотеки [2], и распакуйте его файлы в Ваш проект приложения.

Добавление проекта библиотеки в решение (solution) Visual Studio 2005, процесс по шагам:

1. Откройте Ваше решение (Visual Studio solution). Выберите в меню File -> Add -> Existing Project.

usb-hid-csharp-lib-add-to-VB-project1

2. Откроется диалог открытия файла. Найдите файл USBHIDDRIVER.csproj и откройте его (кликните Open).

usb-hid-csharp-lib-add-to-VB-project2

3. Правым щелчком мыши на проекте Visual Studio откройте контекстное меню проекта и выберите Add Reference (добавить ссылку).

usb-hid-csharp-lib-add-to-VB-project3

4. Выберите закладку Projects, затем выберите USBHIDDRIVER и щелкните OK.

usb-hid-csharp-lib-add-to-VB-project4

Добавление USBHIDDRIVER.dll к проекту Visual Studio, процесс по шагам.

1. Правым щелчком мыши на проекте Visual Studio откройте контекстное меню проекта и выберите Add Reference (добавить ссылку).

USBHIDDRIVER-dll-add-to-Visual-Studio-project1

2. Выберите закладку Browse, найдите USBHIDDRIVER.dll (или USBHIDDRIVER.dll.dll) и кликните OK.

USBHIDDRIVER-dll-add-to-Visual-Studio-project2

[Использование USBHIDDRIVER.dll вместе с Visual Basic 6]

Исполняемый код .Net (.Net runtime) позволяет необслуживаемым клиентам COM (unmanaged COM aware clients, наподобие приложений Visual Basic 6) получить доступ к компонентам .Net через взаимодействие COM (COM interop) и инструменты, предоставленные средой разработки.

Библиотека USBHIDDRIVER.dll является сборкой .NET, к которой не может быть получен доступ из Visual Basic 6. Поэтому мы должны создать библиотеку типов, которая может использоваться с Visual Basic 6. Это можно сделать с помощью инструмента RegAsm.exe, который Вы можете найти в директории инсталляции среды разработки .Net. Создайте командный файл BAT в папке, где находится USBHIDDRIVER.dll, впишите в него следующую команду и затем запустите его:

“C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe” USBHIDDRIVER.dll.dll /tlb: USBHIDDRIVER.dll.tlb

Теперь Вы должны скопировать и dll, и tlb файлы в том же каталоге в папку приложения, Visual Basic, чтобы оно могло использовать библиотеку USB HID.

[Как использовать HID USB Library]

Предположим, Вам нужно наладить обмен с USB-устройством, которое имеет vendor id vid_06ba и несколько возможных product id. Первое, что Вам понадобится - список всех подключенных к PC устройств, которые имеют указанный vendor id. Чтобы получить этот список - просто создайте новый экземпляр класса USBInterface, при этом укажите конструктору только один параметр - VID (vendor id). Затем вызовите метод getDeviceList, и получите список подключенных устройств.

USBHIDDRIVER.USBInterface usb = new USBInterface("vid_06ba");
String[] list = usbI.getDeviceList();

Для организации обмена с нужным устройством из списка сделайте новый экземпляр USBInterface, и на этот раз укажите конструктору два параметра - VID и PID. Затем вызовите метод Connect, и получите соединение с USB-устройством.

USBHIDDRIVER.USBInterface usb = new USBInterface("vid_06ba", "pid_5346");
usb.Connect();

Как только соединение с устройством установлено, Вы можете читать или записывать данные. Для записи данных просто вызовите метод write с указанием в параметре массива байт, который нужно передать. Чтение может быть реализовано двумя способами: первый без события USB buffer event, и второй с событием USB buffer event.

Если разрешено событие, то обработчик события (event handler method) будет вызван всякий раз, когда будет принят новый набор данных. В другом случае Вы можете обработать данные по таймеру наподобие примерно следующего кода:

usb.write(startByte);
usb.enableUsbBufferEvent(new System.EventHandler(myEventCacher));
Thread.Sleep(5);
usb.startRead();
…
usb.stopRead();
usb.write(stopByte);

[Что происходит внутри HID USB Library]

Библиотека основана на классе USBSharp, который импортирует все нужные методы из kernel32.dll и hid.dll. Класс HIDUSBDevice оборачивает эти методы и организует чтение в отдельном потоке. Главным интерфейсом библиотеки является класс USBInterface, который доступен снаружи dll. В классе USBInterface существует объект ListWithEvent, который основывается на ArrayList с бонусом в виде запуска обработчика события, когда добавляется новый набор данных. Наконец, что не менее важно, в классе HidApiDeclaration Вы найдете некоторые объявления, необходимые для работы с USB HID.

[Примечание переводчика]

В Интернете можно найти очень похожий аналог библиотеки, описанной в этой статье, только не в виде DLL, а в виде файлов исходного кода C# (модулей .cs) [3]. Библиотека имеет класс UsbLibrary.UsbHidPort, в котором сосредоточен весь интерфейс работы с устройством USB HID. Возможностей у этой библиотеки больше - например, есть очень удобные события подключения и отключения устройства USB, благодаря чему легко реализовать прозрачную работу с устройством USB HID и восстанавливать обмен данными с USB-устройством без необходимости перезапуска программы.

[Ссылки]

1. The HID Page - страничка, посвященная классу HID.
2. Пакет библиотеки HID USB Driver / Library for .Net / C# (USBHIDDRIVER.dll).
3. UsbLibrary.UsbHidPort class source code.
4. Библиотеки для управления устройствами USB HID.
5. USB in a NutShell - путеводитель по стандарту USB.
6. HID API для Linux, Mac OS X и Windows.

 

Комментарии  

 
0 #18 влад 27.04.2020 14:53
Меня смутило использование метода ReadFile, для чтения данных от usb. По идее этот метод блокирует выполнения потока, пока данные не будут прочитаны. Хоть он и выполняется в отдельном потоке и ничего не тормозит на форме. Проверял на скорости от 1мс./пакет(64Б.) до 1сек./пакет(64Б.), вроде бы работает все быстро, ничего не тормозит.
Тут в комментах выше, кто то жалуется, что данные по 4 байта в USB не пишутся. Думаю проблема в функции записи. Она вроде как по 64 байта данными оперирует.
Цитировать
 
 
0 #17 влад 27.04.2020 14:52
Хочу свои 5 к. добавить.
1. Чтобы работать с обработчиком, надо осуществить подписку от делегата к обработчику. Автор приводит пример:
usb.enableUsbBuffer Event(new System.EventHandler(my EventCacher));
Ложим его либо в конструктор формы после
InitializeCompo nent(); метода, либо можно добавить к форме загрузчик и в него положить.
2. Создаем на форме обработчик
void myEventCacher(o bject sender, EventArgs e){}
обработчик будет вызываться каждый раз, как придет новый usb пакет. Только чтобы запустить процесс, надо однократно вызвать usb.startRead();.
Цитировать
 
 
0 #16 влад 27.04.2020 14:39
Цитирую Бикуклис:
Реализовал проект на C#, используя вышеупомянутую библиотеку - все работает. Проблема только при закрытии программы. Программа сворачивается, но в памяти остается работающий поток, который не выгружается. По логике необходимо сделать disconnect(). Но при работе программы система ругается, на этом методе, что попытка применить метод к несуществующему объекту. Не приходилось сталкиваться с такой проблемой?

microsin: с такой проблемой не сталкивался, метод disconnect() не использую. При закрытии программы тупо вызываю метод Close() созданного объекта UsbLibrary.UsbHidPort - он отвечает за соединение по USB. И все, никаких проблем.

Для решений этой проблемы необходимо снова вызвать метод startRead() или stopRead(), неважно какой, если в текущий момент выполняется поток чтения, то они будут поток останавливать. А затем уже вызывать Disconnect().
Цитировать
 
 
+2 #15 fd 29.07.2015 16:45
Сделал dll и tlb, подключил ссылку в проект (C# Visual Studio 2010, windows 7).

public static USBHIDDRIVER.USBInterface usb = new USBInterface("VID_1СCС","PID_0001");

private void form_Load(objec t sender, EventArgs e)
{
MessageBox.Show(usb.Connect().ToString());
this.Close();
}

Не происходит коннект, постоянно False, что это может быть?
Цитировать
 
 
+7 #14 Александр 26.09.2014 18:33
Не могу понять: HID устройство определяется, но не могу ни отправить, ни принять данные. Подскажите откуда забирать считанную информацию, после того как вызван метод usb.startRead()?
Цитировать
 
 
0 #13 kayar 31.08.2014 19:46
А что делать, если клавиатура определяется в системе как AVR USB KEYBOARD DEMO, и не устанавливаются драйвера, хотя проскакивает информация, что это USB HID устройство (Windows XP)?

microsin: возможно, в дескрипторах или в firmware ошибка, см. код этого устройства USB HID. Возьмите готовый проверенный пример клавиатуры USB HID, и попробуйте его.
Цитировать
 
 
+4 #12 Igor 25.06.2014 23:37
У меня тоже write всегда возвращает false
Цитировать
 
 
+6 #11 Роман 04.06.2014 10:39
Подключил библиотеку "using USBHIDDRIVER;". Все компоненты видит. Но usbI.Connect() выдает true, a usbI.write(startCMD) - false... Что делать?
Цитировать
 
 
0 #10 Александр 13.04.2014 09:11
Статья понравилась, а есть что-нибудь по этой теме еще почитать? просто мне надо для курсового проекта, а сам не особо разбираюсь. Мне нужно организовать связь по USB с контроллером.
Цитировать
 
 
+1 #9 Дима 07.04.2014 21:27
Извините за вопрос, я начинающий программист пытался разобраться но не понял, подскажите пожалуйста: куда помешаются данные с устройства при описанном Вами методе чтения? Также было бы прекрасно если бы, кто-нибудь написал, как выглядит чтение с использованием события (как включить и ...).
Цитировать
 

Добавить комментарий


Защитный код
Обновить

Top of Page