Russian Qt Forum
Ноябрь 25, 2024, 12:05 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: libusb, обёртка  (Прочитано 11984 раз)
juvf
Программист
*****
Offline Offline

Сообщений: 570


Просмотр профиля
« : Апрель 11, 2016, 11:30 »

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

Сообщений: 4350



Просмотр профиля
« Ответ #1 : Апрель 11, 2016, 11:43 »

http://libusb.sourceforge.net/api-1.0/group__asyncio.html
Записан
juvf
Программист
*****
Offline Offline

Сообщений: 570


Просмотр профиля
« Ответ #2 : Апрель 11, 2016, 12:41 »

это я видел, но не понятно... как это можно использовать в моём случае?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #3 : Апрель 11, 2016, 13:02 »

это я видел, но не понятно... как это можно использовать в моём случае?
Стоп, вы хотите чтобы устройство спонтанно отправляло данные? Насколько я помню, все USB-транзакции выполняются по инициативе хоста.
Записан
juvf
Программист
*****
Offline Offline

Сообщений: 570


Просмотр профиля
« Ответ #4 : Апрель 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 мс, но в моём случае это приемлемо.
Записан
juvf
Программист
*****
Offline Offline

Сообщений: 570


Просмотр профиля
« Ответ #5 : Апрель 11, 2016, 13:13 »

а как HID работают? Например клавиатура? Хост постоянно опрашивает HID на предмет наличия данных? Или клавиатура сама шлёт данные, когда её вздумается?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #6 : Апрель 11, 2016, 13:35 »

а как HID работают? Например клавиатура? Хост постоянно опрашивает HID на предмет наличия данных?
Да. Вы можете задавать частоту, с которой хаб будет опрашивать устройство.
Записан
juvf
Программист
*****
Offline Offline

Сообщений: 570


Просмотр профиля
« Ответ #7 : Апрель 11, 2016, 13:41 »

хорошо, а как с libusb можно hid поднять? Придется всё руками делать, т.е. в отдельном треде опрашивать hid? Или можно проинить как нить libusb и обрабатывать эвенты?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #8 : Апрель 11, 2016, 13:51 »

хорошо, а как с libusb можно hid поднять? Придется всё руками делать, т.е. в отдельном треде опрашивать hid? Или можно проинить как нить libusb и обрабатывать эвенты?
Это хороший вопрос. Улыбающийся
Думаю, что все придется делать самому. Но не думаю, что это будет сильно проблемно.
Можно обойтись без отдельного потока, все будет зависеть от необходимой вам частоты опроса. Если она будет не максимальная (1кГц), а скажем раз в 300 мс, то можно использовать таймер. Пришло время, опросили железку, если что-то пришло, послали сигнал с данными.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #9 : Апрель 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..

« Последнее редактирование: Апрель 12, 2016, 08:41 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
juvf
Программист
*****
Offline Offline

Сообщений: 570


Просмотр профиля
« Ответ #10 : Апрель 12, 2016, 07:29 »

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

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

Цитировать
передаем его хендл в QWinOverlappedIoNotifier
Нет такого класса в Qt 5.4. Есть QWinEventNotifier? Наверно это тоже самое?
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #11 : Апрель 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 используется - разницы в принципе нет).
« Последнее редактирование: Апрель 12, 2016, 08:38 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
juvf
Программист
*****
Offline Offline

Сообщений: 570


Просмотр профиля
« Ответ #12 : Апрель 12, 2016, 08:38 »

Ещё нюанс.... вот вызвали ReadFile  и занимаемся своими делами..... но сообщений нет..... внезапно юзер отключает разъем усб, что тогда? ReadFile  корректно отработает такую ситуацию?
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #13 : Апрель 12, 2016, 08:46 »

Цитировать
ReadFile  корректно отработает такую ситуацию?

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

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

ArchLinux x86_64 / Win10 64 bit
juvf
Программист
*****
Offline Offline

Сообщений: 570


Просмотр профиля
« Ответ #14 : Апрель 12, 2016, 09:28 »

Я ещё не подымал в железке хид.... смотрю в Деспетчер устройств в винде... там все HID-устройства безымянные. Это свойство HID? Я не смогу увидеть что-то типа "HID совместимое устройство MyDevice"?

в принцепе похожий алгоритм, предложенный kuzulis, можно бы и на либусб сделать, есть там всякие libusb_fill_bulk_transfer(), но в текущей версии(1.2.5) libusb нет такой функции.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.094 секунд. Запросов: 22.