У нас есть встроенное устройство на основе CC2531 от TI, которое имеет (помимо управляющего EP0 и ряда конечных точек только для IN) конечную точку, которая одновременно является IN и OUT. Мы заметили разницу в том, как Windows отправляет отчеты OUT и как это делает Linux. На самом деле это довольно долгое время поражало нас, но мы так и не смогли найти объяснения.
Мне кажется, что linux делает это так, как должно быть: отчет OUT передается через конечную точку, которая связана с отчетом HID, как мы получаем его из libusb:
Item | Dev | EP | Status | Speed |Payload
-----------------+-----+----+--------+-------+-------------------------------
OUT transaction | 13 | 4 | ACK | FS | 64 bytes (90 13 00 00 00 00 ..
Windows, с другой стороны, отправляет его через контрольную конечную точку (EP0). Мы используем API настройки, чтобы найти устройство с нужным нам использованием, открыть его для IN и OUT и использовать один и тот же дескриптор файла для чтения и записи. Отчеты EP4 IN хорошо принимаются через этот файловый дескриптор, но запись отчета через тот же файловый дескриптор заканчивается на EP0:
Item | Dev | EP | Status | Speed |Payload
-------------------+-----+----+--------+-------+-------------------------------
Class request OUT | 25 | 0 | OK | FS | 64 bytes (90 13 00 00 00 00 ..
(извините, не могу публиковать изображения (пока). Я скопировал отчеты Ellisys вручную)
Встроенное устройство не проверяет, на каком EP получен отчет OUT (т.е. отчеты SET на EP0 будут выполнять ту же функцию, что и отчеты OUT, найденные на других конечных точках при обработке событий HID), поэтому оно будет реагировать в любом случае.
Мой вопрос: правильны ли оба способа, и если нет, то какой правильный, а какой нет? Может быть, ошибка в наших дескрипторах вызывает такое поведение в Windows?
Для полноты: вот наш дескриптор: http://tny.cz/ac745a8f (удалено из идентификации поставщика на держи моего босса счастливым :))
Увеличение отчета в окнах: (Радость! Теперь я могу делать снимки :))
Вся сделка:
Используемые библиотеки в Windows: hid.lib, hidclass.lib и setupapi.lib. При написании отчета мы используем функции HidP_SetUsageValueArray и HidD_SetOutputReport. PHIDP_PREPARSED_DATA и HIDP_CAPS находятся с функциями HidD_GetAttributes, HidD_GetPreparsedData и HidP_GetCaps. Путь к файлу для устройства находится с помощью SetupDiEnumDeviceInterfaces. Если мы найдем устройство с правильным VID, PID, caps.UsagePage и caps.Usage, то это устройство, которое мы используем.
В Linux это немного сложнее, так как я не тот, кто реализовал код Linux. Я могу сказать, что используется libusb-1.0.9, устройство открывается с помощью libusb_open_device_with_vid_pid, отчеты отправляются с помощью libusb_fill_interrupt_transfer и libusb_submit_transfer. Я вижу, что libuwand_fill_interrupt_transfer принимает конечную точку в качестве параметра, поэтому я думаю, что с помощью только дескриптора из libusb_open_device_with_vid_pid и передачи правильного параметра в качестве конечной точки libusb выяснит, куда поместить отчет.