передача прерываний libusb - PullRequest
4 голосов
/ 25 июня 2011

Мне нужно перепроектировать драйвер для изготовленного на заказ устройства HID USB (некоторые кнопки и светодиоды на панели управления). Драйвер доступен только для Windows, и нам нужна реализация * nix.

Устройство, очевидно, является устройством HID, хотя и не относится к конкретному классу. Он предоставляет два интерфейса каждый с одной конечной точкой прерывания.

Моя настройка в настоящее время включает VirtualBox под управлением Windows на хосте Ubuntu для захвата трафика USB через Wireshark. Протокол довольно прост, и я уже получил довольно хорошее понимание.

Я использую libusb-1.0 в простой консольной программе C ++ для создания прототипов. Мне уже удалось переключить светодиоды, передав передачу управления SET_REPORT, но из-за проблем с нажатием кнопки приема происходит прерывание передачи.

Фактически следующие вызовы блокируются навсегда:

unsigned char bytes[8] = { 0 };
int len = 0;
int ret = libusb_interrupt_transfer(handle, 0x81, bytes, 8, &len, 0); 

При проверке результирующего URB в Wireshark он выглядит точно так же, как и в сеансе Windows. Тем не менее я никогда не получаю ответ от устройства.

Я упал, мне не хватает некоторых настроек. Обратите внимание, что устройство правильно открыто, и оба интерфейса, предоставленные устройством, были успешно востребованы. Ввод отчетов с помощью передачи управления происходит даже в моем приложении linux.

Спасибо за любой указатель! Arne

Приложение I: Мне интересно, как мне указать, какой идентификатор отчета я хочу получать при использовании libusb_interrupt_transfer()?

Приложение II: Сравнивая запросы, сделанные драйвером Windows, с запросом, сгенерированным приведенным выше кодом в Wireshark, я не вижу никакой разницы (те же значения в URB). Но, тем не менее, только после выдачи драйвером Windows передача прерывания возвращается.

При проверке связи с драйвером Windows в Wireshark я не вижу никаких передач управления, кроме различных GET_DESCRIPTOR(...). Самое важное: нет SET_INTERFACE или SET_CONFIGURATION Таким образом, я подозреваю, что проблема связана с библиотекой или с тем, как я ее использую, и не связана с устройством.

Ответы [ 2 ]

1 голос
/ 25 июня 2011

Проблема с кодом, который вы разместили.Синтаксис, который вы написали для определения bytes, не приведет к созданию 8-байтового массива, но вы запрашиваете, чтобы libusb записал 8 байтов в этот адрес, чтобы вы могли получить ошибку или повреждение памяти.Попробуйте вместо этого:

unsigned char buffer[8];
int len = 0;
int ret = libusb_interrupt_transfer(handle, 0x81, buffer, sizeof(buffer), &len, 0);

Каждый отчет HID имеет свою конечную точку, поэтому вы указываете, какой отчет вы хотите получить, указав правильную конечную точку.Вы указали конечную точку 1 IN (0x81).Вы уверены, что конечная точка определена в дескрипторах устройства?Может быть, вы должны получить дескрипторы (с lsusb -v в Ubuntu) и опубликовать их здесь, чтобы мы могли их проверить.

0 голосов
/ 25 мая 2019

У меня была та же проблема, libusb_interrupt_transfer() блокирует навсегда для конечной точки чтения (bEndpoinntAddress: 0x81 EP 1 IN (выход lsusb -v)), но решена.

В моем случае я написал так.

#define ENDPOINT_IN 0x81
unsigned char buffer[8];
int len = 0;
int ret = libusb_interrupt_transfer(handle, ENDPOINT_IN, buffer, sizeof(buffer), &len, 0);

Но моему устройству требуется некоторый код, отправленный перед чтением данных,
и требует размера 64 буфера, хотя lsusb -v вывод bLength равен 7.

#define ENDPOINT_OUT 0x01
#define ENDPOINT_IN 0x81
unsigned char buffer[64] = {0x20, 0x01, 0x03, 0x02, 0x07};
int len = 0;
int send_ret = libusb_interrupt_transfer(handle, ENDPOINT_OUT, buffer, sizeof(buffer), &len, 0);
int recv_ret = libusb_interrupt_transfer(handle, ENDPOINT_IN, buffer, sizeof(buffer), &len, 0);

buffer[64] = {0x20, 0x01, 0x03, 0x02, 0x07} зависит от спецификации устройства.

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

...