LINUX.ORG.RU

Как в USB отправить информацию из девайса?

 


0

2

Я пишу прошивку для девайса, который через USB коммуницирует с компьютером. В девайсе возникает событие, которое нужно передать в запущенную на компьютере программу. Я вроде в USB разобрался, но всё равно ничего лучше поллинга 10 раз в секунду не придумал. Просто посылаю setup request из программы на девайс, а девайс отвечает ответом или stall-ом. Но как-то это туповато, такое ощущение, что я что-то фундаментальное не понимаю. Или так и надо?

★★★★
Ответ на: комментарий от I-Love-Microsoft

Чип nRF52, логику реализую сам, пока эндпоинты не добавлял, пользуюсь нулевым. Надо - добавлю. HID городить не планирую, он на андроиде не поддерживается и вообще зачем он мне. На текущий момент девайс это хром через webusb, потом андроид может добавиться, когда-нибудь потом может десктопное приложение через libusb добавиться, но это не точно.

vbr ★★★★
() автор топика
Последнее исправление: vbr (всего исправлений: 2)
Ответ на: комментарий от COKPOWEHEU

хост сколько-то раз в секунду их пинает и смотрит есть ли ответ

Я правильно понимаю, что под хостом в случае использования libusb/webusb понимается конкретно моя программа? К примеру https://developer.mozilla.org/en-US/docs/Web/API/USBDevice/transferIn вот этот метод. И если я его не вызову, то никто его не вызовет. Или в линуксовом драйвере USB автоматом будет проверяться эндпоинт с определённой периодичностью, вне зависимости от того, вычитывает ли его юзерспейс или нет?

vbr ★★★★
() автор топика
Последнее исправление: vbr (всего исправлений: 3)
Ответ на: комментарий от COKPOWEHEU

Хотя почитал ещё, я так понял, если данных нет, девайс отвечает NAK, но такого статуса у USBInTransferResult нет, значит он таки работает под капотом автоматом и более эффективно. Спасибо, буду копать в сторону interrupt endpoint-а, похоже он в данном случае подходит лучше.

vbr ★★★★
() автор топика
Ответ на: комментарий от vbr

HID городить не планирую, он на андроиде не поддерживается и вообще зачем он мне.

Не знаю как на счет custom-hid, но мышь андроидом вполне поддерживается, а ведь она именно на hid основана.

Я правильно понимаю, что под хостом в случае использования libusb/webusb понимается конкретно моя программа?

Скорее, драйвер / аппаратура компа. interrupt-запросы, если я правильно помню, посылаются автоматически, без участия юзерского кода. Но я с interrupt-точками работал только тестово, с точки зрения стандартного устройства. Как они опрашиваются из самодельного «драйвера» не знаю.

HID городить не планирую

похоже он в данном случае подходит лучше

Поскольку вы ничего не рассказали о своем устройстве, мы подсказать ничего не можем. interrupt используются в тех же HID (события от клавиатуры, мыши или подобного) и, скажем, в CDC (переходник на RS232) для служебных линий CTS, DSR и т.д. В общем, для данных, которые появляются редко и непредсказуемо.

COKPOWEHEU
()
Ответ на: комментарий от COKPOWEHEU

Не знаю как на счет custom-hid, но мышь андроидом вполне поддерживается, а ведь она именно на hid основана.

Я имею в виду доступное приложениям API. В ядре-то понятно поддерживается, но я же не для ядра код буду писать. А в юзерспейсе даже usb serial не поддерживается. Причём что противно - /dev/ttyACM0 появляется, но доступа (без рута) нет. Поэтому по итогу проще всего оказывается рабоать с голыми эндпоинтами. Наверняка какие-то реализации HID для юзерспейса есть, для serial по крайней мере есть, но без нужды смысла не вижу этим пользоваться.

Поскольку вы ничего не рассказали о своем устройстве, мы подсказать ничего не можем. interrupt используются в тех же HID (события от клавиатуры, мыши или подобного) и, скажем, в CDC (переходник на RS232) для служебных линий CTS, DSR и т.д. В общем, для данных, которые появляются редко и непредсказуемо.

Ну теорию, как оно «по проводу» передаётся, я примерно понял, а вот в нюансах конкретных реализаций не понимаю. Пока тоже пришёл к выводу, что с interrupt эндпоинтом оно будет правильней, спасибо, буду экспериментировать. С SETUP запросами я разобраться был вынужден, дескрипторы-то отсылать хосту надо, чтобы устройство пронумеровалось как положено, вот и сделал ещё одним запросом с vendor кодом запрос этого пин-кода, показалось так проще всего.

Про устройство пока рассказывать особо нечего, это BLE устройство, а всё, что я сейчас делаю - чтобы отобразить на подключенном компьютере пин-код в момент спаривания, т.к. дисплея на устройстве нет. В будущем в протоколе будет больше функций, но пока - только это - передать строку из 6 цифр в нужный момент.

vbr ★★★★
() автор топика
Последнее исправление: vbr (всего исправлений: 2)

В девайсе возникает событие, которое нужно передать в запущенную на компьютере программу

Как в USB отправить информацию из девайса?

Это принципиально невозможно. Микрософт постарался участвуя в разработке USB чтобы оно было максимально черезжопным.

Фактически, USB девайс всегда поллится хостом. Девайс передаёт данные только если получил IN токен от хоста. Даже если это interrupt или isochronous. Просто в interrupt или isochronous режимах поллингом обычно занимается микруха хоста, а не система или софт. Если девайс не получит IN токен от хоста - то даже если обпередаётся, то хост его проигнорирует.

Соответственно, если твои события редкие, то используй interrupt. Если средненькой периодичности, то bulk или setup. Если это что-то очень частое - то isochronous, позволит передать несколько событий произошедших в течении одного фрейма. Теоретически, можно и bulk/setup несколько раз за фрейм запросить, но это придётся делать ручками в софте.

Stanson ★★★★★
()
Последнее исправление: Stanson (всего исправлений: 1)
Ответ на: комментарий от vbr

Причём что противно - /dev/ttyACM0 появляется, но доступа (без рута) нет.

Но ведь в сторонних приложениях оно как-то работает без рута.

а всё, что я сейчас делаю - чтобы отобразить на подключенном компьютере пин-код в момент спаривания, т.к. дисплея на устройстве нет. В будущем в протоколе будет больше функций, но пока - только это - передать строку из 6 цифр в нужный момент.

Если оно нужно единственный раз в момент подключения, да чтобы максимально юзер-френдли, можно сэмулировать флешку, в которой будет файл с этими 6 цифрами. https://habr.com/ru/articles/654853/

Фактически, USB девайс всегда поллится хостом. Девайс передаёт данные только если получил IN токен от хоста. Даже если это interrupt или isochronous.

Изохронные-то ладно, там это оправдано. Но в целом да, организация шины дурацкая. И отсутствие хоть каких-то прерываний, и адрес девайса, который сообщается самому девайсу при энумерации, и utf-16 в идентификаторе, и 16-битные VID:PID.

Но этого мало. Те же ST на это посмотрели и решили, что градус безумия недостаточен! В результате их реализация USB в F1 и подобных получилась не менее наркоманской. Причем настолько, что даже ихний же Куб ее толком не поддерживает.

COKPOWEHEU
()
Ответ на: комментарий от COKPOWEHEU

Но ведь в сторонних приложениях оно как-то работает без рута.

В андроиде есть доступ к сырому USB. Реализовать поверх него usb serial можно. И я пользовался такой библиотекой. Она не слишком хорошо работает, но работает. Думаю, что другие приложения делают так же.

https://developer.android.com/develop/connectivity/usb/host

https://github.com/mik3y/usb-serial-for-android

vbr ★★★★
() автор топика
Последнее исправление: vbr (всего исправлений: 1)
Ответ на: комментарий от vbr

Если девайс отвечает NAK то хост-контроллер поллит его еще раз через какое-то время (определяемое в дескрипторе точки).

Со стороны программного интерфейса хост-контроллера это все выглядит как один запрос на чтение, который не вернет до тех пор, пока девайс не ответит OK.

Minoru ★★★
()
Ответ на: комментарий от vbr

Причём что противно - /dev/ttyACM0 появляется, но доступа (без рута) нет.

$ ls -l /dev/tty{USB*,ACM*}
crw-rw---- 1 root dialout 166, 0 авг 13 16:31 /dev/ttyACM0
crw-rw---- 1 root dialout 166, 1 авг 13 16:31 /dev/ttyACM1
crw-rw---- 1 root dialout 188, 0 июл 31 17:10 /dev/ttyUSB0
crw-rw---- 1 root dialout 188, 1 авг 13 16:28 /dev/ttyUSB1
crw-rw---- 1 root dialout 188, 2 авг 13 16:29 /dev/ttyUSB2
crw-rw---- 1 root dialout 188, 3 авг 13 16:34 /dev/ttyUSB3

как бы ты скорее не в нужной группе (например, dialout).

AlexVR ★★★★★
()
Ответ на: комментарий от vbr

В смысле? В большинстве дистрибутивов, по умолчанию доступ режиться до групп. К USB-UART-ам имеют доступ те, кто в dialout (или т.п.). По аналогии, если хочешь без рутовый wireshark, надо быть в группе wireshark. И т.д. и т.п.. Это не вопрос специально подготовленного устройства. А вопрос доступа обычного пользователя.

AlexVR ★★★★★
()