Russian Qt Forum

Программирование => Общий => Тема начата: juvf от Апрель 11, 2016, 11:30



Название: libusb, обёртка
Отправлено: juvf от Апрель 11, 2016, 11:30
Пишу обмен с девайсом с использованием libusb. Сделал в девайсе EP_IN и EP_OUT. Обе точки bulk. В хосте осуществляется обмен с девайсом по алгоритму запрос-ответ. В нужно месте вызываю usb_bulk_write() и следом usb_bulk_read() в ожидании ответа.
возникла необходимость получать от девайса спорадические сообщения. Как это сделать с libusb? Хотелось бы, чтоб девайс в лбюбое время послал сообщение, а в хосте возник бы эвент или сигнал "Пришло сообщение от usb девайса", и к этому эвенту или сигналу прикрутить обработчик или слот.


Название: Re: libusb, обёртка
Отправлено: Old от Апрель 11, 2016, 11:43
http://libusb.sourceforge.net/api-1.0/group__asyncio.html


Название: Re: libusb, обёртка
Отправлено: juvf от Апрель 11, 2016, 12:41
это я видел, но не понятно... как это можно использовать в моём случае?


Название: Re: libusb, обёртка
Отправлено: Old от Апрель 11, 2016, 13:02
это я видел, но не понятно... как это можно использовать в моём случае?
Стоп, вы хотите чтобы устройство спонтанно отправляло данные? Насколько я помню, все USB-транзакции выполняются по инициативе хоста.


Название: Re: libusb, обёртка
Отправлено: juvf от Апрель 11, 2016, 13:11
это я видел, но не понятно... как это можно использовать в моём случае?
Стоп, вы хотите чтобы устройство спонтанно отправляло данные? Насколько я помню, все USB-транзакции выполняются по инициативе хоста.
Да, вот именно, мне нужно чтоб устройство само инициализировало передачу. Пока вижу такой сценарий: в устройстве сделать отдельную точку bulk, в хосте в отдельном потоке

1) открыть усб
2) при успешном открытии пробовать прочитать заведомо много байт usb_bulk_read(handlerDev, EP_IN, bufferUsb, 6000, 100);
3)закрыть усб
4)если прочитал что-то, то оработать (послать сигнал с сообщением)
5)уснуть на 100 мс.
6) goto 1

будут задержки до 200 мс, но в моём случае это приемлемо.


Название: Re: libusb, обёртка
Отправлено: juvf от Апрель 11, 2016, 13:13
а как HID работают? Например клавиатура? Хост постоянно опрашивает HID на предмет наличия данных? Или клавиатура сама шлёт данные, когда её вздумается?


Название: Re: libusb, обёртка
Отправлено: Old от Апрель 11, 2016, 13:35
а как HID работают? Например клавиатура? Хост постоянно опрашивает HID на предмет наличия данных?
Да. Вы можете задавать частоту, с которой хаб будет опрашивать устройство.


Название: Re: libusb, обёртка
Отправлено: juvf от Апрель 11, 2016, 13:41
хорошо, а как с libusb можно hid поднять? Придется всё руками делать, т.е. в отдельном треде опрашивать hid? Или можно проинить как нить libusb и обрабатывать эвенты?


Название: Re: libusb, обёртка
Отправлено: Old от Апрель 11, 2016, 13:51
хорошо, а как с libusb можно hid поднять? Придется всё руками делать, т.е. в отдельном треде опрашивать hid? Или можно проинить как нить libusb и обрабатывать эвенты?
Это хороший вопрос. :)
Думаю, что все придется делать самому. Но не думаю, что это будет сильно проблемно.
Можно обойтись без отдельного потока, все будет зависеть от необходимой вам частоты опроса. Если она будет не максимальная (1кГц), а скажем раз в 300 мс, то можно использовать таймер. Пришло время, опросили железку, если что-то пришло, послали сигнал с данными.


Название: Re: libusb, обёртка
Отправлено: kuzulis от Апрель 11, 2016, 18:14
Бррр... Не знаю как там в libusb все "закручено", но нет никаких проблем если использовать нативное API.

Например, если используется Windows то:

= Если принято решение использовать HID девайс, то для этого надо =

1. Реализовать HID класс у-ва (дескрипторы и прочие плюшки) в прошивке железки.

2. Используем Win32 API для работы с HID девайсом:
- ищем DevicePath
- открываем с помощью CreateFile
- конфигурим девайс
- пишем/читаем в ендпойнты девайса (используя WriteFile/ReadFile или DeviceIoControl, в зависимости от того, какая ендпойнт используется).

Прелесть здесь в том, что WriteFile/ReadFile асинхронные для bulk (если открывать девайс в OVERLAPPED режиме)... Например, если хотим прочитать что-то из девайса, то алгоритм такой:
- при открытии девайса передаем его хендл в QWinOverlappedIoNotifier, и коннектим его сигнал notified() к нашему слоту. Этот сигнал будет сигнализировать нам о том, что какая-то I/O операция на хендле девайса завершена.
- делаем ReadFile c OVERLAPEPD структурой и все....
- когда в устройстве появятся данные, то сработает QWinOverlappedIoNotifier с нашей OVERLAPPED структурой, по которой можно сравнить, какая из операций завершена (в нашем случае только одна read).
- И все.. в буфере, который передавался как параметр ReadFile  будут лежать прочитанные данные...
- После того как обработаем данные, можно снова вызвать ReadFile c OVERLAPEPD структурой и т.п. все заново.

Тут не нужны потоки и прочий треш  ;).

Минус в том, что для контрол-эндпойнтов это не будет работать, используя HID функции, т.к. они не используют OVERLAPPED (емнип). т.е. QWinOverlappedIoNotifier будет постоянно срабатывать и грузить event-loop... Хотя, у меня работало и с загрузкой..  ;)

= Если принято решение использовать  девайс как "Стандартное" USB у-во, то для этого надо =

1. Задать USB дескриптору девайса (в его прошивке) класс как "Стандартное ЮСБ" (MSDN в помощь). Это надо чтобы виндовс подгрузил стандартные дрова и определил девайс как "Стандартное ЮСБ у-во".

2. А далее, также как и с HID, ищем devicepath, открываем его, делаем I/O в экдпойнты, используя или ReadFile/WriteFile или WinUSB API, в зависимости от эндпойнтов..

По аналогии такое можно сделать и для Linux, только использовать QSocketNotifier... но я не пробовал.

ЗЫ: Возможно, что асинхонная работа также поддерживается и в LibUSB (как выше приведено в ссылке), т.е. делаем транзакцию, и каллбек вызовется только тогда, когда данные были прочитаны из у-ва... Но я ХЗ. я не работал с LibUSB..



Название: Re: libusb, обёртка
Отправлено: juvf от Апрель 12, 2016, 07:29
2. Используем Win32 API для работы с HID девайсом:
- ищем DevicePath
- открываем с помощью CreateFile
- конфигурим девайс
- пишем/читаем в ендпойнты девайса (используя WriteFile/ReadFile или DeviceIoControl, в зависимости от того, какая ендпойнт используется).

Как найти DevicePath у USB? Есть рабочий пример?

Цитировать
передаем его хендл в QWinOverlappedIoNotifier
Нет такого класса в Qt 5.4. Есть QWinEventNotifier? Наверно это тоже самое?


Название: Re: libusb, обёртка
Отправлено: kuzulis от Апрель 12, 2016, 08:35
Цитировать
Как найти DevicePath у USB? Есть рабочий пример?

В Windows - использовать SetupAPI, где перечислять нужные девайсы по их GUID, где искомое будет то, у которого совпадают VID/PID. В принципе, гугл в помощь, например: http://stackoverflow.com/questions/13927475/windows-how-to-enumerate-all-connected-usb-devices-device-path и много других ресурсов.

Рабочих примеров - полно.

Цитировать
Нет такого класса в Qt 5.4. Есть QWinEventNotifier?

Начиная с 5.5, оно есть но приватное, чтобы использовать достаточно прописать QT += core-private.
Qt 5.4 - ну уж очень древнемамонт..  ;)

Цитировать
Наверно это тоже самое?

Нет, не то-же, но использовать тоже можно. Тут нужно просто в OVERLAPPED структуре создавать ovl.hHandle и его передавать в QWinEventNotifier, вместо хендла девайса.

Как это используется - можно посмотреть в том-же QSerialPort до 5.5 и после 5.5 (также там можно посмотреть как SetupApi используется - разницы в принципе нет).


Название: Re: libusb, обёртка
Отправлено: juvf от Апрель 12, 2016, 08:38
Ещё нюанс.... вот вызвали ReadFile  и занимаемся своими делами..... но сообщений нет..... внезапно юзер отключает разъем усб, что тогда? ReadFile  корректно отработает такую ситуацию?


Название: Re: libusb, обёртка
Отправлено: kuzulis от Апрель 12, 2016, 08:46
Цитировать
ReadFile  корректно отработает такую ситуацию?

да, там Notifier сработает, но с кодом ошибки (GetLastError)... обычно это будет что-то типа OPERATION_ABORTED (или как-то так, не помню)... но, в общем, с ошибкой все вернется.

если такое не устраивает, то можно подписаться на события ATTACH/DETACH (на WM_MESSAGE), для конкретного класса у-в по их GUID. Тогда конкретно уже можно получать нотификации о том что у-во выло всунуто-высунуто и закрывать его хендл если надо.. (гугл в помощь).


Название: Re: libusb, обёртка
Отправлено: juvf от Апрель 12, 2016, 09:28
Я ещё не подымал в железке хид.... смотрю в Деспетчер устройств в винде... там все HID-устройства безымянные. Это свойство HID? Я не смогу увидеть что-то типа "HID совместимое устройство MyDevice"?

http://libusb.sourceforge.net/api-1.0/group__asyncio.html
в принцепе похожий алгоритм, предложенный kuzulis, можно бы и на либусб сделать, есть там всякие libusb_fill_bulk_transfer() (http://libusb.sourceforge.net/api-1.0/group__asyncio.html#gad4ddb1a5c6c7fefc979a44d7300b95d7), но в текущей версии(1.2.5) libusb нет такой функции.


Название: Re: libusb, обёртка
Отправлено: kai666_73 от Апрель 12, 2016, 11:19
Цитировать
Как найти DevicePath у USB? Есть рабочий пример?

В Windows - использовать SetupAPI, где перечислять нужные девайсы по их GUID, где искомое будет то, у которого совпадают VID/PID. В принципе, гугл в помощь, например: http://stackoverflow.com/questions/13927475/windows-how-to-enumerate-all-connected-usb-devices-device-path и много других ресурсов.


Два одинаковых устройства (VID/PID совпадают) и схема ломается (


Название: Re: libusb, обёртка
Отправлено: kuzulis от Апрель 12, 2016, 11:24
Цитировать
Это свойство HID?

Не, это св-во дефолтного драйвера, который поднимает винда, где всем девайсам назначаются дескрипшены типа "USB Input Device". И функции из Setup API возвратят именно этот дескрипшн.

Цитировать
Я не смогу увидеть что-то типа "HID совместимое устройство MyDevice"?

Для этого надо писать свой inf файл, в котором указывать нужный дескрипшн (также указать VIP/PID и тип девайса, см. MSDN) и подсовывать этот файл при установке девайса.
Но это еще не все - нужно подписывать этот inf файл (т.е. нужен сертификат, заплатить денюжку и купить).

Как вариант - можно "MyDevice" прописать в дескрипторе USB у-ва в самой его прошивке и тогда с помощью WinUSB API прочитать USB дескриптор твоего девайса и вытянуть из него любое поле (см. USB спецификацию).


Название: Re: libusb, обёртка
Отправлено: kuzulis от Апрель 12, 2016, 11:25
Цитировать
Два одинаковых устройства (VID/PID совпадают) и схема ломается (

Для этого служит серийный номер ;)